Browse Source

feat: lint

zhangjie 8 months ago
parent
commit
a73084d673
100 changed files with 15429 additions and 15436 deletions
  1. 1 1
      babel.config.js
  2. 55 55
      src/App.vue
  3. 564 564
      src/api.js
  4. 178 178
      src/components/EchartRender.vue
  5. 111 111
      src/components/ImageViewContain.vue
  6. 7 7
      src/components/PaperCarousel.vue
  7. 325 325
      src/components/SimpleImagePreview.vue
  8. 25 25
      src/components/UploadButton.vue
  9. 1 1
      src/components/ViewFooter.vue
  10. 6 6
      src/components/ViewHeader.vue
  11. 31 31
      src/components/common/ImagePreview/ImagePreview.vue
  12. 4 4
      src/components/common/ImagePreview/move-ele.js
  13. 185 185
      src/components/common/ImportFile/ImportFile.vue
  14. 3 5
      src/components/common/StepsProgress/StepFour.vue
  15. 3 5
      src/components/common/StepsProgress/StepOne.vue
  16. 3 5
      src/components/common/StepsProgress/StepThree.vue
  17. 3 5
      src/components/common/StepsProgress/StepTwo.vue
  18. 12 12
      src/components/common/StepsProgress/StepsProgress.vue
  19. 4 4
      src/components/homeMenuMixins.js
  20. 1 1
      src/config.js
  21. 52 52
      src/constants/authority.js
  22. 154 154
      src/constants/enumerate.js
  23. 21 21
      src/constants/navs.js
  24. 120 120
      src/main.js
  25. 17 17
      src/modules/client-set/ClientAccountSet.vue
  26. 279 279
      src/modules/client-set/ClientParamSet.vue
  27. 5 5
      src/modules/client-set/ClientSet.vue
  28. 16 16
      src/modules/client-set/InspectionAccountSet.vue
  29. 10 10
      src/modules/client-set/components/ModifyClientUser.vue
  30. 636 637
      src/modules/grading-set/GradingLevelSet.vue
  31. 492 492
      src/modules/grading-set/GradingRuleSet.vue
  32. 5 5
      src/modules/grading-set/GradingSet.vue
  33. 6 6
      src/modules/grading-set/UploadPaper.vue
  34. 178 178
      src/modules/grading/Grading.vue
  35. 11 11
      src/modules/grading/GradingAnalysis.vue
  36. 622 622
      src/modules/grading/GradingDetail.vue
  37. 260 260
      src/modules/grading/GradingGroupManage.vue
  38. 30 30
      src/modules/grading/GradingOperation.vue
  39. 343 343
      src/modules/grading/GradingProgress.vue
  40. 364 362
      src/modules/grading/GradingStandardPaperManage.vue
  41. 26 26
      src/modules/grading/GradingUserManage.vue
  42. 7 7
      src/modules/grading/components/CleanGradingDataDialog.vue
  43. 599 598
      src/modules/grading/components/GradeAction.vue
  44. 777 775
      src/modules/grading/components/GradeActionRough.vue
  45. 20 20
      src/modules/grading/components/GradeAnalysis.vue
  46. 11 13
      src/modules/grading/components/GradeAnalysisExport.vue
  47. 10 10
      src/modules/grading/components/GradeFilter.vue
  48. 12 12
      src/modules/grading/components/GradeHistoryPaper.vue
  49. 4 6
      src/modules/grading/components/GradeImageList.vue
  50. 47 47
      src/modules/grading/components/GradeRibbon.vue
  51. 11 11
      src/modules/grading/components/GradeStandardPaper.vue
  52. 84 84
      src/modules/grading/components/GradeStep.vue
  53. 235 231
      src/modules/grading/components/ModifyFormalGradingTask.vue
  54. 27 27
      src/modules/grading/components/ModifyGradingUser.vue
  55. 158 158
      src/modules/grading/components/ModifyLeaderGrading.vue
  56. 160 160
      src/modules/grading/components/ModifyUnformalGradingTask.vue
  57. 328 327
      src/modules/grading/components/NoticeDialog.vue
  58. 6 6
      src/modules/grading/components/ProgressLine.vue
  59. 101 101
      src/modules/grading/components/RibbonSetDialog.vue
  60. 127 129
      src/modules/grading/leader/LeaderAnalysisExport.vue
  61. 766 764
      src/modules/grading/leader/LeaderGrading.vue
  62. 216 218
      src/modules/grading/leader/LeaderProgress.vue
  63. 175 175
      src/modules/grading/leader/LeaderStatistics.vue
  64. 826 824
      src/modules/grading/marker/MarkerGrading.vue
  65. 577 577
      src/modules/grading/marker/MarkerHeader.vue
  66. 192 192
      src/modules/grading/marker/MarkerHistory.vue
  67. 180 180
      src/modules/grading/marker/MarkerImageView.vue
  68. 264 264
      src/modules/grading/marker/MarkerStandard.vue
  69. 105 105
      src/modules/grading/marker/MarkerStatistics.vue
  70. 122 122
      src/modules/grading/marker/store.js
  71. 4 4
      src/modules/inspection/Inspection.vue
  72. 20 20
      src/modules/inspection/InspectionActionLogs.vue
  73. 18 18
      src/modules/inspection/InspectionCollectLogs.vue
  74. 348 348
      src/modules/inspection/InspectionGrading.vue
  75. 2 4
      src/modules/inspection/InspectionScore.vue
  76. 211 211
      src/modules/login/LoginHome.vue
  77. 11 11
      src/modules/login/ResetPwd.vue
  78. 7 7
      src/modules/login/fetchSmsMixins.js
  79. 188 188
      src/modules/main/CheckData.vue
  80. 179 179
      src/modules/main/ClientMonitor.vue
  81. 5 5
      src/modules/main/ExamPaperView.vue
  82. 7 7
      src/modules/main/Main.vue
  83. 376 376
      src/modules/main/PaperManage.vue
  84. 26 26
      src/modules/main/QualityAnalysis.vue
  85. 471 471
      src/modules/main/StudentManage.vue
  86. 330 330
      src/modules/main/StudentScore.vue
  87. 174 174
      src/modules/main/WorkManage.vue
  88. 149 149
      src/modules/main/WorkOverview.vue
  89. 139 139
      src/modules/main/components/CheckDataResult.vue
  90. 163 163
      src/modules/main/components/ImageActionList.vue
  91. 26 26
      src/modules/main/components/ModifyStudent.vue
  92. 18 20
      src/modules/main/components/QualityAnalysisExport.vue
  93. 1 1
      src/modules/main/components/UploadStudentPaper.vue
  94. 8 8
      src/modules/mark-set/ExportPaper.vue
  95. 137 137
      src/modules/mark-set/MarkRuleSet.vue
  96. 5 5
      src/modules/mark-set/MarkSet.vue
  97. 462 462
      src/modules/mark/MarkDetail.vue
  98. 1 1
      src/modules/mark/MarkGroupManage.vue
  99. 135 135
      src/modules/mark/MarkHome.vue
  100. 492 492
      src/modules/mark/MarkOperation.vue

+ 1 - 1
babel.config.js

@@ -1,3 +1,3 @@
 module.exports = {
 module.exports = {
-  presets: ["@vue/cli-plugin-babel/preset"]
+  presets: ["@vue/cli-plugin-babel/preset"],
 };
 };

+ 55 - 55
src/App.vue

@@ -1,55 +1,55 @@
-<template>
-  <div id="app">
-    <router-view />
-  </div>
-</template>
-
-<script>
-import timeMixin from "./plugins/timeMixin";
-
-export default {
-  name: "app",
-  mixins: [timeMixin],
-  data() {
-    return {
-      unactiveTime: 0,
-      // unactiveTime: 10 * 60 * 1000,
-      timeIsOut: false
-    };
-  },
-  computed: {
-    IS_LOGIN() {
-      return this.$route.name === "Login";
-    }
-  },
-  mounted() {
-    if (process.env.NODE_ENV !== "production") return;
-    if (!this.unactiveTime) return;
-    this.registPageAction();
-    document.addEventListener("click", this.registPageAction);
-  },
-  methods: {
-    registPageAction() {
-      // console.log("act event");
-      if (this.timeIsOut) return;
-      // console.log("active");
-      this.timeIsOut = false;
-      this.clearSetTs();
-      this.addSetTime(this.timeOutLogout, this.unactiveTime);
-    },
-    timeOutLogout() {
-      // console.log("trigger time out");
-      if (this.IS_LOGIN) return;
-      this.timeIsOut = true;
-      this.$ls.clear();
-      this.$Modal.info({
-        content: "操作过时,请重新登录!",
-        onOk: () => {
-          this.$router.push({ name: "Login" });
-          this.timeIsOut = false;
-        }
-      });
-    }
-  }
-};
-</script>
+<template>
+  <div id="app">
+    <router-view />
+  </div>
+</template>
+
+<script>
+import timeMixin from "./plugins/timeMixin";
+
+export default {
+  name: "app",
+  mixins: [timeMixin],
+  data() {
+    return {
+      unactiveTime: 0,
+      // unactiveTime: 10 * 60 * 1000,
+      timeIsOut: false,
+    };
+  },
+  computed: {
+    IS_LOGIN() {
+      return this.$route.name === "Login";
+    },
+  },
+  mounted() {
+    if (process.env.NODE_ENV !== "production") return;
+    if (!this.unactiveTime) return;
+    this.registPageAction();
+    document.addEventListener("click", this.registPageAction);
+  },
+  methods: {
+    registPageAction() {
+      // console.log("act event");
+      if (this.timeIsOut) return;
+      // console.log("active");
+      this.timeIsOut = false;
+      this.clearSetTs();
+      this.addSetTime(this.timeOutLogout, this.unactiveTime);
+    },
+    timeOutLogout() {
+      // console.log("trigger time out");
+      if (this.IS_LOGIN) return;
+      this.timeIsOut = true;
+      this.$ls.clear();
+      this.$Modal.info({
+        content: "操作过时,请重新登录!",
+        onOk: () => {
+          this.$router.push({ name: "Login" });
+          this.timeIsOut = false;
+        },
+      });
+    },
+  },
+};
+</script>

+ 564 - 564
src/api.js

@@ -1,564 +1,564 @@
-import { $get, $post, $del, $patch, $put } from "@/plugins/axios";
-
-// login
-export const login = datas => {
-  return $post("/api/login", datas);
-};
-export const logout = () => {
-  return $del("/api/logout");
-};
-export const resetPwd = ({ userId, password }) => {
-  return $patch(`/api/${userId}/password`, { password }, "json");
-};
-
-// work-manage
-export const workList = () => {
-  return $get("/api/admin/works");
-};
-export const workDetail = workId => {
-  return $get(`/api/admin/works/${workId}`);
-};
-export const updateWork = datas => {
-  return $put(`/api/admin/works/${datas.id}`, datas, "json");
-};
-export const createWork = datas => {
-  return $post("/api/admin/works", datas, "json");
-};
-export const activeWork = workId => {
-  return $patch(`/api/admin/works/${workId}`, {});
-};
-export const deleteWork = workId => {
-  return $del(`/api/admin/works/${workId}`);
-};
-
-// work-overview
-export const workOverviewDetail = workId => {
-  return $get(`/api/admin/works/${workId}/overview`);
-};
-
-// paper-manage
-export const paperPageList = datas => {
-  return $get("/api/papers/listByQuestion", datas);
-};
-export const rotatePaper = (imageId, degree) => {
-  return $get(`/api/images/${imageId}/rotate`, { degree });
-};
-export const absentPaper = imageId => {
-  return $post(`/api/score/missing/${imageId}`, {});
-};
-export const markPaper = ({ paperId, isMark, role }) => {
-  return $post(`/api/papers/mark_paper`, { paperId, isMark, role });
-};
-
-// client-monitor
-export const clientMonitorList = datas => {
-  return $get("/api/marklog/equipmentMonitor", datas);
-};
-
-// student-manage
-export const studentPageList = datas => {
-  return $get("/api/students", datas);
-};
-export const updateStudent = datas => {
-  if (datas.id) {
-    return $put(`/api/students/${datas.id}`, datas, "json");
-  } else {
-    return $post(`/api/students`, datas, "json");
-  }
-};
-export const deleteStudent = studentId => {
-  return $del(`/api/students/${studentId}`, {});
-};
-export const areaSchoolRoomCascadeList = workId => {
-  // 考区-学校-考场 联动查询
-  return $get(`/api/students/select/${workId}`);
-};
-
-// client-set -------------------------->
-// client-user-set
-export const clientUserPageList = datas => {
-  return $get("/api/admin/users/collect", datas);
-};
-export const clientUserQuery = workId => {
-  return $get("/api/admin/users/collect/all", { workId });
-};
-export const updateClientUser = datas => {
-  if (datas.id) {
-    return $put(`/api/admin/users/collect/${datas.id}`, datas, "json");
-  } else {
-    return $post("/api/admin/users/collect", datas, "json");
-  }
-};
-export const deleteClientUser = userId => {
-  return $del(`/api/admin/users/collect/${userId}`, {});
-};
-// inspection-user-set
-export const inspectionUserPageList = () => {
-  return $get("/api/admin/users/inspection");
-};
-export const deleteInspectionUser = userId => {
-  return $del(`/api/admin/users/collect/${userId}`, {});
-};
-// client-param-set -------------------------->
-// subject-set
-export const subjectList = workId => {
-  return $get(`/api/marksubjects/${workId}/subjects`);
-};
-export const subjectDetail = subjectId => {
-  return $get(`/api/marksubjects/${subjectId}`);
-};
-export const updateSubject = datas => {
-  if (datas.id) {
-    return $post(`/api/marksubjects/${datas.id}/updateName`, datas);
-  } else {
-    return $post(`/api/marksubjects/${datas.id}`, datas);
-  }
-};
-export const enableSubject = subjectId => {
-  return $post(`/api/marksubjects/${subjectId}/updateEnable`, {});
-};
-// param-set
-export const getParamsSet = async workId => {
-  const data = await $get("/api/param/getParam", { workId });
-  let result = {};
-  const keys = [
-    "collectConfig",
-    "levelConfig",
-    "roughLevelConfig",
-    "scoreConfig"
-  ];
-  keys.forEach(key => {
-    result[key] = data[key] ? JSON.parse(data[key]) : {};
-  });
-  return result;
-};
-export const updateCollectParams = datas => {
-  return $post("/api/param/collect", datas, "json");
-};
-
-// grading-set -------------------------->
-// grading-level-set
-// TO workDetail and updateWork
-
-// grading-rule-set
-export const updateLevelParams = datas => {
-  return $post("/api/param/level", datas, "json");
-};
-export const updateRoughLevelParams = datas => {
-  return $post("/api/param/rough_level", datas, "json");
-};
-// update-paper
-// grading-rule-set
-
-// mark-set -------------------------->
-// mark-rule-set
-export const updateScoreParams = datas => {
-  return $post("/api/param/score", datas, "json");
-};
-// export-paper
-export const exportScorePictures = datas => {
-  return $get("/api/file/image/exportScorePictures", datas);
-};
-export const exportDecryptPictures = datas => {
-  return $get("/api/file/image/exportDecryptPictures", datas);
-};
-
-// quality-analysis -------------------------->
-// 档位占比
-export const levelsPropReport = datas => {
-  return $get("/api/quality/levelsPropReport", datas);
-};
-// 累计偏差(差值和)
-export const deviationReport = datas => {
-  return $get("/api/quality/deviationReport", datas);
-};
-// 累计误差(差值绝对值之和)
-export const distanceReport = datas => {
-  return $get("/api/quality/distanceReport", datas);
-};
-// 打回次数
-export const callbackReport = datas => {
-  return $get("/api/quality/callbackReport", datas);
-};
-// 自查卷
-export const selfCheckReport = datas => {
-  return $get("/api/quality/selfReport", datas);
-};
-
-// student-score -------------------------->
-export const studentScoreList = datas => {
-  return $get(`/api/papers/studentScore`, datas);
-};
-// exam-paper-view
-export const uploadPaperList = workId => {
-  return $get(`/api/papers/${workId}/listUploadPaper`);
-};
-
-// check-data
-export const checkDataList = workId => {
-  return $get(`/api/check_data/list`, { workId });
-};
-export const dataItemCheck = ({ workId, checkItem, paramValue }) => {
-  return $post(`/api/check_data/check`, { workId, checkItem, paramValue });
-};
-export const checkDataDetailList = datas => {
-  return $get(`/api/check_data/page_error`, datas);
-};
-// grading -------------------------->
-// grading-user-manage
-export const gradingUserList = datas => {
-  return $get("/api/admin/users", datas);
-};
-export const updateGradingUser = datas => {
-  if (datas.id) {
-    return $put(`/api/admin/users/${datas.id}`, datas, "json");
-  } else {
-    return $post("/api/admin/users", datas, "json");
-  }
-};
-export const deleteGradingUser = userId => {
-  return $del(`/api/admin/users/${userId}`);
-};
-// grading-group-manage
-export const gradingGroupList = subjectId => {
-  return $get(`/api/marksubjects/${subjectId}/markergroups`, {});
-};
-export const updateGradingGroup = (subjectId, datas) => {
-  if (datas.groupId) {
-    return $patch(
-      `/api/marksubjects/${subjectId}/markergroups/${datas.groupId}`,
-      datas,
-      "json"
-    );
-  } else {
-    return $post(`/api/marksubjects/${subjectId}/markergroups`, datas, "json");
-  }
-};
-export const deleteGradingGroup = (subjectId, groupId) => {
-  return $del(`/api/marksubjects/${subjectId}/markergroups/${groupId}`);
-};
-export const deleteGradeGroupStudent = (subject, groupId) => {
-  return $del(`/api/marksubjects/marker_groups_student/${subject}/${groupId}`);
-};
-export const markUserList = ({ workId, subjectId }) => {
-  return $get("/api/markers", { workId, subject: subjectId });
-};
-export const userGroupList = datas => {
-  // workId=&subject=&stage=  stage非必填
-  return $get("/api/admin/users/list_group", datas);
-};
-export const leaderMarkUserList = datas => {
-  // workId=&subject=&stage=&markerId=
-  return $get("/api/admin/users/list_group_users", datas);
-};
-// grading-progress
-export const gradingProgressDetail = ({ workId, subject }) => {
-  return $get("/api/markers/stat/progress", { workId, subject });
-};
-export const markLeaderGradingProgressDetail = ({ workId, subject }) => {
-  return $get("/api/markers/mark_leader/stat/progress", { workId, subject });
-};
-export const areaStatProgress = subjectId => {
-  return $get(`/api/marksubjects/${subjectId}/areaProgress`);
-};
-export const createTryGradingTask = datas => {
-  // workId, subject
-  return $get(`/api/trial/startTrial`, datas);
-};
-export const finishTryGradingTask = datas => {
-  // workId, subject
-  return $get(`/api/trial/finishTrial`, datas);
-};
-export const cleanGradingData = datas => {
-  // workId, subject,stage,,loginName,password
-  return $post(`/api/markers/subject/reset`, datas);
-};
-// grade-task
-export const checkMissionStatus = ({ workId, subject }) => {
-  return $get("/api/trial/checkMissionStatus", { workId, subject });
-};
-export const checkCanPublishTask = subjectId => {
-  return $get(`/api/marksubjects/${subjectId}/canLevel`);
-};
-// 分档任务发布
-export const createGradingTask = ({ subjectId, taskCount, questionId }) => {
-  return $patch(
-    `/api/marksubjects/${subjectId}`,
-    {
-      taskCount,
-      questionId
-    },
-    "json"
-  );
-};
-// 进入打分阶段,和上面掉的同一个接口,分开是为了便于区分
-export const gotoNextStage = ({ workId, subject }) => {
-  return $post(`/api/marksubjects/go_next_stage`, { workId, subject });
-};
-// 打分任务发布
-export const publishScoreTask = ({ subjectId, questionId, taskList }) => {
-  return $post(
-    `/api/marksubjects/${subjectId}/publishScore`,
-    {
-      questionId,
-      taskList
-    },
-    "json"
-  );
-};
-// grading-standard-paper-manage
-export const cancelStandardPaper = ({ paperIds, stage }) => {
-  return $patch(`/api/papers/batch/cancelSample`, { paperIds, stage }, "json");
-};
-
-// grading-detail ------------------------->
-// grading-analysis
-export const gradingStatData = datas => {
-  return $get("/api/marktasks/levelStatDetail", datas);
-};
-
-// level relate
-export const workLevelList = async (workId, stage = "LEVEL") => {
-  const data = await $get(`/api/admin/works/${workId}/levels`);
-  if (stage === "ROUGH_LEVEL") {
-    const levelMap = {};
-    data.forEach(item => {
-      const ind = item.roughCode;
-      if (!levelMap[ind]) levelMap[ind] = [];
-      levelMap[ind].push(item);
-    });
-    let levelList = Object.keys(levelMap).map((roughCode, ind) => {
-      const group = levelMap[roughCode];
-      const levels = group.map(item => item.code);
-      const minSs = group.map(item => item.minScore);
-      const maxSs = group.map(item => item.maxScore);
-
-      return {
-        id: ind + 1,
-        name: roughCode,
-        minScore: levels[0],
-        maxScore: levels.slice(-1)[0],
-        minSubScore: Math.min.apply(null, minSs),
-        maxSubScore: Math.max.apply(null, maxSs)
-      };
-    });
-    levelList.sort((a, b) => (a.name < b.name ? -1 : 1));
-    return levelList;
-  } else {
-    return data.map(item => {
-      return {
-        ...item,
-        name: item.code
-      };
-    });
-  }
-};
-export const levelStatData = (subjectId, questionId) => {
-  return $get(`/api/marksubjects/${subjectId}/stat/levels`, { questionId });
-};
-export const scoreStatData = (subjectId, questionId) => {
-  return $get(`/api/marksubjects/${subjectId}/stat/scores`, { questionId });
-};
-export const markLeaderLevelStatData = (
-  subjectId,
-  questionId,
-  stage = "LEVEL"
-) => {
-  if (stage === "LEVEL") {
-    return $get(`/api/marksubjects/${subjectId}/mark_leader/stat/levels`, {
-      questionId
-    });
-  } else {
-    return $get(`/api/marksubjects/${subjectId}/mark_leader/stat/roughLevels`, {
-      questionId
-    });
-  }
-};
-export const markLeaderScoreStatData = (subjectId, questionId) => {
-  return $get(`/api/marksubjects/${subjectId}/mark_leader/stat/scores`, {
-    questionId
-  });
-};
-export const markerLevelStatData = (userId, questionId) => {
-  return $get(`/api/markers/${userId}/stat/levels`, { questionId });
-};
-export const markerLevelTotalStatData = (
-  userId,
-  questionId,
-  stage = "LEVEL"
-) => {
-  if (stage === "LEVEL") {
-    return $get(`/api/markers/${userId}/stat/totalLevels`, { questionId });
-  } else {
-    return $get(`/api/markers/${userId}/stat/totalRoughLevels`, { questionId });
-  }
-};
-
-// area
-export const areaList = ({ workId, subject }) => {
-  return $get("/api/questions", { workId, subject });
-};
-export const sampleAreaList = ({ workId, subject }) => {
-  return $get("/api/questions/sampleQuestions", { workId, subject });
-};
-// papers
-export const paperList = datas => {
-  // ?questionId=64&level=A&page=0&size=6&sort=secretNumber&isSample=true
-  return $get("/api/papers", datas);
-};
-export const markerTaskList = datas => {
-  // ?stage=LEVEL&markerId=49&size=6&page=0&sort=updatedOn,desc&questionId=73&isSample=false&level=C
-  return $get("/api/marktasks", datas);
-};
-export const markTaskPaperList = datas => {
-  // ?workId=&stage=&subject=&markerId=
-  return $get("/api/marktasks/list_mark_task", datas);
-};
-export const markerSelfCheckTask = ({ workId, markerId, subject, stage }) => {
-  // stage => LEVEL or SCORE
-  return $get(`/api/marktasks/getSelfCheckTask`, {
-    workId,
-    markerId,
-    subject,
-    stage
-  });
-};
-export const markerSelfCheckLevel = (id, level) => {
-  return $post(
-    `/api/marktasks/markingSelfCheckTask?id=${id}&level=${level}`,
-    {}
-  );
-};
-
-// grading or scoring
-export const paperSelectLevelOrScore = (taskId, result, stage) => {
-  // stage => LEVEL or SCORE
-  return $patch(`/api/marktasks/${taskId}`, { stage, result }, "json");
-};
-export const paperSelectLevelBatch = (taskIds, result, stage) => {
-  return $patch(`/api/marktasks/batch`, { taskIds, result, stage }, "json");
-};
-export const paperTaskPass = (stage, taskId) => {
-  return $post(`/api/marktasks/${stage}/${taskId}/skip`, {});
-};
-export const markTask = ({ markTaskId, stage, isMark }) => {
-  return $post(`/api/marktasks/${stage}/mark_task`, { markTaskId, isMark });
-};
-// grade or mark history
-export const markHistoryList = (paperId, stage) => {
-  return $get(`/api/papers/${paperId}/marktasks`, { stage });
-};
-// marker-status-info
-export const markerDetail = userId => {
-  return $get(`/api/markers/${userId}`);
-};
-// leader mark paper
-export const leaderGradingPaper = datas => {
-  // datas:{value: ,level:,range?, paperIds: '1,2'}
-  return $patch(`/api/papers/batch`, datas, "json");
-  // return $patch(`/api/papers/${paperId}`, datas, "json");
-};
-// review action history
-export const actionHistory = datas => {
-  return $get("/api/marktasks/reviewPaper", datas);
-};
-export const actionLeaderHistory = datas => {
-  return $get("/api/marktasks/kzzReviewPaper", datas);
-};
-// sn search
-export const taskSnSearch = (type, code, questionId, stage) => {
-  if (type === "task") {
-    return $get(`/api/papers/search/byTaskSecretNumber`, {
-      sn: code,
-      questionId,
-      stage
-    });
-  } else {
-    const paramName = type === "examNumber" ? "examNumber" : "sn";
-    return $get(`/api/papers/one`, { [paramName]: code, questionId, stage });
-  }
-};
-// mark step change level
-export const markStepChangeLevel = ({ subjectId, paperId, level, userId }) => {
-  // paperId,level
-  return $post(`/api/changelevel/${subjectId}/changeLevel`, {
-    paperId,
-    level,
-    userId
-  });
-};
-export const changeLevelPaperList = datas => {
-  // 纪检人员、超级管理员和科组长查询改档列表
-  // status => 0:未审核,1:已审核
-  // 科组长默认查询审核通过的
-  return $get("/api/changelevel/list", datas);
-};
-
-// mark -------------------------->
-// mark-progress
-// to see grading progress
-
-// mark-task-manage
-export const checkMarkTaskSubmitType = subjectId => {
-  return $get(`/api/marksubjects/${subjectId}/canScoreAll`);
-};
-export const checkMarkTaskCanSubmit = (subjectId, questionId) => {
-  let datas = questionId ? { questionId } : null;
-  return $get(`/api/marksubjects/${subjectId}/canScore`, datas);
-};
-export const markTaskInfo = (subjectId, questionId) => {
-  let datas = questionId ? { questionId } : null;
-  return $get(`/api/marksubjects/${subjectId}/scoreProgress`, datas);
-};
-// mark-detail
-export const markerScoreStatData = (userId, questionId) => {
-  return $get(`/api/markers/${userId}/stat/scores`, { questionId });
-};
-export const markerScoreTotalStatData = (userId, questionId) => {
-  return $get(`/api/markers/${userId}/stat/totalScores`, { questionId });
-};
-// mark-operation
-export const markerChangeLevelPaperList = datas => {
-  // ?markerId=49&size=6&page=0&isShift=true&isShiftScore=false&questionId=10
-  return $get(`/api/marktasks/shift`, datas);
-};
-export const markerMarkPaperList = datas => {
-  // ?markerId=15&questionId=2&subject=SC&workId=25&stage=&page=0&size=12
-  return $get(`/api/marktasks/markedPapers`, datas);
-};
-
-// inspection -------------------------->
-// inspection-log
-export const inspectionActionLogPageList = datas => {
-  return $get(`/api/marklog/selectMarkLog`, datas);
-};
-export const inspectionCollectLogPageList = datas => {
-  return $get(`/api/marklog/selectCollectMarkLog`, datas);
-};
-export const inspectionConfirmCheckGrade = datas => {
-  // id,auditStatus
-  return $post(`/api/changelevel/changeLevelAudit`, datas);
-};
-export const logTypeList = () => {
-  return $get(`/api/marklog/listTypes`);
-};
-
-// notice -------------------------->
-export const userSendNoticeList = datas => {
-  // subject=&stage=&sendUserId=
-  return $get(`/api/message/page_send`, datas);
-};
-export const userReceiveNoticeList = datas => {
-  // subject=&stage=&receiveUserId=&lastId=
-  return $get(`/api/message/page_receive`, datas);
-};
-export const fetchReleaseUnreadNotice = datas => {
-  // subject=&stage=&receiveUserId=
-  return $get(`/api/message/list_receive_unread`, datas, { hideLoad: true });
-};
-export const readNotice = ids => {
-  return $post(`/api/message/read`, { ids }, "json");
-};
-export const sendNotice = datas => {
-  return $post(`/api/message/send`, datas, "json");
-};
+import { $get, $post, $del, $patch, $put } from "@/plugins/axios";
+
+// login
+export const login = (datas) => {
+  return $post("/api/login", datas);
+};
+export const logout = () => {
+  return $del("/api/logout");
+};
+export const resetPwd = ({ userId, password }) => {
+  return $patch(`/api/${userId}/password`, { password }, "json");
+};
+
+// work-manage
+export const workList = () => {
+  return $get("/api/admin/works");
+};
+export const workDetail = (workId) => {
+  return $get(`/api/admin/works/${workId}`);
+};
+export const updateWork = (datas) => {
+  return $put(`/api/admin/works/${datas.id}`, datas, "json");
+};
+export const createWork = (datas) => {
+  return $post("/api/admin/works", datas, "json");
+};
+export const activeWork = (workId) => {
+  return $patch(`/api/admin/works/${workId}`, {});
+};
+export const deleteWork = (workId) => {
+  return $del(`/api/admin/works/${workId}`);
+};
+
+// work-overview
+export const workOverviewDetail = (workId) => {
+  return $get(`/api/admin/works/${workId}/overview`);
+};
+
+// paper-manage
+export const paperPageList = (datas) => {
+  return $get("/api/papers/listByQuestion", datas);
+};
+export const rotatePaper = (imageId, degree) => {
+  return $get(`/api/images/${imageId}/rotate`, { degree });
+};
+export const absentPaper = (imageId) => {
+  return $post(`/api/score/missing/${imageId}`, {});
+};
+export const markPaper = ({ paperId, isMark, role }) => {
+  return $post(`/api/papers/mark_paper`, { paperId, isMark, role });
+};
+
+// client-monitor
+export const clientMonitorList = (datas) => {
+  return $get("/api/marklog/equipmentMonitor", datas);
+};
+
+// student-manage
+export const studentPageList = (datas) => {
+  return $get("/api/students", datas);
+};
+export const updateStudent = (datas) => {
+  if (datas.id) {
+    return $put(`/api/students/${datas.id}`, datas, "json");
+  } else {
+    return $post(`/api/students`, datas, "json");
+  }
+};
+export const deleteStudent = (studentId) => {
+  return $del(`/api/students/${studentId}`, {});
+};
+export const areaSchoolRoomCascadeList = (workId) => {
+  // 考区-学校-考场 联动查询
+  return $get(`/api/students/select/${workId}`);
+};
+
+// client-set -------------------------->
+// client-user-set
+export const clientUserPageList = (datas) => {
+  return $get("/api/admin/users/collect", datas);
+};
+export const clientUserQuery = (workId) => {
+  return $get("/api/admin/users/collect/all", { workId });
+};
+export const updateClientUser = (datas) => {
+  if (datas.id) {
+    return $put(`/api/admin/users/collect/${datas.id}`, datas, "json");
+  } else {
+    return $post("/api/admin/users/collect", datas, "json");
+  }
+};
+export const deleteClientUser = (userId) => {
+  return $del(`/api/admin/users/collect/${userId}`, {});
+};
+// inspection-user-set
+export const inspectionUserPageList = () => {
+  return $get("/api/admin/users/inspection");
+};
+export const deleteInspectionUser = (userId) => {
+  return $del(`/api/admin/users/collect/${userId}`, {});
+};
+// client-param-set -------------------------->
+// subject-set
+export const subjectList = (workId) => {
+  return $get(`/api/marksubjects/${workId}/subjects`);
+};
+export const subjectDetail = (subjectId) => {
+  return $get(`/api/marksubjects/${subjectId}`);
+};
+export const updateSubject = (datas) => {
+  if (datas.id) {
+    return $post(`/api/marksubjects/${datas.id}/updateName`, datas);
+  } else {
+    return $post(`/api/marksubjects/${datas.id}`, datas);
+  }
+};
+export const enableSubject = (subjectId) => {
+  return $post(`/api/marksubjects/${subjectId}/updateEnable`, {});
+};
+// param-set
+export const getParamsSet = async (workId) => {
+  const data = await $get("/api/param/getParam", { workId });
+  let result = {};
+  const keys = [
+    "collectConfig",
+    "levelConfig",
+    "roughLevelConfig",
+    "scoreConfig",
+  ];
+  keys.forEach((key) => {
+    result[key] = data[key] ? JSON.parse(data[key]) : {};
+  });
+  return result;
+};
+export const updateCollectParams = (datas) => {
+  return $post("/api/param/collect", datas, "json");
+};
+
+// grading-set -------------------------->
+// grading-level-set
+// TO workDetail and updateWork
+
+// grading-rule-set
+export const updateLevelParams = (datas) => {
+  return $post("/api/param/level", datas, "json");
+};
+export const updateRoughLevelParams = (datas) => {
+  return $post("/api/param/rough_level", datas, "json");
+};
+// update-paper
+// grading-rule-set
+
+// mark-set -------------------------->
+// mark-rule-set
+export const updateScoreParams = (datas) => {
+  return $post("/api/param/score", datas, "json");
+};
+// export-paper
+export const exportScorePictures = (datas) => {
+  return $get("/api/file/image/exportScorePictures", datas);
+};
+export const exportDecryptPictures = (datas) => {
+  return $get("/api/file/image/exportDecryptPictures", datas);
+};
+
+// quality-analysis -------------------------->
+// 档位占比
+export const levelsPropReport = (datas) => {
+  return $get("/api/quality/levelsPropReport", datas);
+};
+// 累计偏差(差值和)
+export const deviationReport = (datas) => {
+  return $get("/api/quality/deviationReport", datas);
+};
+// 累计误差(差值绝对值之和)
+export const distanceReport = (datas) => {
+  return $get("/api/quality/distanceReport", datas);
+};
+// 打回次数
+export const callbackReport = (datas) => {
+  return $get("/api/quality/callbackReport", datas);
+};
+// 自查卷
+export const selfCheckReport = (datas) => {
+  return $get("/api/quality/selfReport", datas);
+};
+
+// student-score -------------------------->
+export const studentScoreList = (datas) => {
+  return $get(`/api/papers/studentScore`, datas);
+};
+// exam-paper-view
+export const uploadPaperList = (workId) => {
+  return $get(`/api/papers/${workId}/listUploadPaper`);
+};
+
+// check-data
+export const checkDataList = (workId) => {
+  return $get(`/api/check_data/list`, { workId });
+};
+export const dataItemCheck = ({ workId, checkItem, paramValue }) => {
+  return $post(`/api/check_data/check`, { workId, checkItem, paramValue });
+};
+export const checkDataDetailList = (datas) => {
+  return $get(`/api/check_data/page_error`, datas);
+};
+// grading -------------------------->
+// grading-user-manage
+export const gradingUserList = (datas) => {
+  return $get("/api/admin/users", datas);
+};
+export const updateGradingUser = (datas) => {
+  if (datas.id) {
+    return $put(`/api/admin/users/${datas.id}`, datas, "json");
+  } else {
+    return $post("/api/admin/users", datas, "json");
+  }
+};
+export const deleteGradingUser = (userId) => {
+  return $del(`/api/admin/users/${userId}`);
+};
+// grading-group-manage
+export const gradingGroupList = (subjectId) => {
+  return $get(`/api/marksubjects/${subjectId}/markergroups`, {});
+};
+export const updateGradingGroup = (subjectId, datas) => {
+  if (datas.groupId) {
+    return $patch(
+      `/api/marksubjects/${subjectId}/markergroups/${datas.groupId}`,
+      datas,
+      "json"
+    );
+  } else {
+    return $post(`/api/marksubjects/${subjectId}/markergroups`, datas, "json");
+  }
+};
+export const deleteGradingGroup = (subjectId, groupId) => {
+  return $del(`/api/marksubjects/${subjectId}/markergroups/${groupId}`);
+};
+export const deleteGradeGroupStudent = (subject, groupId) => {
+  return $del(`/api/marksubjects/marker_groups_student/${subject}/${groupId}`);
+};
+export const markUserList = ({ workId, subjectId }) => {
+  return $get("/api/markers", { workId, subject: subjectId });
+};
+export const userGroupList = (datas) => {
+  // workId=&subject=&stage=  stage非必填
+  return $get("/api/admin/users/list_group", datas);
+};
+export const leaderMarkUserList = (datas) => {
+  // workId=&subject=&stage=&markerId=
+  return $get("/api/admin/users/list_group_users", datas);
+};
+// grading-progress
+export const gradingProgressDetail = ({ workId, subject }) => {
+  return $get("/api/markers/stat/progress", { workId, subject });
+};
+export const markLeaderGradingProgressDetail = ({ workId, subject }) => {
+  return $get("/api/markers/mark_leader/stat/progress", { workId, subject });
+};
+export const areaStatProgress = (subjectId) => {
+  return $get(`/api/marksubjects/${subjectId}/areaProgress`);
+};
+export const createTryGradingTask = (datas) => {
+  // workId, subject
+  return $get(`/api/trial/startTrial`, datas);
+};
+export const finishTryGradingTask = (datas) => {
+  // workId, subject
+  return $get(`/api/trial/finishTrial`, datas);
+};
+export const cleanGradingData = (datas) => {
+  // workId, subject,stage,,loginName,password
+  return $post(`/api/markers/subject/reset`, datas);
+};
+// grade-task
+export const checkMissionStatus = ({ workId, subject }) => {
+  return $get("/api/trial/checkMissionStatus", { workId, subject });
+};
+export const checkCanPublishTask = (subjectId) => {
+  return $get(`/api/marksubjects/${subjectId}/canLevel`);
+};
+// 分档任务发布
+export const createGradingTask = ({ subjectId, taskCount, questionId }) => {
+  return $patch(
+    `/api/marksubjects/${subjectId}`,
+    {
+      taskCount,
+      questionId,
+    },
+    "json"
+  );
+};
+// 进入打分阶段,和上面掉的同一个接口,分开是为了便于区分
+export const gotoNextStage = ({ workId, subject }) => {
+  return $post(`/api/marksubjects/go_next_stage`, { workId, subject });
+};
+// 打分任务发布
+export const publishScoreTask = ({ subjectId, questionId, taskList }) => {
+  return $post(
+    `/api/marksubjects/${subjectId}/publishScore`,
+    {
+      questionId,
+      taskList,
+    },
+    "json"
+  );
+};
+// grading-standard-paper-manage
+export const cancelStandardPaper = ({ paperIds, stage }) => {
+  return $patch(`/api/papers/batch/cancelSample`, { paperIds, stage }, "json");
+};
+
+// grading-detail ------------------------->
+// grading-analysis
+export const gradingStatData = (datas) => {
+  return $get("/api/marktasks/levelStatDetail", datas);
+};
+
+// level relate
+export const workLevelList = async (workId, stage = "LEVEL") => {
+  const data = await $get(`/api/admin/works/${workId}/levels`);
+  if (stage === "ROUGH_LEVEL") {
+    const levelMap = {};
+    data.forEach((item) => {
+      const ind = item.roughCode;
+      if (!levelMap[ind]) levelMap[ind] = [];
+      levelMap[ind].push(item);
+    });
+    let levelList = Object.keys(levelMap).map((roughCode, ind) => {
+      const group = levelMap[roughCode];
+      const levels = group.map((item) => item.code);
+      const minSs = group.map((item) => item.minScore);
+      const maxSs = group.map((item) => item.maxScore);
+
+      return {
+        id: ind + 1,
+        name: roughCode,
+        minScore: levels[0],
+        maxScore: levels.slice(-1)[0],
+        minSubScore: Math.min.apply(null, minSs),
+        maxSubScore: Math.max.apply(null, maxSs),
+      };
+    });
+    levelList.sort((a, b) => (a.name < b.name ? -1 : 1));
+    return levelList;
+  } else {
+    return data.map((item) => {
+      return {
+        ...item,
+        name: item.code,
+      };
+    });
+  }
+};
+export const levelStatData = (subjectId, questionId) => {
+  return $get(`/api/marksubjects/${subjectId}/stat/levels`, { questionId });
+};
+export const scoreStatData = (subjectId, questionId) => {
+  return $get(`/api/marksubjects/${subjectId}/stat/scores`, { questionId });
+};
+export const markLeaderLevelStatData = (
+  subjectId,
+  questionId,
+  stage = "LEVEL"
+) => {
+  if (stage === "LEVEL") {
+    return $get(`/api/marksubjects/${subjectId}/mark_leader/stat/levels`, {
+      questionId,
+    });
+  } else {
+    return $get(`/api/marksubjects/${subjectId}/mark_leader/stat/roughLevels`, {
+      questionId,
+    });
+  }
+};
+export const markLeaderScoreStatData = (subjectId, questionId) => {
+  return $get(`/api/marksubjects/${subjectId}/mark_leader/stat/scores`, {
+    questionId,
+  });
+};
+export const markerLevelStatData = (userId, questionId) => {
+  return $get(`/api/markers/${userId}/stat/levels`, { questionId });
+};
+export const markerLevelTotalStatData = (
+  userId,
+  questionId,
+  stage = "LEVEL"
+) => {
+  if (stage === "LEVEL") {
+    return $get(`/api/markers/${userId}/stat/totalLevels`, { questionId });
+  } else {
+    return $get(`/api/markers/${userId}/stat/totalRoughLevels`, { questionId });
+  }
+};
+
+// area
+export const areaList = ({ workId, subject }) => {
+  return $get("/api/questions", { workId, subject });
+};
+export const sampleAreaList = ({ workId, subject }) => {
+  return $get("/api/questions/sampleQuestions", { workId, subject });
+};
+// papers
+export const paperList = (datas) => {
+  // ?questionId=64&level=A&page=0&size=6&sort=secretNumber&isSample=true
+  return $get("/api/papers", datas);
+};
+export const markerTaskList = (datas) => {
+  // ?stage=LEVEL&markerId=49&size=6&page=0&sort=updatedOn,desc&questionId=73&isSample=false&level=C
+  return $get("/api/marktasks", datas);
+};
+export const markTaskPaperList = (datas) => {
+  // ?workId=&stage=&subject=&markerId=
+  return $get("/api/marktasks/list_mark_task", datas);
+};
+export const markerSelfCheckTask = ({ workId, markerId, subject, stage }) => {
+  // stage => LEVEL or SCORE
+  return $get(`/api/marktasks/getSelfCheckTask`, {
+    workId,
+    markerId,
+    subject,
+    stage,
+  });
+};
+export const markerSelfCheckLevel = (id, level) => {
+  return $post(
+    `/api/marktasks/markingSelfCheckTask?id=${id}&level=${level}`,
+    {}
+  );
+};
+
+// grading or scoring
+export const paperSelectLevelOrScore = (taskId, result, stage) => {
+  // stage => LEVEL or SCORE
+  return $patch(`/api/marktasks/${taskId}`, { stage, result }, "json");
+};
+export const paperSelectLevelBatch = (taskIds, result, stage) => {
+  return $patch(`/api/marktasks/batch`, { taskIds, result, stage }, "json");
+};
+export const paperTaskPass = (stage, taskId) => {
+  return $post(`/api/marktasks/${stage}/${taskId}/skip`, {});
+};
+export const markTask = ({ markTaskId, stage, isMark }) => {
+  return $post(`/api/marktasks/${stage}/mark_task`, { markTaskId, isMark });
+};
+// grade or mark history
+export const markHistoryList = (paperId, stage) => {
+  return $get(`/api/papers/${paperId}/marktasks`, { stage });
+};
+// marker-status-info
+export const markerDetail = (userId) => {
+  return $get(`/api/markers/${userId}`);
+};
+// leader mark paper
+export const leaderGradingPaper = (datas) => {
+  // datas:{value: ,level:,range?, paperIds: '1,2'}
+  return $patch(`/api/papers/batch`, datas, "json");
+  // return $patch(`/api/papers/${paperId}`, datas, "json");
+};
+// review action history
+export const actionHistory = (datas) => {
+  return $get("/api/marktasks/reviewPaper", datas);
+};
+export const actionLeaderHistory = (datas) => {
+  return $get("/api/marktasks/kzzReviewPaper", datas);
+};
+// sn search
+export const taskSnSearch = (type, code, questionId, stage) => {
+  if (type === "task") {
+    return $get(`/api/papers/search/byTaskSecretNumber`, {
+      sn: code,
+      questionId,
+      stage,
+    });
+  } else {
+    const paramName = type === "examNumber" ? "examNumber" : "sn";
+    return $get(`/api/papers/one`, { [paramName]: code, questionId, stage });
+  }
+};
+// mark step change level
+export const markStepChangeLevel = ({ subjectId, paperId, level, userId }) => {
+  // paperId,level
+  return $post(`/api/changelevel/${subjectId}/changeLevel`, {
+    paperId,
+    level,
+    userId,
+  });
+};
+export const changeLevelPaperList = (datas) => {
+  // 纪检人员、超级管理员和科组长查询改档列表
+  // status => 0:未审核,1:已审核
+  // 科组长默认查询审核通过的
+  return $get("/api/changelevel/list", datas);
+};
+
+// mark -------------------------->
+// mark-progress
+// to see grading progress
+
+// mark-task-manage
+export const checkMarkTaskSubmitType = (subjectId) => {
+  return $get(`/api/marksubjects/${subjectId}/canScoreAll`);
+};
+export const checkMarkTaskCanSubmit = (subjectId, questionId) => {
+  let datas = questionId ? { questionId } : null;
+  return $get(`/api/marksubjects/${subjectId}/canScore`, datas);
+};
+export const markTaskInfo = (subjectId, questionId) => {
+  let datas = questionId ? { questionId } : null;
+  return $get(`/api/marksubjects/${subjectId}/scoreProgress`, datas);
+};
+// mark-detail
+export const markerScoreStatData = (userId, questionId) => {
+  return $get(`/api/markers/${userId}/stat/scores`, { questionId });
+};
+export const markerScoreTotalStatData = (userId, questionId) => {
+  return $get(`/api/markers/${userId}/stat/totalScores`, { questionId });
+};
+// mark-operation
+export const markerChangeLevelPaperList = (datas) => {
+  // ?markerId=49&size=6&page=0&isShift=true&isShiftScore=false&questionId=10
+  return $get(`/api/marktasks/shift`, datas);
+};
+export const markerMarkPaperList = (datas) => {
+  // ?markerId=15&questionId=2&subject=SC&workId=25&stage=&page=0&size=12
+  return $get(`/api/marktasks/markedPapers`, datas);
+};
+
+// inspection -------------------------->
+// inspection-log
+export const inspectionActionLogPageList = (datas) => {
+  return $get(`/api/marklog/selectMarkLog`, datas);
+};
+export const inspectionCollectLogPageList = (datas) => {
+  return $get(`/api/marklog/selectCollectMarkLog`, datas);
+};
+export const inspectionConfirmCheckGrade = (datas) => {
+  // id,auditStatus
+  return $post(`/api/changelevel/changeLevelAudit`, datas);
+};
+export const logTypeList = () => {
+  return $get(`/api/marklog/listTypes`);
+};
+
+// notice -------------------------->
+export const userSendNoticeList = (datas) => {
+  // subject=&stage=&sendUserId=
+  return $get(`/api/message/page_send`, datas);
+};
+export const userReceiveNoticeList = (datas) => {
+  // subject=&stage=&receiveUserId=&lastId=
+  return $get(`/api/message/page_receive`, datas);
+};
+export const fetchReleaseUnreadNotice = (datas) => {
+  // subject=&stage=&receiveUserId=
+  return $get(`/api/message/list_receive_unread`, datas, { hideLoad: true });
+};
+export const readNotice = (ids) => {
+  return $post(`/api/message/read`, { ids }, "json");
+};
+export const sendNotice = (datas) => {
+  return $post(`/api/message/send`, datas, "json");
+};

+ 178 - 178
src/components/EchartRender.vue

@@ -30,29 +30,29 @@ export default {
             "line",
             "line",
             "darkLines",
             "darkLines",
             "barGroup",
             "barGroup",
-            "lineGroup"
+            "lineGroup",
           ].indexOf(value) !== -1
           ].indexOf(value) !== -1
         );
         );
-      }
+      },
     },
     },
     rendererType: {
     rendererType: {
       type: String,
       type: String,
       default: "canvas",
       default: "canvas",
       validator(val) {
       validator(val) {
         return ["canvas", "svg"].indexOf(val) !== -1;
         return ["canvas", "svg"].indexOf(val) !== -1;
-      }
+      },
     },
     },
     animationIsOpen: {
     animationIsOpen: {
       type: Boolean,
       type: Boolean,
-      default: true
+      default: true,
     },
     },
     chartData: {
     chartData: {
       type: [Object, Array],
       type: [Object, Array],
-      required: true
+      required: true,
     },
     },
     chartTitle: {
     chartTitle: {
       type: String,
       type: String,
-      default: ""
+      default: "",
     },
     },
     chartColor: {
     chartColor: {
       type: Array,
       type: Array,
@@ -63,15 +63,15 @@ export default {
           "#FF7786",
           "#FF7786",
           "#4E7CFF",
           "#4E7CFF",
           "#6d32f9",
           "#6d32f9",
-          "#dd7755"
+          "#dd7755",
         ];
         ];
-      }
-    }
+      },
+    },
   },
   },
   data() {
   data() {
     return {
     return {
       chartOption: null,
       chartOption: null,
-      initOptions: { renderer: "canvas" }
+      initOptions: { renderer: "canvas" },
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -89,19 +89,19 @@ export default {
     getLineOption(datas) {
     getLineOption(datas) {
       let labels = [],
       let labels = [],
         vals = [];
         vals = [];
-      datas.map(item => {
+      datas.map((item) => {
         labels.push(item.name);
         labels.push(item.name);
         vals.push(item.value);
         vals.push(item.value);
       });
       });
       const linearColor = new echarts.graphic.LinearGradient(0, 1, 0, 0, [
       const linearColor = new echarts.graphic.LinearGradient(0, 1, 0, 0, [
         {
         {
           offset: 1,
           offset: 1,
-          color: "rgba(34,192,255,1)"
+          color: "rgba(34,192,255,1)",
         },
         },
         {
         {
           offset: 0,
           offset: 0,
-          color: "rgba(34,192,255,0)"
-        }
+          color: "rgba(34,192,255,0)",
+        },
       ]);
       ]);
 
 
       return {
       return {
@@ -110,13 +110,13 @@ export default {
           top: "10%",
           top: "10%",
           bottom: "12%",
           bottom: "12%",
           left: "5%",
           left: "5%",
-          right: "5%"
+          right: "5%",
         },
         },
         tooltip: {
         tooltip: {
           show: true,
           show: true,
-          formatter: function(params) {
+          formatter: function (params) {
             return params.value + "%";
             return params.value + "%";
-          }
+          },
         },
         },
         xAxis: {
         xAxis: {
           type: "category",
           type: "category",
@@ -124,46 +124,46 @@ export default {
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         yAxis: {
         yAxis: {
           type: "value",
           type: "value",
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             fontSize: 12,
             fontSize: 12,
             color: "#7C86A3",
             color: "#7C86A3",
-            formatter: function(value, index) {
+            formatter: function (value, index) {
               return value + "%";
               return value + "%";
-            }
+            },
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         series: [
         series: [
           {
           {
@@ -172,21 +172,21 @@ export default {
             smooth: true,
             smooth: true,
             data: vals,
             data: vals,
             itemStyle: {
             itemStyle: {
-              color: "rgba(34, 192, 255, 1)"
+              color: "rgba(34, 192, 255, 1)",
             },
             },
             lineStyle: {
             lineStyle: {
-              color: "rgba(34, 192, 255, 1)"
+              color: "rgba(34, 192, 255, 1)",
             },
             },
             areaStyle: {
             areaStyle: {
-              color: linearColor
-            }
-          }
-        ]
+              color: linearColor,
+            },
+          },
+        ],
       };
       };
     },
     },
     getDarkLinesOption(datas) {
     getDarkLinesOption(datas) {
       if (!datas.length) return;
       if (!datas.length) return;
-      const labels = datas[0].data.map(item => item.name);
+      const labels = datas[0].data.map((item) => item.name);
       const colors = [
       const colors = [
         {
         {
           color: "rgba(21, 91, 146,1)",
           color: "rgba(21, 91, 146,1)",
@@ -194,14 +194,14 @@ export default {
           linearColor: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
           linearColor: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
             {
             {
               offset: 1,
               offset: 1,
-              color: "rgba(21, 91, 146,1)"
+              color: "rgba(21, 91, 146,1)",
             },
             },
             {
             {
               offset: 0,
               offset: 0,
-              color: "rgba(21, 91, 146,0.2)"
-            }
+              color: "rgba(21, 91, 146,0.2)",
+            },
           ]),
           ]),
-          z: 4
+          z: 4,
         },
         },
         {
         {
           color: "rgba(204, 70, 53,1)",
           color: "rgba(204, 70, 53,1)",
@@ -209,19 +209,19 @@ export default {
           linearColor: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
           linearColor: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
             {
             {
               offset: 1,
               offset: 1,
-              color: "rgba(204, 70, 53,1)"
+              color: "rgba(204, 70, 53,1)",
             },
             },
             {
             {
               offset: 0,
               offset: 0,
-              color: "rgba(204, 70, 53,0)"
-            }
+              color: "rgba(204, 70, 53,0)",
+            },
           ]),
           ]),
-          z: 3
-        }
+          z: 3,
+        },
       ];
       ];
 
 
-      const series = datas.map(function(item, index) {
-        const data = item.data.map(function(elem) {
+      const series = datas.map(function (item, index) {
+        const data = item.data.map(function (elem) {
           return elem.value;
           return elem.value;
         });
         });
         const color = colors[index];
         const color = colors[index];
@@ -234,14 +234,14 @@ export default {
           symbolSize: 6,
           symbolSize: 6,
           z: color.z,
           z: color.z,
           itemStyle: {
           itemStyle: {
-            color: color.color
+            color: color.color,
           },
           },
           lineStyle: {
           lineStyle: {
-            color: color.lineColor
+            color: color.lineColor,
           },
           },
           areaStyle: {
           areaStyle: {
-            color: color.linearColor
-          }
+            color: color.linearColor,
+          },
         };
         };
       });
       });
 
 
@@ -251,22 +251,22 @@ export default {
           top: "10%",
           top: "10%",
           bottom: "12%",
           bottom: "12%",
           left: 40,
           left: 40,
-          right: 20
+          right: 20,
         },
         },
         tooltip: {
         tooltip: {
           show: true,
           show: true,
-          formatter: function(params) {
+          formatter: function (params) {
             return params.value + "%";
             return params.value + "%";
-          }
+          },
         },
         },
         legend: {
         legend: {
-          data: datas.map(data => data.name),
+          data: datas.map((data) => data.name),
           right: 20,
           right: 20,
           itemWidth: 14,
           itemWidth: 14,
           textStyle: {
           textStyle: {
             color: "#9d9c9c",
             color: "#9d9c9c",
-            fontSize: 14
-          }
+            fontSize: 14,
+          },
         },
         },
         xAxis: {
         xAxis: {
           type: "category",
           type: "category",
@@ -274,73 +274,73 @@ export default {
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "#3d3f55"
-            }
+              color: "#3d3f55",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "#3d3f55"
-            }
+              color: "#3d3f55",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#9d9c9c",
             color: "#9d9c9c",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         yAxis: {
         yAxis: {
           type: "value",
           type: "value",
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "#3d3f55"
-            }
+              color: "#3d3f55",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "#3d3f55"
-            }
+              color: "#3d3f55",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             fontSize: 12,
             fontSize: 12,
             color: "#9d9c9c",
             color: "#9d9c9c",
-            formatter: "{value}%"
+            formatter: "{value}%",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
-        series: series
+        series: series,
       };
       };
     },
     },
     getPieOption(datas) {
     getPieOption(datas) {
       if (!datas.chartLabels.length) return;
       if (!datas.chartLabels.length) return;
-      const seriesData = datas.chartLabels.map(function(item, index) {
+      const seriesData = datas.chartLabels.map(function (item, index) {
         return {
         return {
           name: item,
           name: item,
-          value: datas.chartData[0][index]
+          value: datas.chartData[0][index],
         };
         };
       });
       });
       return {
       return {
         animation: this.animationIsOpen,
         animation: this.animationIsOpen,
         grid: {
         grid: {
           top: "24%",
           top: "24%",
-          bottom: "10%"
+          bottom: "10%",
         },
         },
         tooltip: {
         tooltip: {
           trigger: "item",
           trigger: "item",
-          formatter: "{a} <br/>{b} : {c} ({d}%)"
+          formatter: "{a} <br/>{b} : {c} ({d}%)",
         },
         },
         legend: {
         legend: {
           show: true,
           show: true,
           itemGap: 20,
           itemGap: 20,
           itemWidth: 20,
           itemWidth: 20,
           textStyle: {
           textStyle: {
-            fontSize: 16
-          }
+            fontSize: 16,
+          },
         },
         },
         series: [
         series: [
           {
           {
@@ -349,17 +349,17 @@ export default {
             radius: "70%",
             radius: "70%",
             data: seriesData,
             data: seriesData,
             label: {
             label: {
-              show: false
+              show: false,
             },
             },
             itemStyle: {
             itemStyle: {
               emphasis: {
               emphasis: {
                 shadowBlur: 10,
                 shadowBlur: 10,
                 shadowOffsetX: 0,
                 shadowOffsetX: 0,
-                shadowColor: "rgba(0, 0, 0, 0.5)"
-              }
-            }
-          }
-        ]
+                shadowColor: "rgba(0, 0, 0, 0.5)",
+              },
+            },
+          },
+        ],
       };
       };
     },
     },
     getBarOption(datas) {
     getBarOption(datas) {
@@ -371,49 +371,49 @@ export default {
           top: "20%",
           top: "20%",
           bottom: "10%",
           bottom: "10%",
           left: "8%",
           left: "8%",
-          right: "5%"
+          right: "5%",
         },
         },
         tooltip: {
         tooltip: {
-          show: true
+          show: true,
         },
         },
         xAxis: {
         xAxis: {
           type: "category",
           type: "category",
           data: datas.names,
           data: datas.names,
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         yAxis: {
         yAxis: {
           type: "value",
           type: "value",
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         series: [
         series: [
           {
           {
@@ -424,13 +424,13 @@ export default {
             label: {
             label: {
               show: true,
               show: true,
               position: "top",
               position: "top",
-              color: "#666"
+              color: "#666",
             },
             },
             itemStyle: {
             itemStyle: {
-              barBorderRadius: 4
-            }
-          }
-        ]
+              barBorderRadius: 4,
+            },
+          },
+        ],
       };
       };
     },
     },
     getBarReverseOption(datas) {
     getBarReverseOption(datas) {
@@ -442,55 +442,55 @@ export default {
           top: "20%",
           top: "20%",
           bottom: "10%",
           bottom: "10%",
           left: "12%",
           left: "12%",
-          right: "5%"
+          right: "5%",
         },
         },
         tooltip: {
         tooltip: {
-          show: true
+          show: true,
         },
         },
         yAxis: {
         yAxis: {
           type: "category",
           type: "category",
           data: datas.names,
           data: datas.names,
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         xAxis: {
         xAxis: {
           type: "value",
           type: "value",
           splitLine: {
           splitLine: {
             show: false,
             show: false,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         series: [
         series: [
           {
           {
@@ -501,22 +501,22 @@ export default {
             label: {
             label: {
               show: true,
               show: true,
               position: "right",
               position: "right",
-              color: "#666"
+              color: "#666",
             },
             },
             itemStyle: {
             itemStyle: {
-              barBorderRadius: 4
-            }
-          }
-        ]
+              barBorderRadius: 4,
+            },
+          },
+        ],
       };
       };
     },
     },
     getBarGroupOption(datas) {
     getBarGroupOption(datas) {
       if (!datas.names.length) return;
       if (!datas.names.length) return;
-      const xAxis = datas.dataList.map(function(item) {
+      const xAxis = datas.dataList.map(function (item) {
         return item.name;
         return item.name;
       });
       });
-      const series = datas.names.map(function(name, index) {
-        const data = datas.dataList.map(function(item) {
+      const series = datas.names.map(function (name, index) {
+        const data = datas.dataList.map(function (item) {
           return item.data[index];
           return item.data[index];
         });
         });
         return {
         return {
@@ -525,8 +525,8 @@ export default {
           data: data,
           data: data,
           barMaxWidth: 12,
           barMaxWidth: 12,
           itemStyle: {
           itemStyle: {
-            barBorderRadius: 2
-          }
+            barBorderRadius: 2,
+          },
         };
         };
       });
       });
 
 
@@ -537,30 +537,30 @@ export default {
           top: "20%",
           top: "20%",
           bottom: "10%",
           bottom: "10%",
           left: "8%",
           left: "8%",
-          right: "5%"
+          right: "5%",
         },
         },
         tooltip: {
         tooltip: {
           show: true,
           show: true,
           trigger: "axis",
           trigger: "axis",
           axisPointer: {
           axisPointer: {
-            type: "shadow"
+            type: "shadow",
           },
           },
-          formatter: function(params) {
+          formatter: function (params) {
             const label = params[0].axisValueLabel;
             const label = params[0].axisValueLabel;
-            let infos = params.map(function(item) {
+            let infos = params.map(function (item) {
               return item.seriesName + ":" + item.value.toFixed(2) + "%";
               return item.seriesName + ":" + item.value.toFixed(2) + "%";
             });
             });
             infos.unshift(label);
             infos.unshift(label);
             return infos.join("<br/>");
             return infos.join("<br/>");
-          }
+          },
         },
         },
         legend: {
         legend: {
           data: datas.names,
           data: datas.names,
           right: 0,
           right: 0,
           itemWidth: 14,
           itemWidth: 14,
           textStyle: {
           textStyle: {
-            fontSize: 16
-          }
+            fontSize: 16,
+          },
         },
         },
         xAxis: {
         xAxis: {
           type: "category",
           type: "category",
@@ -568,50 +568,50 @@ export default {
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         yAxis: {
         yAxis: {
           type: "value",
           type: "value",
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
             fontWeight: "bold",
             fontWeight: "bold",
-            formatter: function(value, index) {
+            formatter: function (value, index) {
               return value + "%";
               return value + "%";
-            }
+            },
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
-        series: series
+        series: series,
       };
       };
 
 
       return options;
       return options;
     },
     },
     getLineGroupOption(datas) {
     getLineGroupOption(datas) {
       if (!datas.names.length) return;
       if (!datas.names.length) return;
-      const xAxis = datas.dataList.map(function(item) {
+      const xAxis = datas.dataList.map(function (item) {
         return item.name;
         return item.name;
       });
       });
 
 
-      const series = datas.names.map(function(name, index) {
-        const data = datas.dataList.map(function(item) {
+      const series = datas.names.map(function (name, index) {
+        const data = datas.dataList.map(function (item) {
           return item.data[index];
           return item.data[index];
         });
         });
         return {
         return {
@@ -621,10 +621,10 @@ export default {
           smooth: true,
           smooth: true,
           itemStyle: {
           itemStyle: {
             emphasis: {
             emphasis: {
-              color: "#333"
-            }
+              color: "#333",
+            },
           },
           },
-          data
+          data,
         };
         };
       });
       });
       return {
       return {
@@ -634,30 +634,30 @@ export default {
           top: "20%",
           top: "20%",
           bottom: "10%",
           bottom: "10%",
           left: "8%",
           left: "8%",
-          right: "5%"
+          right: "5%",
         },
         },
         tooltip: {
         tooltip: {
           show: true,
           show: true,
           trigger: "axis",
           trigger: "axis",
           axisPointer: {
           axisPointer: {
-            type: "shadow"
+            type: "shadow",
           },
           },
-          formatter: function(params) {
+          formatter: function (params) {
             const label = params[0].axisValueLabel;
             const label = params[0].axisValueLabel;
-            let infos = params.map(function(item) {
+            let infos = params.map(function (item) {
               return item.seriesName + ":" + item.value.toFixed(2) + "%";
               return item.seriesName + ":" + item.value.toFixed(2) + "%";
             });
             });
             infos.unshift(label);
             infos.unshift(label);
             return infos.join("<br/>");
             return infos.join("<br/>");
-          }
+          },
         },
         },
         legend: {
         legend: {
           data: datas.names,
           data: datas.names,
           right: 0,
           right: 0,
           itemWidth: 14,
           itemWidth: 14,
           textStyle: {
           textStyle: {
-            fontSize: 16
-          }
+            fontSize: 16,
+          },
         },
         },
 
 
         xAxis: {
         xAxis: {
@@ -666,40 +666,40 @@ export default {
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
-            fontWeight: "bold"
+            fontWeight: "bold",
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
         yAxis: {
         yAxis: {
           type: "value",
           type: "value",
           splitLine: {
           splitLine: {
             show: true,
             show: true,
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLine: {
           axisLine: {
             lineStyle: {
             lineStyle: {
-              color: "rgba(231,234,241,1)"
-            }
+              color: "rgba(231,234,241,1)",
+            },
           },
           },
           axisLabel: {
           axisLabel: {
             color: "#7C86A3",
             color: "#7C86A3",
             fontSize: 12,
             fontSize: 12,
             fontWeight: "bold",
             fontWeight: "bold",
-            formatter: function(value, index) {
+            formatter: function (value, index) {
               return value + "%";
               return value + "%";
-            }
+            },
           },
           },
           axisTick: {
           axisTick: {
-            show: false
-          }
+            show: false,
+          },
         },
         },
-        series: series
+        series: series,
       };
       };
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 111 - 111
src/components/ImageViewContain.vue

@@ -1,111 +1,111 @@
-<template>
-  <div :class="['image-view-contain', { 'image-view-none': !image.thumbSrc }]">
-    <div class="image-view-image" :style="styles">
-      <img
-        v-if="image.thumbSrc"
-        :src="image.thumbSrc"
-        :alt="image.title"
-        @click="toReview"
-        @load="resizeImage"
-      />
-    </div>
-  </div>
-</template>
-
-<script>
-export default {
-  name: "image-view-contain",
-  props: {
-    image: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      styles: { width: "", height: "", top: "", left: "", transform: "" },
-      deg: 0
-    };
-  },
-  mounted() {
-    this.registWinResize();
-  },
-  beforeDestroy() {
-    window.removeEventListener("resize", () => {
-      this.resizeImage(this.deg);
-    });
-  },
-  methods: {
-    toReview() {
-      this.$emit("to-review");
-    },
-    registWinResize() {
-      window.addEventListener("resize", () => {
-        this.resizeImage(this.deg);
-      });
-    },
-    resizeImage(deg = 0) {
-      this.deg = deg;
-      const box = this.$el;
-      const imgDom = box.firstChild.firstChild;
-      const { naturalWidth, naturalHeight } = imgDom;
-      const imageSize = this.getImageSizePos({
-        win: {
-          width: box.clientWidth,
-          height: box.clientHeight
-        },
-        img: {
-          width: naturalWidth,
-          height: naturalHeight
-        },
-        rotate: deg
-      });
-      this.styles = Object.assign(this.styles, {
-        width: imageSize.width + "px",
-        height: imageSize.height + "px",
-        top: imageSize.top + "px",
-        left: imageSize.left + "px",
-        transform: `rotate(${deg}deg)`
-      });
-    },
-    getImageSizePos({ win, img, rotate }) {
-      const imageSize = {
-        width: 0,
-        height: 0,
-        top: 0,
-        left: 0
-      };
-      const isHorizontal = !!(rotate % 180);
-
-      const rateWin = isHorizontal
-        ? win.height / win.width
-        : win.width / win.height;
-      const hwin = isHorizontal
-        ? {
-            width: win.height,
-            height: win.width
-          }
-        : win;
-
-      const rateImg = img.width / img.height;
-
-      if (rateImg <= rateWin) {
-        imageSize.height = Math.min(hwin.height, img.height);
-        imageSize.width = Math.floor(
-          (imageSize.height * img.width) / img.height
-        );
-      } else {
-        imageSize.width = Math.min(hwin.width, img.width);
-        imageSize.height = Math.floor(
-          (imageSize.width * img.height) / img.width
-        );
-      }
-      imageSize.left = (win.width - imageSize.width) / 2;
-      imageSize.top = (win.height - imageSize.height) / 2;
-      return imageSize;
-    }
-  }
-};
-</script>
+<template>
+  <div :class="['image-view-contain', { 'image-view-none': !image.thumbSrc }]">
+    <div class="image-view-image" :style="styles">
+      <img
+        v-if="image.thumbSrc"
+        :src="image.thumbSrc"
+        :alt="image.title"
+        @click="toReview"
+        @load="resizeImage"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "image-view-contain",
+  props: {
+    image: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      styles: { width: "", height: "", top: "", left: "", transform: "" },
+      deg: 0,
+    };
+  },
+  mounted() {
+    this.registWinResize();
+  },
+  beforeDestroy() {
+    window.removeEventListener("resize", () => {
+      this.resizeImage(this.deg);
+    });
+  },
+  methods: {
+    toReview() {
+      this.$emit("to-review");
+    },
+    registWinResize() {
+      window.addEventListener("resize", () => {
+        this.resizeImage(this.deg);
+      });
+    },
+    resizeImage(deg = 0) {
+      this.deg = deg;
+      const box = this.$el;
+      const imgDom = box.firstChild.firstChild;
+      const { naturalWidth, naturalHeight } = imgDom;
+      const imageSize = this.getImageSizePos({
+        win: {
+          width: box.clientWidth,
+          height: box.clientHeight,
+        },
+        img: {
+          width: naturalWidth,
+          height: naturalHeight,
+        },
+        rotate: deg,
+      });
+      this.styles = Object.assign(this.styles, {
+        width: imageSize.width + "px",
+        height: imageSize.height + "px",
+        top: imageSize.top + "px",
+        left: imageSize.left + "px",
+        transform: `rotate(${deg}deg)`,
+      });
+    },
+    getImageSizePos({ win, img, rotate }) {
+      const imageSize = {
+        width: 0,
+        height: 0,
+        top: 0,
+        left: 0,
+      };
+      const isHorizontal = !!(rotate % 180);
+
+      const rateWin = isHorizontal
+        ? win.height / win.width
+        : win.width / win.height;
+      const hwin = isHorizontal
+        ? {
+            width: win.height,
+            height: win.width,
+          }
+        : win;
+
+      const rateImg = img.width / img.height;
+
+      if (rateImg <= rateWin) {
+        imageSize.height = Math.min(hwin.height, img.height);
+        imageSize.width = Math.floor(
+          (imageSize.height * img.width) / img.height
+        );
+      } else {
+        imageSize.width = Math.min(hwin.width, img.width);
+        imageSize.height = Math.floor(
+          (imageSize.width * img.height) / img.width
+        );
+      }
+      imageSize.left = (win.width - imageSize.width) / 2;
+      imageSize.top = (win.height - imageSize.height) / 2;
+      return imageSize;
+    },
+  },
+};
+</script>

+ 7 - 7
src/components/PaperCarousel.vue

@@ -31,17 +31,17 @@ export default {
       type: Array,
       type: Array,
       default() {
       default() {
         return [];
         return [];
-      }
+      },
     },
     },
     loop: {
     loop: {
       type: Boolean,
       type: Boolean,
-      default: false
-    }
+      default: false,
+    },
   },
   },
   data() {
   data() {
     return {
     return {
       curPaper: {},
       curPaper: {},
-      curIndex: 0
+      curIndex: 0,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -53,7 +53,7 @@ export default {
     },
     },
     lastIndex() {
     lastIndex() {
       return this.papers.length ? this.papers.length - 1 : 0;
       return this.papers.length ? this.papers.length - 1 : 0;
-    }
+    },
   },
   },
   methods: {
   methods: {
     initIndex() {
     initIndex() {
@@ -105,7 +105,7 @@ export default {
     },
     },
     clickHandle() {
     clickHandle() {
       this.$emit("on-paper-click", this.curIndex, this.papers);
       this.$emit("on-paper-click", this.curIndex, this.papers);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 325 - 325
src/components/SimpleImagePreview.vue

@@ -1,325 +1,325 @@
-<template>
-  <Modal
-    :class="prefixCls"
-    v-model="modalIsShow"
-    title="图片预览"
-    fullscreen
-    footer-hide
-    :closable="canClose"
-    :mask-closable="canClose"
-    @on-visible-change="visibleChange"
-  >
-    <div slot="header"></div>
-    <div v-if="canClose" :class="[`${prefixCls}-close`]" @click="cancel">
-      <Icon type="ios-close" />
-    </div>
-
-    <div :class="[`${prefixCls}-body`]" ref="ReviewBody">
-      <div
-        v-if="canClose"
-        :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
-        @click.stop="showPrev"
-      >
-        <Icon type="ios-arrow-back" />
-      </div>
-      <div
-        v-if="canClose"
-        :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
-        @click.stop="showNext"
-      >
-        <Icon type="ios-arrow-forward" />
-      </div>
-      <div
-        :class="[
-          `${prefixCls}-imgs`,
-          { [`${prefixCls}-imgs-nosition`]: nosition }
-        ]"
-        :style="styles"
-        v-move-ele.prevent.stop="{ mouseMove, click: cancel }"
-        v-if="modalIsShow"
-      >
-        <img
-          :key="curImage.imgSrc"
-          :src="curImage.imgSrc"
-          :alt="curImage.name"
-          ref="PreviewImgDetail"
-          @load="resizeImage"
-        />
-      </div>
-      <div :class="[`${prefixCls}-none`]" v-if="!curImage.imgSrc">
-        <Icon type="md-image" />
-        <p>暂无数据</p>
-      </div>
-
-      <div :class="[`${prefixCls}-loading`]" v-show="loading">
-        <Icon class="ivu-load-loop" type="ios-loading" />
-      </div>
-    </div>
-
-    <div :class="[`${prefixCls}-footer`]">
-      <ul>
-        <li title="合适大小" @click="toOrigin">
-          <Icon type="md-expand" />
-        </li>
-        <li
-          title="放大"
-          @click="toMagnify"
-          :class="{
-            'li-disabled': transform.scale === maxScale
-          }"
-        >
-          <Icon type="md-add-circle" />
-        </li>
-        <li
-          title="缩小"
-          @click="toShrink"
-          :class="{
-            'li-disabled': transform.scale === minScale
-          }"
-        >
-          <Icon type="md-remove-circle" />
-        </li>
-        <li title="旋转" @click.stop="toRotate">
-          <Icon type="ios-refresh-circle" />
-        </li>
-      </ul>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import MoveEle from "./common/ImagePreview/move-ele";
-const prefixCls = "cc-image-preview";
-
-export default {
-  name: "simple-image-preview",
-  props: {
-    curImage: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    canClose: {
-      type: Boolean,
-      default: true
-    }
-  },
-  directives: { MoveEle },
-  data() {
-    return {
-      prefixCls,
-      modalIsShow: false,
-      styles: { width: "", height: "", top: "", left: "", transform: "" },
-      initWidth: 500,
-      minScale: 0.2,
-      maxScale: 5,
-      transform: {
-        scale: 1,
-        rotate: 0
-      },
-      loading: false,
-      loadingSetT: null,
-      nosition: false
-    };
-  },
-  // watch: {
-  //   "curImage.imgSrc": {
-  //     handler(val) {
-  //       if (val) {
-  //         this.loadingSetT = setTimeout(() => {
-  //           this.loading = true;
-  //         }, 300);
-  //         this.styles = {
-  //           width: "",
-  //           height: "",
-  //           top: "",
-  //           left: "",
-  //           transform: ""
-  //         };
-  //       }
-  //     }
-  //   }
-  // },
-  mounted() {
-    this.registWheelHandle();
-  },
-  methods: {
-    visibleChange(visible) {
-      if (!visible) return;
-      // this.loading = true;
-      // this.$nextTick(() => {
-      //   this.registfileLoad();
-      // });
-    },
-    // registfileLoad() {
-    //   const imgDom = this.$refs.PreviewImgDetail;
-    //   imgDom.onload = () => {
-    //     this.resizeImage(imgDom);
-    //   };
-    // },
-    resizeImage() {
-      // if (this.loadingSetT) clearTimeout(this.loadingSetT);
-
-      const imgDom = this.$refs.PreviewImgDetail;
-      const { naturalWidth, naturalHeight } = imgDom;
-      const rotate = this.curImage.deg || 0;
-      const imageSize = this.getImageSizePos({
-        win: {
-          width: this.$refs.ReviewBody.clientWidth,
-          height: this.$refs.ReviewBody.clientHeight
-        },
-        img: {
-          width: naturalWidth,
-          height: naturalHeight
-        },
-        rotate
-      });
-      this.transform = {
-        scale: 1,
-        rotate
-      };
-
-      this.styles = Object.assign(this.styles, {
-        width: imageSize.width + "px",
-        height: imageSize.height + "px",
-        top: imageSize.top + "px",
-        left: imageSize.left + "px",
-        marginLeft: "auto",
-        transform: "none"
-      });
-      this.setStyleTransform();
-      this.nosition = true;
-
-      this.loading = false;
-      setTimeout(() => {
-        this.nosition = false;
-      }, 100);
-    },
-    getImageSizePos({ win, img, rotate }) {
-      const imageSize = {
-        width: 0,
-        height: 0,
-        top: 0,
-        left: 0
-      };
-      const isHorizontal = !!(rotate % 180);
-
-      const rateWin = isHorizontal
-        ? win.height / win.width
-        : win.width / win.height;
-      const hwin = isHorizontal
-        ? {
-            width: win.height,
-            height: win.width
-          }
-        : win;
-
-      const rateImg = img.width / img.height;
-
-      if (rateImg <= rateWin) {
-        imageSize.height = Math.min(hwin.height, img.height);
-        imageSize.width = Math.floor(
-          (imageSize.height * img.width) / img.height
-        );
-      } else {
-        imageSize.width = Math.min(hwin.width, img.width);
-        imageSize.height = Math.floor(
-          (imageSize.width * img.height) / img.width
-        );
-      }
-      imageSize.left = (win.width - imageSize.width) / 2;
-      imageSize.top = (win.height - imageSize.height) / 2;
-      return imageSize;
-    },
-    cancel() {
-      if (!this.canClose) return;
-      this.modalIsShow = false;
-      this.$emit("on-close");
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    showPrev() {
-      this.$emit("on-prev");
-      // this.initData();
-    },
-    showNext() {
-      this.$emit("on-next");
-      // this.initData();
-    },
-    // dome-move
-    registWheelHandle() {
-      this.$refs.ReviewBody.addEventListener("wheel", e => {
-        e.preventDefault();
-        this.mouseWheel(e.wheelDeltaY);
-      });
-    },
-    mouseMove({ left, top }) {
-      this.styles.left = left + "px";
-      this.styles.top = top + "px";
-    },
-    mouseWheel(delta) {
-      if (delta > 0) {
-        this.toMagnify();
-      } else {
-        this.toShrink();
-      }
-    },
-    setStyleTransform() {
-      const { scale, rotate } = this.transform;
-      this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
-    },
-    toOrigin() {
-      this.transform.scale = 1;
-      this.setStyleTransform();
-    },
-    toMagnify() {
-      const scale = (this.transform.scale * 1.2).toFixed(2);
-      this.transform.scale = scale >= this.maxScale ? this.maxScale : scale;
-      this.setStyleTransform();
-    },
-    toShrink() {
-      const scale = (this.transform.scale * 0.75).toFixed(2);
-      this.transform.scale = scale <= this.minScale ? this.minScale : scale;
-      this.setStyleTransform();
-    },
-    toRotate() {
-      this.transform.rotate = this.transform.rotate + 90;
-      this.setStyleTransform();
-      // 调整图片尺寸
-      const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
-      const imageSize = this.getImageSizePos({
-        win: {
-          width: this.$refs.ReviewBody.clientWidth,
-          height: this.$refs.ReviewBody.clientHeight
-        },
-        img: {
-          width: naturalWidth,
-          height: naturalHeight
-        },
-        rotate: this.transform.rotate
-      });
-
-      this.styles = Object.assign(this.styles, {
-        width: imageSize.width + "px",
-        height: imageSize.height + "px",
-        top: imageSize.top + "px",
-        left: imageSize.left + "px"
-      });
-      // 360度无缝切换到0度
-      if (this.transform.rotate >= 360) {
-        setTimeout(() => {
-          this.nosition = true;
-          this.transform.rotate = 0;
-          this.setStyleTransform();
-          setTimeout(() => {
-            this.nosition = false;
-          }, 100);
-        }, 200);
-        // 200ms当次旋转动画持续时间
-      }
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    :class="prefixCls"
+    v-model="modalIsShow"
+    title="图片预览"
+    fullscreen
+    footer-hide
+    :closable="canClose"
+    :mask-closable="canClose"
+    @on-visible-change="visibleChange"
+  >
+    <div slot="header"></div>
+    <div v-if="canClose" :class="[`${prefixCls}-close`]" @click="cancel">
+      <Icon type="ios-close" />
+    </div>
+
+    <div :class="[`${prefixCls}-body`]" ref="ReviewBody">
+      <div
+        v-if="canClose"
+        :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
+        @click.stop="showPrev"
+      >
+        <Icon type="ios-arrow-back" />
+      </div>
+      <div
+        v-if="canClose"
+        :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
+        @click.stop="showNext"
+      >
+        <Icon type="ios-arrow-forward" />
+      </div>
+      <div
+        :class="[
+          `${prefixCls}-imgs`,
+          { [`${prefixCls}-imgs-nosition`]: nosition },
+        ]"
+        :style="styles"
+        v-move-ele.prevent.stop="{ mouseMove, click: cancel }"
+        v-if="modalIsShow"
+      >
+        <img
+          :key="curImage.imgSrc"
+          :src="curImage.imgSrc"
+          :alt="curImage.name"
+          ref="PreviewImgDetail"
+          @load="resizeImage"
+        />
+      </div>
+      <div :class="[`${prefixCls}-none`]" v-if="!curImage.imgSrc">
+        <Icon type="md-image" />
+        <p>暂无数据</p>
+      </div>
+
+      <div :class="[`${prefixCls}-loading`]" v-show="loading">
+        <Icon class="ivu-load-loop" type="ios-loading" />
+      </div>
+    </div>
+
+    <div :class="[`${prefixCls}-footer`]">
+      <ul>
+        <li title="合适大小" @click="toOrigin">
+          <Icon type="md-expand" />
+        </li>
+        <li
+          title="放大"
+          @click="toMagnify"
+          :class="{
+            'li-disabled': transform.scale === maxScale,
+          }"
+        >
+          <Icon type="md-add-circle" />
+        </li>
+        <li
+          title="缩小"
+          @click="toShrink"
+          :class="{
+            'li-disabled': transform.scale === minScale,
+          }"
+        >
+          <Icon type="md-remove-circle" />
+        </li>
+        <li title="旋转" @click.stop="toRotate">
+          <Icon type="ios-refresh-circle" />
+        </li>
+      </ul>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import MoveEle from "./common/ImagePreview/move-ele";
+const prefixCls = "cc-image-preview";
+
+export default {
+  name: "simple-image-preview",
+  props: {
+    curImage: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    canClose: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  directives: { MoveEle },
+  data() {
+    return {
+      prefixCls,
+      modalIsShow: false,
+      styles: { width: "", height: "", top: "", left: "", transform: "" },
+      initWidth: 500,
+      minScale: 0.2,
+      maxScale: 5,
+      transform: {
+        scale: 1,
+        rotate: 0,
+      },
+      loading: false,
+      loadingSetT: null,
+      nosition: false,
+    };
+  },
+  // watch: {
+  //   "curImage.imgSrc": {
+  //     handler(val) {
+  //       if (val) {
+  //         this.loadingSetT = setTimeout(() => {
+  //           this.loading = true;
+  //         }, 300);
+  //         this.styles = {
+  //           width: "",
+  //           height: "",
+  //           top: "",
+  //           left: "",
+  //           transform: ""
+  //         };
+  //       }
+  //     }
+  //   }
+  // },
+  mounted() {
+    this.registWheelHandle();
+  },
+  methods: {
+    visibleChange(visible) {
+      if (!visible) return;
+      // this.loading = true;
+      // this.$nextTick(() => {
+      //   this.registfileLoad();
+      // });
+    },
+    // registfileLoad() {
+    //   const imgDom = this.$refs.PreviewImgDetail;
+    //   imgDom.onload = () => {
+    //     this.resizeImage(imgDom);
+    //   };
+    // },
+    resizeImage() {
+      // if (this.loadingSetT) clearTimeout(this.loadingSetT);
+
+      const imgDom = this.$refs.PreviewImgDetail;
+      const { naturalWidth, naturalHeight } = imgDom;
+      const rotate = this.curImage.deg || 0;
+      const imageSize = this.getImageSizePos({
+        win: {
+          width: this.$refs.ReviewBody.clientWidth,
+          height: this.$refs.ReviewBody.clientHeight,
+        },
+        img: {
+          width: naturalWidth,
+          height: naturalHeight,
+        },
+        rotate,
+      });
+      this.transform = {
+        scale: 1,
+        rotate,
+      };
+
+      this.styles = Object.assign(this.styles, {
+        width: imageSize.width + "px",
+        height: imageSize.height + "px",
+        top: imageSize.top + "px",
+        left: imageSize.left + "px",
+        marginLeft: "auto",
+        transform: "none",
+      });
+      this.setStyleTransform();
+      this.nosition = true;
+
+      this.loading = false;
+      setTimeout(() => {
+        this.nosition = false;
+      }, 100);
+    },
+    getImageSizePos({ win, img, rotate }) {
+      const imageSize = {
+        width: 0,
+        height: 0,
+        top: 0,
+        left: 0,
+      };
+      const isHorizontal = !!(rotate % 180);
+
+      const rateWin = isHorizontal
+        ? win.height / win.width
+        : win.width / win.height;
+      const hwin = isHorizontal
+        ? {
+            width: win.height,
+            height: win.width,
+          }
+        : win;
+
+      const rateImg = img.width / img.height;
+
+      if (rateImg <= rateWin) {
+        imageSize.height = Math.min(hwin.height, img.height);
+        imageSize.width = Math.floor(
+          (imageSize.height * img.width) / img.height
+        );
+      } else {
+        imageSize.width = Math.min(hwin.width, img.width);
+        imageSize.height = Math.floor(
+          (imageSize.width * img.height) / img.width
+        );
+      }
+      imageSize.left = (win.width - imageSize.width) / 2;
+      imageSize.top = (win.height - imageSize.height) / 2;
+      return imageSize;
+    },
+    cancel() {
+      if (!this.canClose) return;
+      this.modalIsShow = false;
+      this.$emit("on-close");
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    showPrev() {
+      this.$emit("on-prev");
+      // this.initData();
+    },
+    showNext() {
+      this.$emit("on-next");
+      // this.initData();
+    },
+    // dome-move
+    registWheelHandle() {
+      this.$refs.ReviewBody.addEventListener("wheel", (e) => {
+        e.preventDefault();
+        this.mouseWheel(e.wheelDeltaY);
+      });
+    },
+    mouseMove({ left, top }) {
+      this.styles.left = left + "px";
+      this.styles.top = top + "px";
+    },
+    mouseWheel(delta) {
+      if (delta > 0) {
+        this.toMagnify();
+      } else {
+        this.toShrink();
+      }
+    },
+    setStyleTransform() {
+      const { scale, rotate } = this.transform;
+      this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
+    },
+    toOrigin() {
+      this.transform.scale = 1;
+      this.setStyleTransform();
+    },
+    toMagnify() {
+      const scale = (this.transform.scale * 1.2).toFixed(2);
+      this.transform.scale = scale >= this.maxScale ? this.maxScale : scale;
+      this.setStyleTransform();
+    },
+    toShrink() {
+      const scale = (this.transform.scale * 0.75).toFixed(2);
+      this.transform.scale = scale <= this.minScale ? this.minScale : scale;
+      this.setStyleTransform();
+    },
+    toRotate() {
+      this.transform.rotate = this.transform.rotate + 90;
+      this.setStyleTransform();
+      // 调整图片尺寸
+      const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
+      const imageSize = this.getImageSizePos({
+        win: {
+          width: this.$refs.ReviewBody.clientWidth,
+          height: this.$refs.ReviewBody.clientHeight,
+        },
+        img: {
+          width: naturalWidth,
+          height: naturalHeight,
+        },
+        rotate: this.transform.rotate,
+      });
+
+      this.styles = Object.assign(this.styles, {
+        width: imageSize.width + "px",
+        height: imageSize.height + "px",
+        top: imageSize.top + "px",
+        left: imageSize.left + "px",
+      });
+      // 360度无缝切换到0度
+      if (this.transform.rotate >= 360) {
+        setTimeout(() => {
+          this.nosition = true;
+          this.transform.rotate = 0;
+          this.setStyleTransform();
+          setTimeout(() => {
+            this.nosition = false;
+          }, 100);
+        }, 200);
+        // 200ms当次旋转动画持续时间
+      }
+    },
+  },
+};
+</script>

+ 25 - 25
src/components/UploadButton.vue

@@ -29,8 +29,8 @@
       :class="[
       :class="[
         {
         {
           'cc-tips-success': res.success,
           'cc-tips-success': res.success,
-          'cc-tips-error': !res.success
-        }
+          'cc-tips-error': !res.success,
+        },
       ]"
       ]"
       v-if="res.msg && !res.success"
       v-if="res.msg && !res.success"
     >
     >
@@ -47,44 +47,44 @@ export default {
   name: "upload-button",
   name: "upload-button",
   props: {
   props: {
     btnIcon: {
     btnIcon: {
-      type: String
+      type: String,
     },
     },
     btnType: {
     btnType: {
       type: String,
       type: String,
-      default: "default"
+      default: "default",
     },
     },
     btnContent: {
     btnContent: {
       type: String,
       type: String,
-      default: "上传文件"
+      default: "上传文件",
     },
     },
     format: {
     format: {
       type: Array,
       type: Array,
       default() {
       default() {
         return ["jpg", "png"];
         return ["jpg", "png"];
-      }
+      },
     },
     },
     uploadUrl: {
     uploadUrl: {
       type: String,
       type: String,
-      required: true
+      required: true,
     },
     },
     uploadData: {
     uploadData: {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
+      },
     },
     },
     maxSize: {
     maxSize: {
       type: Number,
       type: Number,
-      default: 10 * 1024
+      default: 10 * 1024,
     },
     },
     addFilenameParam: {
     addFilenameParam: {
       type: String,
       type: String,
-      default: "fileName"
+      default: "fileName",
     },
     },
     autoUpload: {
     autoUpload: {
       type: Boolean,
       type: Boolean,
-      default: true
-    }
+      default: true,
+    },
   },
   },
   data() {
   data() {
     const user = this.$ls.get("user", { token: "", id: "" });
     const user = this.$ls.get("user", { token: "", id: "" });
@@ -95,27 +95,27 @@ export default {
       headers: {
       headers: {
         md5: "",
         md5: "",
         Authorization: user.token,
         Authorization: user.token,
-        userId: user.id
+        userId: user.id,
       },
       },
       uploadDataDict: {},
       uploadDataDict: {},
       file: null,
       file: null,
       res: {
       res: {
         success: true,
         success: true,
-        msg: ""
-      }
+        msg: "",
+      },
     };
     };
   },
   },
   computed: {
   computed: {
     accept() {
     accept() {
-      return this.format.map(el => `.${el}`).join();
-    }
+      return this.format.map((el) => `.${el}`).join();
+    },
   },
   },
   methods: {
   methods: {
     visibleChange(visible) {
     visibleChange(visible) {
       if (!visible) {
       if (!visible) {
         this.res = {
         this.res = {
           success: true,
           success: true,
-          msg: ""
+          msg: "",
         };
         };
         this.$refs.UploadComp.clearFiles();
         this.$refs.UploadComp.clearFiles();
       }
       }
@@ -134,7 +134,7 @@ export default {
         this.uploadDataDict[this.addFilenameParam] = file.name;
         this.uploadDataDict[this.addFilenameParam] = file.name;
       this.res = {
       this.res = {
         success: true,
         success: true,
-        msg: ""
+        msg: "",
       };
       };
       this.$emit("file-change", file);
       this.$emit("file-change", file);
 
 
@@ -150,28 +150,28 @@ export default {
       this.loading = false;
       this.loading = false;
       this.res = {
       this.res = {
         success: false,
         success: false,
-        msg: response.message
+        msg: response.message,
       };
       };
     },
     },
     handleSuccess(response) {
     handleSuccess(response) {
       this.loading = false;
       this.loading = false;
       this.res = {
       this.res = {
         success: true,
         success: true,
-        msg: "上传成功!"
+        msg: "上传成功!",
       };
       };
       this.$emit("upload-success", response);
       this.$emit("upload-success", response);
     },
     },
     handleFormatError() {
     handleFormatError() {
       this.res = {
       this.res = {
         success: false,
         success: false,
-        msg: "只支持文件格式为" + this.format.join("/")
+        msg: "只支持文件格式为" + this.format.join("/"),
       };
       };
       this.loading = false;
       this.loading = false;
     },
     },
     handleExceededSize() {
     handleExceededSize() {
       this.res = {
       this.res = {
         success: false,
         success: false,
-        msg: "文件大小不能超过" + Math.floor(this.maxSize / 1024) + "M"
+        msg: "文件大小不能超过" + Math.floor(this.maxSize / 1024) + "M",
       };
       };
       this.loading = false;
       this.loading = false;
     },
     },
@@ -183,7 +183,7 @@ export default {
     },
     },
     open() {
     open() {
       this.modalIsShow = true;
       this.modalIsShow = true;
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 1 - 1
src/components/ViewFooter.vue

@@ -10,6 +10,6 @@
 
 
 <script>
 <script>
 export default {
 export default {
-  name: "view-footer"
+  name: "view-footer",
 };
 };
 </script>
 </script>

+ 6 - 6
src/components/ViewHeader.vue

@@ -53,17 +53,17 @@ export default {
   props: {
   props: {
     showResetPwd: {
     showResetPwd: {
       type: Boolean,
       type: Boolean,
-      default: true
-    }
+      default: true,
+    },
   },
   },
   computed: {
   computed: {
     classes() {
     classes() {
       return ["view-header"];
       return ["view-header"];
-    }
+    },
   },
   },
   data() {
   data() {
     return {
     return {
-      username: this.$ls.get("user", { loginName: "" }).loginName
+      username: this.$ls.get("user", { loginName: "" }).loginName,
     };
     };
   },
   },
   methods: {
   methods: {
@@ -78,7 +78,7 @@ export default {
       await logout();
       await logout();
       this.$ls.clear();
       this.$ls.clear();
       this.$router.push({ name: "Login" });
       this.$router.push({ name: "Login" });
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 31 - 31
src/components/common/ImagePreview/ImagePreview.vue

@@ -35,7 +35,7 @@
       <div
       <div
         :class="[
         :class="[
           `${prefixCls}-imgs`,
           `${prefixCls}-imgs`,
-          { [`${prefixCls}-imgs-nosition`]: nosition }
+          { [`${prefixCls}-imgs-nosition`]: nosition },
         ]"
         ]"
         :style="styles"
         :style="styles"
         v-move-ele.prevent="{ mouseMove }"
         v-move-ele.prevent="{ mouseMove }"
@@ -53,7 +53,7 @@
           title="放大"
           title="放大"
           @click="toMagnify"
           @click="toMagnify"
           :class="{
           :class="{
-            'li-disabled': transform.scale === maxScale
+            'li-disabled': transform.scale === maxScale,
           }"
           }"
         >
         >
           <Icon type="md-add-circle" />
           <Icon type="md-add-circle" />
@@ -62,7 +62,7 @@
           title="缩小"
           title="缩小"
           @click="toShrink"
           @click="toShrink"
           :class="{
           :class="{
-            'li-disabled': transform.scale === minScale
+            'li-disabled': transform.scale === minScale,
           }"
           }"
         >
         >
           <Icon type="md-remove-circle" />
           <Icon type="md-remove-circle" />
@@ -94,23 +94,23 @@ export default {
       type: Array,
       type: Array,
       default() {
       default() {
         return [];
         return [];
-      }
+      },
     },
     },
     initIndex: {
     initIndex: {
       type: Number,
       type: Number,
-      default: 0
+      default: 0,
     },
     },
     headerHide: {
     headerHide: {
       type: Boolean,
       type: Boolean,
-      default: false
+      default: false,
     },
     },
     loop: {
     loop: {
       type: Boolean,
       type: Boolean,
-      default: false
-    }
+      default: false,
+    },
   },
   },
   directives: {
   directives: {
-    MoveEle
+    MoveEle,
   },
   },
   data() {
   data() {
     return {
     return {
@@ -124,12 +124,12 @@ export default {
       initWidth: 500,
       initWidth: 500,
       transform: {
       transform: {
         scale: 1,
         scale: 1,
-        rotate: 0
+        rotate: 0,
       },
       },
       preLoadFiles: [],
       preLoadFiles: [],
       loading: false,
       loading: false,
       loadingSetT: null,
       loadingSetT: null,
-      nosition: false
+      nosition: false,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -141,7 +141,7 @@ export default {
     },
     },
     lastIndex() {
     lastIndex() {
       return this.imageList.length - 1;
       return this.imageList.length - 1;
-    }
+    },
   },
   },
   // watch: {
   // watch: {
   //   curIndex: {
   //   curIndex: {
@@ -171,11 +171,11 @@ export default {
           height: "",
           height: "",
           top: "",
           top: "",
           left: "",
           left: "",
-          transform: ""
+          transform: "",
         };
         };
         this.transform = {
         this.transform = {
           scale: 1,
           scale: 1,
-          rotate: 0
+          rotate: 0,
         };
         };
         this.preLoadFiles = [];
         this.preLoadFiles = [];
         this.loading = false;
         this.loading = false;
@@ -201,13 +201,13 @@ export default {
         const imageSize = this.getImageSizePos({
         const imageSize = this.getImageSizePos({
           win: {
           win: {
             width: this.$refs.ReviewBody.clientWidth,
             width: this.$refs.ReviewBody.clientWidth,
-            height: this.$refs.ReviewBody.clientHeight
+            height: this.$refs.ReviewBody.clientHeight,
           },
           },
           img: {
           img: {
             width: naturalWidth,
             width: naturalWidth,
-            height: naturalHeight
+            height: naturalHeight,
           },
           },
-          rotate: 0
+          rotate: 0,
         });
         });
 
 
         this.styles = Object.assign(this.styles, {
         this.styles = Object.assign(this.styles, {
@@ -215,11 +215,11 @@ export default {
           height: imageSize.height + "px",
           height: imageSize.height + "px",
           top: imageSize.top + "px",
           top: imageSize.top + "px",
           left: imageSize.left + "px",
           left: imageSize.left + "px",
-          transform: ""
+          transform: "",
         });
         });
         this.transform = {
         this.transform = {
           scale: 1,
           scale: 1,
-          rotate: 0
+          rotate: 0,
         };
         };
         if (this.loadingSetT) clearTimeout(this.loadingSetT);
         if (this.loadingSetT) clearTimeout(this.loadingSetT);
         this.loading = false;
         this.loading = false;
@@ -233,24 +233,24 @@ export default {
       if (this.loop) {
       if (this.loop) {
         preLoadIndexs = [
         preLoadIndexs = [
           curIndex === 0 ? this.lastIndex : curIndex - 1,
           curIndex === 0 ? this.lastIndex : curIndex - 1,
-          curIndex === this.lastIndex ? 0 : curIndex + 1
+          curIndex === this.lastIndex ? 0 : curIndex + 1,
         ];
         ];
       } else {
       } else {
         preLoadIndexs = [
         preLoadIndexs = [
           curIndex === 0 ? null : curIndex - 1,
           curIndex === 0 ? null : curIndex - 1,
-          curIndex === this.lastIndex ? null : curIndex + 1
+          curIndex === this.lastIndex ? null : curIndex + 1,
         ];
         ];
       }
       }
       this.preLoadFiles = preLoadIndexs
       this.preLoadFiles = preLoadIndexs
-        .filter(item => item !== null)
-        .map(item => this.imageList[item]);
+        .filter((item) => item !== null)
+        .map((item) => this.imageList[item]);
     },
     },
     getImageSizePos({ win, img, rotate }) {
     getImageSizePos({ win, img, rotate }) {
       const imageSize = {
       const imageSize = {
         width: 0,
         width: 0,
         height: 0,
         height: 0,
         top: 0,
         top: 0,
-        left: 0
+        left: 0,
       };
       };
       const isHorizontal = !!(rotate % 180);
       const isHorizontal = !!(rotate % 180);
 
 
@@ -260,7 +260,7 @@ export default {
       const hwin = isHorizontal
       const hwin = isHorizontal
         ? {
         ? {
             width: win.height,
             width: win.height,
-            height: win.width
+            height: win.width,
           }
           }
         : win;
         : win;
 
 
@@ -347,20 +347,20 @@ export default {
       const imageSize = this.getImageSizePos({
       const imageSize = this.getImageSizePos({
         win: {
         win: {
           width: this.$refs.ReviewBody.clientWidth,
           width: this.$refs.ReviewBody.clientWidth,
-          height: this.$refs.ReviewBody.clientHeight
+          height: this.$refs.ReviewBody.clientHeight,
         },
         },
         img: {
         img: {
           width: naturalWidth,
           width: naturalWidth,
-          height: naturalHeight
+          height: naturalHeight,
         },
         },
-        rotate: this.transform.rotate
+        rotate: this.transform.rotate,
       });
       });
 
 
       this.styles = Object.assign(this.styles, {
       this.styles = Object.assign(this.styles, {
         width: imageSize.width + "px",
         width: imageSize.width + "px",
         height: imageSize.height + "px",
         height: imageSize.height + "px",
         top: imageSize.top + "px",
         top: imageSize.top + "px",
-        left: imageSize.left + "px"
+        left: imageSize.left + "px",
       });
       });
       // 360度无缝切换到0度
       // 360度无缝切换到0度
       if (this.transform.rotate >= 360) {
       if (this.transform.rotate >= 360) {
@@ -373,10 +373,10 @@ export default {
           }, 100);
           }, 100);
         }, 200);
         }, 200);
       }
       }
-    }
+    },
   },
   },
   beforeDestroy() {
   beforeDestroy() {
     if (this.loadingSetT) clearTimeout(this.loadingSetT);
     if (this.loadingSetT) clearTimeout(this.loadingSetT);
-  }
+  },
 };
 };
 </script>
 </script>

+ 4 - 4
src/components/common/ImagePreview/move-ele.js

@@ -7,7 +7,7 @@ export default {
     let [left, top] = [0, 0];
     let [left, top] = [0, 0];
     let isDrag = false;
     let isDrag = false;
 
 
-    let moveHandle = function(e) {
+    let moveHandle = function (e) {
       isDrag = true;
       isDrag = true;
       if (modifiers.prevent) {
       if (modifiers.prevent) {
         e.preventDefault();
         e.preventDefault();
@@ -23,7 +23,7 @@ export default {
       }
       }
     };
     };
 
 
-    let upHandle = function(e) {
+    let upHandle = function (e) {
       if (modifiers.prevent) {
       if (modifiers.prevent) {
         e.preventDefault();
         e.preventDefault();
       }
       }
@@ -39,7 +39,7 @@ export default {
       isDrag = false;
       isDrag = false;
     };
     };
 
 
-    el.addEventListener("mousedown", function(e) {
+    el.addEventListener("mousedown", function (e) {
       if (modifiers.prevent) {
       if (modifiers.prevent) {
         e.preventDefault();
         e.preventDefault();
       }
       }
@@ -52,5 +52,5 @@ export default {
       document.addEventListener("mousemove", moveHandle);
       document.addEventListener("mousemove", moveHandle);
       document.addEventListener("mouseup", upHandle);
       document.addEventListener("mouseup", upHandle);
     });
     });
-  }
+  },
 };
 };

+ 185 - 185
src/components/common/ImportFile/ImportFile.vue

@@ -1,185 +1,185 @@
-<template>
-  <div :class="prefixCls">
-    <Modal
-      v-model="modalIsShow"
-      :title="title"
-      :footer-hide="true"
-      :mask-closable="false"
-      @on-visible-change="visibleChange"
-    >
-      <div :class="[`${prefixCls}-head`]">
-        <slot name="head"> </slot>
-      </div>
-      <div :class="[`${prefixCls}-body`]">
-        <Upload
-          type="drag"
-          :action="uploadUrl"
-          :headers="headers"
-          :max-size="maxSize"
-          :format="format"
-          :accept="accept"
-          :data="uploadData"
-          :before-upload="handleBeforeUpload"
-          :on-format-error="handleFormatError"
-          :on-exceeded-size="handleExceededSize"
-          :on-error="handleError"
-          :on-success="handleSuccess"
-          :on-remove="handleRemove"
-          :disabled="!!load"
-          ref="UploadComp"
-        >
-          <div style="padding: 40px 0">
-            <Icon class="upload-icon" type="md-cloud-upload" size="40"></Icon>
-            <p v-if="load">正在导入……</p>
-            <p v-else>将文件拖到此处,或<em>点击上传</em></p>
-          </div>
-        </Upload>
-        <p
-          :class="[
-            `${prefixCls}-tips`,
-            {
-              'cc-tips-success': res.success,
-              'cc-tips-error': !res.success
-            }
-          ]"
-          v-if="res.msg"
-        >
-          {{ res.msg }}
-        </p>
-      </div>
-      <div :class="[`${prefixCls}-footer`]" v-if="downloadUrl">
-        模板下载:
-        <a :href="downloadUrl" :download="dfilename">{{ dfilename }}</a>
-      </div>
-    </Modal>
-  </div>
-</template>
-
-<script>
-const prefixCls = "cc-import-file";
-
-export default {
-  name: "import-file",
-  props: {
-    title: {
-      type: String,
-      default: "文件上传"
-    },
-    downloadUrl: {
-      type: String,
-      default: ""
-    },
-    downloadFilename: String,
-    format: {
-      type: Array,
-      default() {
-        return ["jpg", "png"];
-      }
-    },
-    uploadUrl: {
-      type: String,
-      required: true
-    },
-    uploadData: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    headers: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    maxSize: {
-      type: Number,
-      default: 10 * 1024
-    },
-    addFilenameParam: {
-      type: String,
-      default: "fileName"
-    }
-  },
-  data() {
-    return {
-      prefixCls,
-      modalIsShow: false,
-      res: {
-        success: true,
-        msg: ""
-      },
-      load: null
-    };
-  },
-  computed: {
-    dfilename() {
-      return this.downloadFilename || this.downloadUrl.split("/").pop();
-    },
-    accept() {
-      return this.format.map(el => `.${el}`).join();
-    }
-  },
-  methods: {
-    visibleChange(visible) {
-      if (!visible) {
-        this.res = {
-          success: true,
-          msg: ""
-        };
-        this.$refs.UploadComp.clearFiles();
-      }
-    },
-    handleBeforeUpload(file) {
-      if (this.addFilenameParam)
-        this.uploadData[this.addFilenameParam] = file.name;
-      this.$refs.UploadComp.clearFiles();
-
-      this.res = {
-        success: true,
-        msg: ""
-      };
-
-      this.load = this.$Message.loading({
-        content: "Loading...",
-        duration: 0
-      });
-    },
-    handleError(error, response) {
-      this.load();
-      this.load = null;
-      this.res = {
-        success: false,
-        msg: response.message
-      };
-    },
-    handleSuccess(response) {
-      this.load();
-      this.load = null;
-      this.$emit("upload-success", response);
-      this.cancel();
-    },
-    handleFormatError() {
-      this.res = {
-        success: false,
-        msg: "只支持文件格式为" + this.format.join("/")
-      };
-    },
-    handleExceededSize() {
-      this.res = {
-        success: false,
-        msg: "文件大小不能超过" + Math.floor(this.maxSize / 1024) + "M"
-      };
-    },
-    handleRemove() {
-      this.resData = "";
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    }
-  }
-};
-</script>
+<template>
+  <div :class="prefixCls">
+    <Modal
+      v-model="modalIsShow"
+      :title="title"
+      :footer-hide="true"
+      :mask-closable="false"
+      @on-visible-change="visibleChange"
+    >
+      <div :class="[`${prefixCls}-head`]">
+        <slot name="head"> </slot>
+      </div>
+      <div :class="[`${prefixCls}-body`]">
+        <Upload
+          type="drag"
+          :action="uploadUrl"
+          :headers="headers"
+          :max-size="maxSize"
+          :format="format"
+          :accept="accept"
+          :data="uploadData"
+          :before-upload="handleBeforeUpload"
+          :on-format-error="handleFormatError"
+          :on-exceeded-size="handleExceededSize"
+          :on-error="handleError"
+          :on-success="handleSuccess"
+          :on-remove="handleRemove"
+          :disabled="!!load"
+          ref="UploadComp"
+        >
+          <div style="padding: 40px 0">
+            <Icon class="upload-icon" type="md-cloud-upload" size="40"></Icon>
+            <p v-if="load">正在导入……</p>
+            <p v-else>将文件拖到此处,或<em>点击上传</em></p>
+          </div>
+        </Upload>
+        <p
+          :class="[
+            `${prefixCls}-tips`,
+            {
+              'cc-tips-success': res.success,
+              'cc-tips-error': !res.success,
+            },
+          ]"
+          v-if="res.msg"
+        >
+          {{ res.msg }}
+        </p>
+      </div>
+      <div :class="[`${prefixCls}-footer`]" v-if="downloadUrl">
+        模板下载:
+        <a :href="downloadUrl" :download="dfilename">{{ dfilename }}</a>
+      </div>
+    </Modal>
+  </div>
+</template>
+
+<script>
+const prefixCls = "cc-import-file";
+
+export default {
+  name: "import-file",
+  props: {
+    title: {
+      type: String,
+      default: "文件上传",
+    },
+    downloadUrl: {
+      type: String,
+      default: "",
+    },
+    downloadFilename: String,
+    format: {
+      type: Array,
+      default() {
+        return ["jpg", "png"];
+      },
+    },
+    uploadUrl: {
+      type: String,
+      required: true,
+    },
+    uploadData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    headers: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    maxSize: {
+      type: Number,
+      default: 10 * 1024,
+    },
+    addFilenameParam: {
+      type: String,
+      default: "fileName",
+    },
+  },
+  data() {
+    return {
+      prefixCls,
+      modalIsShow: false,
+      res: {
+        success: true,
+        msg: "",
+      },
+      load: null,
+    };
+  },
+  computed: {
+    dfilename() {
+      return this.downloadFilename || this.downloadUrl.split("/").pop();
+    },
+    accept() {
+      return this.format.map((el) => `.${el}`).join();
+    },
+  },
+  methods: {
+    visibleChange(visible) {
+      if (!visible) {
+        this.res = {
+          success: true,
+          msg: "",
+        };
+        this.$refs.UploadComp.clearFiles();
+      }
+    },
+    handleBeforeUpload(file) {
+      if (this.addFilenameParam)
+        this.uploadData[this.addFilenameParam] = file.name;
+      this.$refs.UploadComp.clearFiles();
+
+      this.res = {
+        success: true,
+        msg: "",
+      };
+
+      this.load = this.$Message.loading({
+        content: "Loading...",
+        duration: 0,
+      });
+    },
+    handleError(error, response) {
+      this.load();
+      this.load = null;
+      this.res = {
+        success: false,
+        msg: response.message,
+      };
+    },
+    handleSuccess(response) {
+      this.load();
+      this.load = null;
+      this.$emit("upload-success", response);
+      this.cancel();
+    },
+    handleFormatError() {
+      this.res = {
+        success: false,
+        msg: "只支持文件格式为" + this.format.join("/"),
+      };
+    },
+    handleExceededSize() {
+      this.res = {
+        success: false,
+        msg: "文件大小不能超过" + Math.floor(this.maxSize / 1024) + "M",
+      };
+    },
+    handleRemove() {
+      this.resData = "";
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+  },
+};
+</script>

+ 3 - 5
src/components/common/StepsProgress/StepFour.vue

@@ -1,7 +1,5 @@
 <template>
 <template>
-  <div class="step-four">
-    step-four
-  </div>
+  <div class="step-four">step-four</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -22,7 +20,7 @@ export default {
 
 
       // 提交可执行下一步操作事件
       // 提交可执行下一步操作事件
       this.$emit("on-next");
       this.$emit("on-next");
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 3 - 5
src/components/common/StepsProgress/StepOne.vue

@@ -1,7 +1,5 @@
 <template>
 <template>
-  <div class="step-one">
-    step-one
-  </div>
+  <div class="step-one">step-one</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -22,7 +20,7 @@ export default {
 
 
       // 提交可执行下一步操作事件
       // 提交可执行下一步操作事件
       this.$emit("on-next");
       this.$emit("on-next");
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 3 - 5
src/components/common/StepsProgress/StepThree.vue

@@ -1,7 +1,5 @@
 <template>
 <template>
-  <div class="step-three">
-    step-three
-  </div>
+  <div class="step-three">step-three</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -22,7 +20,7 @@ export default {
 
 
       // 提交可执行下一步操作事件
       // 提交可执行下一步操作事件
       this.$emit("on-next");
       this.$emit("on-next");
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 3 - 5
src/components/common/StepsProgress/StepTwo.vue

@@ -1,7 +1,5 @@
 <template>
 <template>
-  <div class="step-two">
-    step-two
-  </div>
+  <div class="step-two">step-two</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -22,7 +20,7 @@ export default {
 
 
       // 提交可执行下一步操作事件
       // 提交可执行下一步操作事件
       this.$emit("on-next");
       this.$emit("on-next");
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 12 - 12
src/components/common/StepsProgress/StepsProgress.vue

@@ -23,7 +23,7 @@
         type="primary"
         type="primary"
         @click="prevStep"
         @click="prevStep"
         :disabled="isFirstStep"
         :disabled="isFirstStep"
-        style="margin-right: 20px;"
+        style="margin-right: 20px"
         >上一步</Button
         >上一步</Button
       >
       >
       <Button
       <Button
@@ -45,20 +45,20 @@ import StepFour from "./StepFour";
 const STEPS_LIST = [
 const STEPS_LIST = [
   {
   {
     name: "step-one",
     name: "step-one",
-    title: "步骤1"
+    title: "步骤1",
   },
   },
   {
   {
     name: "step-two",
     name: "step-two",
-    title: "步骤2"
+    title: "步骤2",
   },
   },
   {
   {
     name: "step-three",
     name: "step-three",
-    title: "步骤3"
+    title: "步骤3",
   },
   },
   {
   {
     name: "step-four",
     name: "step-four",
-    title: "步骤4"
-  }
+    title: "步骤4",
+  },
 ];
 ];
 
 
 export default {
 export default {
@@ -67,14 +67,14 @@ export default {
     StepOne,
     StepOne,
     StepTwo,
     StepTwo,
     StepThree,
     StepThree,
-    StepFour
+    StepFour,
   },
   },
   data() {
   data() {
     return {
     return {
       STEPS_LIST,
       STEPS_LIST,
       current: 0,
       current: 0,
       nextHolder: true,
       nextHolder: true,
-      dataReady: true
+      dataReady: true,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -89,13 +89,13 @@ export default {
     },
     },
     lastStep() {
     lastStep() {
       return this.STEPS_LIST.length - 1;
       return this.STEPS_LIST.length - 1;
-    }
+    },
   },
   },
   watch: {
   watch: {
     current() {
     current() {
       // 滚动条置顶
       // 滚动条置顶
       // document.getElementById("home-body").scrollTop = 0;
       // document.getElementById("home-body").scrollTop = 0;
-    }
+    },
   },
   },
   methods: {
   methods: {
     prevStep() {
     prevStep() {
@@ -113,8 +113,8 @@ export default {
     },
     },
     stepReady() {
     stepReady() {
       this.nextHolder = false;
       this.nextHolder = false;
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>
 
 

+ 4 - 4
src/components/homeMenuMixins.js

@@ -5,11 +5,11 @@ export default {
 
 
       this.curNav = item;
       this.curNav = item;
       this.$router.push({
       this.$router.push({
-        name: item.name
+        name: item.name,
       });
       });
     },
     },
     actCurNav(router) {
     actCurNav(router) {
-      this.curNav = this.navs.find(item => item.name === router.name);
-    }
-  }
+      this.curNav = this.navs.find((item) => item.name === router.name);
+    },
+  },
 };
 };

+ 1 - 1
src/config.js

@@ -2,5 +2,5 @@ export default {
   domain: process.env.VUE_APP_DOMAIN || window.location.origin,
   domain: process.env.VUE_APP_DOMAIN || window.location.origin,
   timeout: process.env.VUE_APP_TIMEOUT * 1,
   timeout: process.env.VUE_APP_TIMEOUT * 1,
   pageSize: process.env.VUE_APP_PAGE_SIZE * 1,
   pageSize: process.env.VUE_APP_PAGE_SIZE * 1,
-  authTimeout: process.env.VUE_APP_AUTH_TIMEOUT * 1
+  authTimeout: process.env.VUE_APP_AUTH_TIMEOUT * 1,
 };
 };

+ 52 - 52
src/constants/authority.js

@@ -2,193 +2,193 @@ export const main = [
   {
   {
     name: "WorkManage",
     name: "WorkManage",
     title: "工作文件夹",
     title: "工作文件夹",
-    icon: "ivu-icon-files"
+    icon: "ivu-icon-files",
   },
   },
   {
   {
     name: "WorkOverview",
     name: "WorkOverview",
     title: "总览",
     title: "总览",
-    icon: "ivu-icon-overview"
+    icon: "ivu-icon-overview",
   },
   },
   {
   {
     name: "PaperManage",
     name: "PaperManage",
     title: "试卷管理",
     title: "试卷管理",
-    icon: "ivu-icon-paper"
+    icon: "ivu-icon-paper",
   },
   },
   {
   {
     name: "ClientMonitor",
     name: "ClientMonitor",
     title: "设备监控",
     title: "设备监控",
-    icon: "ivu-icon-monitor"
+    icon: "ivu-icon-monitor",
   },
   },
   {
   {
     name: "StudentManage",
     name: "StudentManage",
     title: "考生管理",
     title: "考生管理",
-    icon: "ivu-icon-student"
+    icon: "ivu-icon-student",
   },
   },
   {
   {
     name: "ClientSet",
     name: "ClientSet",
     title: "采集设置",
     title: "采集设置",
-    icon: "ivu-icon-recode"
+    icon: "ivu-icon-recode",
   },
   },
   {
   {
     name: "GradingSet",
     name: "GradingSet",
     title: "分档设置",
     title: "分档设置",
-    icon: "ivu-icon-grade-set"
+    icon: "ivu-icon-grade-set",
   },
   },
   {
   {
     name: "MarkSet",
     name: "MarkSet",
     title: "打分设置",
     title: "打分设置",
-    icon: "ivu-icon-score-set"
+    icon: "ivu-icon-score-set",
   },
   },
   {
   {
     name: "QualityAnalysis",
     name: "QualityAnalysis",
     title: "质量分析",
     title: "质量分析",
-    icon: "ivu-icon-analysis"
+    icon: "ivu-icon-analysis",
   },
   },
   {
   {
     name: "StudentScore",
     name: "StudentScore",
     title: "成绩查询",
     title: "成绩查询",
-    icon: "ivu-icon-score"
+    icon: "ivu-icon-score",
   },
   },
   {
   {
     name: "CheckData",
     name: "CheckData",
     title: "数据校验",
     title: "数据校验",
-    icon: "ivu-icon-task"
-  }
+    icon: "ivu-icon-task",
+  },
 ];
 ];
 
 
 export const clientSet = [
 export const clientSet = [
   {
   {
     name: "ClientAccountSet",
     name: "ClientAccountSet",
-    title: "账号设置"
+    title: "账号设置",
   },
   },
   {
   {
     name: "ClientParamSet",
     name: "ClientParamSet",
-    title: "参数设置"
+    title: "参数设置",
   },
   },
   {
   {
     name: "InspectionAccountSet",
     name: "InspectionAccountSet",
-    title: "纪检账号"
-  }
+    title: "纪检账号",
+  },
 ];
 ];
 
 
 export const gradingSet = [
 export const gradingSet = [
   {
   {
     name: "GradingLevelSet",
     name: "GradingLevelSet",
-    title: "档位设置"
+    title: "档位设置",
   },
   },
   {
   {
     name: "GradingRuleSet",
     name: "GradingRuleSet",
-    title: "定档规则"
+    title: "定档规则",
   },
   },
   {
   {
     name: "UploadPaper",
     name: "UploadPaper",
-    title: "上传试题"
-  }
+    title: "上传试题",
+  },
 ];
 ];
 
 
 export const markSet = [
 export const markSet = [
   {
   {
     name: "MarkRuleSet",
     name: "MarkRuleSet",
-    title: "打分设置"
+    title: "打分设置",
   },
   },
   {
   {
     name: "ExportPaper",
     name: "ExportPaper",
-    title: "图片导出"
-  }
+    title: "图片导出",
+  },
 ];
 ];
 
 
 export const grading = [
 export const grading = [
   {
   {
     name: "GradingProgress",
     name: "GradingProgress",
     title: "分档进度",
     title: "分档进度",
-    icon: "ivu-icon-progress"
+    icon: "ivu-icon-progress",
   },
   },
   {
   {
     name: "GradingDetail",
     name: "GradingDetail",
     title: "分档详情",
     title: "分档详情",
-    icon: "ivu-icon-score-detail"
+    icon: "ivu-icon-score-detail",
   },
   },
   {
   {
     name: "GradingAnalysis",
     name: "GradingAnalysis",
     title: "分档统计",
     title: "分档统计",
-    icon: "ivu-icon-score-detail"
+    icon: "ivu-icon-score-detail",
   },
   },
   {
   {
     name: "GradingUserManage",
     name: "GradingUserManage",
     title: "用户管理",
     title: "用户管理",
-    icon: "ivu-icon-student"
+    icon: "ivu-icon-student",
   },
   },
   {
   {
     name: "GradingGroupManage",
     name: "GradingGroupManage",
     title: "分档分组",
     title: "分档分组",
-    icon: "ivu-icon-group"
+    icon: "ivu-icon-group",
   },
   },
   {
   {
     name: "GradingStandardPaperManage",
     name: "GradingStandardPaperManage",
     title: "标准卷管理",
     title: "标准卷管理",
-    icon: "ivu-icon-score"
+    icon: "ivu-icon-score",
   },
   },
   {
   {
     name: "ExamPaperView",
     name: "ExamPaperView",
     title: "查看试卷",
     title: "查看试卷",
-    icon: "ivu-icon-view"
-  }
+    icon: "ivu-icon-view",
+  },
 ];
 ];
 
 
 export const mark = [
 export const mark = [
   {
   {
     name: "MarkProgress",
     name: "MarkProgress",
     title: "打分进度",
     title: "打分进度",
-    icon: "ivu-icon-progress"
+    icon: "ivu-icon-progress",
   },
   },
   {
   {
     name: "MarkTaskManage",
     name: "MarkTaskManage",
     title: "任务发布",
     title: "任务发布",
-    icon: "ivu-icon-task"
+    icon: "ivu-icon-task",
   },
   },
   {
   {
     name: "MarkDetail",
     name: "MarkDetail",
     title: "打分详情",
     title: "打分详情",
-    icon: "ivu-icon-score-detail"
+    icon: "ivu-icon-score-detail",
   },
   },
   {
   {
     name: "MarkUserManage",
     name: "MarkUserManage",
     title: "用户管理",
     title: "用户管理",
-    icon: "ivu-icon-student"
+    icon: "ivu-icon-student",
   },
   },
   {
   {
     name: "MarkGroupManage",
     name: "MarkGroupManage",
     title: "打分分组",
     title: "打分分组",
-    icon: "ivu-icon-group"
+    icon: "ivu-icon-group",
   },
   },
   {
   {
     name: "MarkExamPaperView",
     name: "MarkExamPaperView",
     title: "查看试卷",
     title: "查看试卷",
-    icon: "ivu-icon-view"
-  }
+    icon: "ivu-icon-view",
+  },
 ];
 ];
 
 
 export const inspection = [
 export const inspection = [
   {
   {
     name: "InspectionActionLogs",
     name: "InspectionActionLogs",
     title: "操作日志",
     title: "操作日志",
-    icon: "ivu-icon-logs"
+    icon: "ivu-icon-logs",
   },
   },
   {
   {
     name: "InspectionCollectLogs",
     name: "InspectionCollectLogs",
     title: "采集日志",
     title: "采集日志",
-    icon: "ivu-icon-recode"
+    icon: "ivu-icon-recode",
   },
   },
   {
   {
     name: "InspectionGrading",
     name: "InspectionGrading",
     title: "改档处理",
     title: "改档处理",
-    icon: "ivu-icon-change"
+    icon: "ivu-icon-change",
   },
   },
   {
   {
     name: "InspectionScore",
     name: "InspectionScore",
     title: "成绩查询",
     title: "成绩查询",
-    icon: "ivu-icon-score"
-  }
+    icon: "ivu-icon-score",
+  },
 ];
 ];
 
 
 // const getLeadRouter = () => {
 // const getLeadRouter = () => {
@@ -201,15 +201,15 @@ export const inspection = [
 // };
 // };
 
 
 const getAdminRouter = () => {
 const getAdminRouter = () => {
-  let leadGrade = grading.map(item => item.name).slice(0, -2);
-  let leadMark = mark.map(item => item.name).slice(0, -1);
+  let leadGrade = grading.map((item) => item.name).slice(0, -2);
+  let leadMark = mark.map((item) => item.name).slice(0, -1);
   return [
   return [
     ...leadGrade,
     ...leadGrade,
     ...leadMark,
     ...leadMark,
-    ...main.map(item => item.name),
-    ...clientSet.map(item => item.name),
-    ...gradingSet.map(item => item.name),
-    ...markSet.map(item => item.name)
+    ...main.map((item) => item.name),
+    ...clientSet.map((item) => item.name),
+    ...gradingSet.map((item) => item.name),
+    ...markSet.map((item) => item.name),
   ];
   ];
 };
 };
 
 
@@ -220,11 +220,11 @@ export const checkRouterValid = (roleCode, routerName) => {
       "GradingOperation",
       "GradingOperation",
       "MarkOperation",
       "MarkOperation",
       "MarkerGrading",
       "MarkerGrading",
-      "MarkerMarking"
+      "MarkerMarking",
     ],
     ],
     MARK_LEADER: () => ["LeaderGrading", "LeaderMarking"],
     MARK_LEADER: () => ["LeaderGrading", "LeaderMarking"],
-    INSPECTION: () => inspection.map(item => item.name),
-    QC: () => ["Quality"]
+    INSPECTION: () => inspection.map((item) => item.name),
+    QC: () => ["Quality"],
   };
   };
 
 
   const validList = func[roleCode]();
   const validList = func[roleCode]();

+ 154 - 154
src/constants/enumerate.js

@@ -1,154 +1,154 @@
-// 启用/禁用
-export const ABLE_TYPE = {
-  DISABLE: "禁用",
-  ENABLE: "启用"
-};
-
-// 性别
-export const GENDER_TYPE = {
-  MALE: "男",
-  FEMALE: "女"
-};
-
-export const BOOLEAN_TYPE = {
-  0: "否",
-  1: "是"
-};
-
-// subject step
-export const SUBJECT_STAGE = {
-  INIT: "采集阶段",
-  ROUGH_LEVEL: "粗分档阶段",
-  LEVEL: "分档阶段",
-  SCORE: "打分阶段"
-};
-
-// grading level
-export const LEVEL_TYPE = {
-  ADMITED: "间隔给分",
-  UNADMIT: "手动给分"
-};
-export const PROP_DENOMINATOR_TYPE = {
-  1: "全部考生数",
-  2: "去掉缺考考生数"
-};
-
-export const ROUGH_LEVEL_TYPE = {
-  1: "一",
-  2: "二",
-  3: "三",
-  4: "四",
-  5: "五",
-  6: "六",
-  7: "七",
-  8: "八",
-  9: "九"
-};
-
-// student score
-export const CODE_TYPE = {
-  examNumber: "试卷考号",
-  paper: "试卷密号",
-  task: "任务密号"
-};
-
-// role type
-export const ROLE_TYPE = {
-  MARKER: "评卷员",
-  MARK_LEADER: "科组长"
-};
-export const MARK_LEADER_RIGHTS = {
-  oneClickLevel: {
-    name: "一键定档",
-    action: "leveling"
-  },
-  standardVolume: {
-    name: "设立标准卷",
-    action: "sampling"
-  },
-  levelCallback: {
-    name: "建议档位打回",
-    action: "reject"
-  }
-};
-
-export const MARKER_RIGHT_TYPE = {
-  ALLOW_LEVELING: "只允许分档",
-  ALLOW_SCORING: "只允许打分",
-  ALLOW_ALL: "允许分档打分"
-};
-// sort
-export const SORT_ORDER_TYPE = {
-  0: "乱序",
-  1: "定序"
-};
-export const SORT_RULE_TYPE = {
-  1: "按时间",
-  2: "按考号"
-};
-// cafa-exception
-export const CAFA_EXCEPTION_TYPE = {
-  0: "缺考",
-  1: "手工绑定"
-  // 2: "关联考号"
-};
-
-// action-type
-export const ACTION_TYPE = {
-  1: "分档",
-  2: "打分",
-  3: "回评档位",
-  4: "回评分数",
-  5: "档位打回",
-  6: "档位打回回评",
-  7: "一键定档",
-  8: "标准卷设置",
-  9: "采集",
-  10: "系统自动打回",
-  11: "重评",
-  12: "手动打回",
-  13: "档位落差"
-};
-
-// image-name-type
-export const IMAGE_NAME_TYPE = {
-  0: "按考号命名",
-  1: "随机码命名"
-};
-export const EXPORT_IMAGE_NAME_TYPE = {
-  1: "考号+姓名",
-  2: "流水号"
-};
-// image-type
-export const IMAGE_TYPE = {
-  1: "原图",
-  2: "裁切图"
-};
-
-// paper-level-known-type
-export const PAPER_LEVEL_KNOWN_TYPE = {
-  0: "未知",
-  1: "已知"
-};
-// paper-upload-type
-export const PAPER_UPLOAD_TYPE = {
-  0: "未上传",
-  1: "已上传"
-};
-
-// score-handle-type
-export const SCORE_HANDLE_TYPE = {
-  0: "非零进一",
-  1: "四舍五入"
-};
-// score-calc-type
-export const SCORE_CALC_TYPE = {
-  0: "全部加权平均",
-  1: "去高去低加权平均"
-};
-
-// apply-change-level-status
-export const CHANGE_LEVEL_STATUS = {
-  0: "未处理",
-  1: "已处理"
-};
+// 启用/禁用
+export const ABLE_TYPE = {
+  DISABLE: "禁用",
+  ENABLE: "启用",
+};
+
+// 性别
+export const GENDER_TYPE = {
+  MALE: "男",
+  FEMALE: "女",
+};
+
+export const BOOLEAN_TYPE = {
+  0: "否",
+  1: "是",
+};
+
+// subject step
+export const SUBJECT_STAGE = {
+  INIT: "采集阶段",
+  ROUGH_LEVEL: "粗分档阶段",
+  LEVEL: "分档阶段",
+  SCORE: "打分阶段",
+};
+
+// grading level
+export const LEVEL_TYPE = {
+  ADMITED: "间隔给分",
+  UNADMIT: "手动给分",
+};
+export const PROP_DENOMINATOR_TYPE = {
+  1: "全部考生数",
+  2: "去掉缺考考生数",
+};
+
+export const ROUGH_LEVEL_TYPE = {
+  1: "一",
+  2: "二",
+  3: "三",
+  4: "四",
+  5: "五",
+  6: "六",
+  7: "七",
+  8: "八",
+  9: "九",
+};
+
+// student score
+export const CODE_TYPE = {
+  examNumber: "试卷考号",
+  paper: "试卷密号",
+  task: "任务密号",
+};
+
+// role type
+export const ROLE_TYPE = {
+  MARKER: "评卷员",
+  MARK_LEADER: "科组长",
+};
+export const MARK_LEADER_RIGHTS = {
+  oneClickLevel: {
+    name: "一键定档",
+    action: "leveling",
+  },
+  standardVolume: {
+    name: "设立标准卷",
+    action: "sampling",
+  },
+  levelCallback: {
+    name: "建议档位打回",
+    action: "reject",
+  },
+};
+
+export const MARKER_RIGHT_TYPE = {
+  ALLOW_LEVELING: "只允许分档",
+  ALLOW_SCORING: "只允许打分",
+  ALLOW_ALL: "允许分档打分",
+};
+// sort
+export const SORT_ORDER_TYPE = {
+  0: "乱序",
+  1: "定序",
+};
+export const SORT_RULE_TYPE = {
+  1: "按时间",
+  2: "按考号",
+};
+// cafa-exception
+export const CAFA_EXCEPTION_TYPE = {
+  0: "缺考",
+  1: "手工绑定",
+  // 2: "关联考号"
+};
+
+// action-type
+export const ACTION_TYPE = {
+  1: "分档",
+  2: "打分",
+  3: "回评档位",
+  4: "回评分数",
+  5: "档位打回",
+  6: "档位打回回评",
+  7: "一键定档",
+  8: "标准卷设置",
+  9: "采集",
+  10: "系统自动打回",
+  11: "重评",
+  12: "手动打回",
+  13: "档位落差",
+};
+
+// image-name-type
+export const IMAGE_NAME_TYPE = {
+  0: "按考号命名",
+  1: "随机码命名",
+};
+export const EXPORT_IMAGE_NAME_TYPE = {
+  1: "考号+姓名",
+  2: "流水号",
+};
+// image-type
+export const IMAGE_TYPE = {
+  1: "原图",
+  2: "裁切图",
+};
+
+// paper-level-known-type
+export const PAPER_LEVEL_KNOWN_TYPE = {
+  0: "未知",
+  1: "已知",
+};
+// paper-upload-type
+export const PAPER_UPLOAD_TYPE = {
+  0: "未上传",
+  1: "已上传",
+};
+
+// score-handle-type
+export const SCORE_HANDLE_TYPE = {
+  0: "非零进一",
+  1: "四舍五入",
+};
+// score-calc-type
+export const SCORE_CALC_TYPE = {
+  0: "全部加权平均",
+  1: "去高去低加权平均",
+};
+
+// apply-change-level-status
+export const CHANGE_LEVEL_STATUS = {
+  0: "未处理",
+  1: "已处理",
+};

+ 21 - 21
src/constants/navs.js

@@ -6,9 +6,9 @@ const navs = [
     children: [
     children: [
       {
       {
         title: "通用数据管理模板",
         title: "通用数据管理模板",
-        router: "DataManage"
-      }
-    ]
+        router: "DataManage",
+      },
+    ],
   },
   },
   {
   {
     title: "通用组件",
     title: "通用组件",
@@ -17,45 +17,45 @@ const navs = [
     children: [
     children: [
       {
       {
         title: "树形结构编辑",
         title: "树形结构编辑",
-        router: "TreeEditIntance"
+        router: "TreeEditIntance",
       },
       },
       {
       {
         title: "树形结构双选",
         title: "树形结构双选",
-        router: "TransferTreeInstance"
+        router: "TransferTreeInstance",
       },
       },
       {
       {
         title: "文件上传",
         title: "文件上传",
-        router: "ImportFileInstance"
+        router: "ImportFileInstance",
       },
       },
       {
       {
         title: "图片编辑上传",
         title: "图片编辑上传",
-        router: "ImageEditUploadInstance"
+        router: "ImageEditUploadInstance",
       },
       },
       {
       {
         title: "图片相册预览",
         title: "图片相册预览",
-        router: "ImagePreviewInstance"
+        router: "ImagePreviewInstance",
       },
       },
       {
       {
         title: "日历备忘",
         title: "日历备忘",
-        router: "CalendarMenoInstance"
+        router: "CalendarMenoInstance",
       },
       },
       {
       {
         title: "富文本编辑器",
         title: "富文本编辑器",
-        router: "RichEditInstance"
+        router: "RichEditInstance",
       },
       },
       {
       {
         title: "echart图表",
         title: "echart图表",
-        router: "VueEchartsInstance"
+        router: "VueEchartsInstance",
       },
       },
       {
       {
         title: "树形编辑",
         title: "树形编辑",
-        router: "TreeListEditInstance"
+        router: "TreeListEditInstance",
       },
       },
       {
       {
         title: "多流程控制器",
         title: "多流程控制器",
-        router: "StepsProgressInstance"
-      }
-    ]
+        router: "StepsProgressInstance",
+      },
+    ],
   },
   },
   {
   {
     title: "个人中心",
     title: "个人中心",
@@ -64,18 +64,18 @@ const navs = [
     children: [
     children: [
       {
       {
         title: "个人设置",
         title: "个人设置",
-        router: "UserSet"
+        router: "UserSet",
       },
       },
       {
       {
         title: "重置密码",
         title: "重置密码",
-        router: "ResetPswd"
+        router: "ResetPswd",
       },
       },
       {
       {
         title: "绑定手机",
         title: "绑定手机",
-        router: "BindMobile"
-      }
-    ]
-  }
+        router: "BindMobile",
+      },
+    ],
+  },
 ];
 ];
 
 
 export default navs;
 export default navs;

+ 120 - 120
src/main.js

@@ -1,120 +1,120 @@
-import Vue from "vue";
-import axios from "axios";
-
-import App from "./App.vue";
-import router from "./routers";
-import store from "./store";
-import GLOBAL from "./config";
-import globalVuePlugins from "./plugins/globalVuePlugins";
-
-// https://github.com/RobinCK/vue-ls
-import VueLocalStorage from "vue-ls";
-import ViewUI from "view-design";
-// import "view-design/dist/styles/iview.css";
-import "./assets/styles/index.less";
-// regist v-chart
-import "./plugins/VueCharts";
-import "./plugins/filters";
-
-import { checkRouterValid } from "./constants/authority";
-
-Vue.use(ViewUI);
-ViewUI.Message.config({
-  duration: 3
-});
-ViewUI.Notice.config({
-  duration: 3
-});
-Vue.use(VueLocalStorage, { storage: "session" });
-Vue.use(globalVuePlugins);
-
-Vue.prototype.GLOBAL = GLOBAL;
-
-Vue.config.productionTip = false;
-
-// route interceptor
-router.beforeEach((to, from, next) => {
-  const user = Vue.ls.get("user");
-  if (to.meta.noRequire) {
-    // 不需要登录的页面
-    next();
-  } else {
-    // 需要登录的路由
-    if (user && checkRouterValid(user["role"], to.name)) {
-      next();
-    } else {
-      ViewUI.Notice.error({ title: "错误提示", desc: "权限失效!" });
-      // 登录失效的处理
-      Vue.ls.clear();
-      next({ name: "Login" });
-    }
-  }
-});
-
-// axios interceptors
-var load = "";
-// 同一时间有多个请求时,会形成队列。在第一个请求创建loading,在最后一个响应关闭loading
-var queue = [];
-axios.interceptors.request.use(
-  config => {
-    // 显示loading提示
-    if (!queue.length && !config.hideLoad) {
-      load = ViewUI.Message.loading({
-        content: "Loading...",
-        duration: 0
-      });
-    }
-
-    queue.push(1);
-
-    // 为请求地址添加全局domain
-    if (config.url.indexOf("http://") < 0) {
-      config.url = GLOBAL.domain + config.url;
-    }
-
-    // 为请求头添加token信息
-    const user = Vue.ls.get("user", {});
-    if (user) {
-      config.headers["userId"] = user.id;
-      config.headers["workId"] = user.workId;
-      config.headers["Authorization"] = user.token;
-    }
-
-    // 设置延迟时效
-    config.timeout = GLOBAL.timeout;
-    return config;
-  },
-  error => {
-    // 关闭loading提示
-    // 继发请求,延时处理是为防止出现多个loading实例。
-    setTimeout(() => {
-      queue.shift();
-      if (!queue.length) load();
-    }, 100);
-    return Promise.reject(error);
-  }
-);
-axios.interceptors.response.use(
-  response => {
-    // 关闭loading提示
-    setTimeout(() => {
-      queue.shift();
-      if (!queue.length) load();
-    }, 100);
-    return response;
-  },
-  error => {
-    // 关闭loading提示
-    setTimeout(() => {
-      queue.shift();
-      if (!queue.length) load();
-    }, 100);
-    return Promise.reject(error);
-  }
-);
-
-new Vue({
-  router,
-  store,
-  render: h => h(App)
-}).$mount("#app");
+import Vue from "vue";
+import axios from "axios";
+
+import App from "./App.vue";
+import router from "./routers";
+import store from "./store";
+import GLOBAL from "./config";
+import globalVuePlugins from "./plugins/globalVuePlugins";
+
+// https://github.com/RobinCK/vue-ls
+import VueLocalStorage from "vue-ls";
+import ViewUI from "view-design";
+// import "view-design/dist/styles/iview.css";
+import "./assets/styles/index.less";
+// regist v-chart
+import "./plugins/VueCharts";
+import "./plugins/filters";
+
+import { checkRouterValid } from "./constants/authority";
+
+Vue.use(ViewUI);
+ViewUI.Message.config({
+  duration: 3,
+});
+ViewUI.Notice.config({
+  duration: 3,
+});
+Vue.use(VueLocalStorage, { storage: "session" });
+Vue.use(globalVuePlugins);
+
+Vue.prototype.GLOBAL = GLOBAL;
+
+Vue.config.productionTip = false;
+
+// route interceptor
+router.beforeEach((to, from, next) => {
+  const user = Vue.ls.get("user");
+  if (to.meta.noRequire) {
+    // 不需要登录的页面
+    next();
+  } else {
+    // 需要登录的路由
+    if (user && checkRouterValid(user["role"], to.name)) {
+      next();
+    } else {
+      ViewUI.Notice.error({ title: "错误提示", desc: "权限失效!" });
+      // 登录失效的处理
+      Vue.ls.clear();
+      next({ name: "Login" });
+    }
+  }
+});
+
+// axios interceptors
+var load = "";
+// 同一时间有多个请求时,会形成队列。在第一个请求创建loading,在最后一个响应关闭loading
+var queue = [];
+axios.interceptors.request.use(
+  (config) => {
+    // 显示loading提示
+    if (!queue.length && !config.hideLoad) {
+      load = ViewUI.Message.loading({
+        content: "Loading...",
+        duration: 0,
+      });
+    }
+
+    queue.push(1);
+
+    // 为请求地址添加全局domain
+    if (config.url.indexOf("http://") < 0) {
+      config.url = GLOBAL.domain + config.url;
+    }
+
+    // 为请求头添加token信息
+    const user = Vue.ls.get("user", {});
+    if (user) {
+      config.headers["userId"] = user.id;
+      config.headers["workId"] = user.workId;
+      config.headers["Authorization"] = user.token;
+    }
+
+    // 设置延迟时效
+    config.timeout = GLOBAL.timeout;
+    return config;
+  },
+  (error) => {
+    // 关闭loading提示
+    // 继发请求,延时处理是为防止出现多个loading实例。
+    setTimeout(() => {
+      queue.shift();
+      if (!queue.length) load();
+    }, 100);
+    return Promise.reject(error);
+  }
+);
+axios.interceptors.response.use(
+  (response) => {
+    // 关闭loading提示
+    setTimeout(() => {
+      queue.shift();
+      if (!queue.length) load();
+    }, 100);
+    return response;
+  },
+  (error) => {
+    // 关闭loading提示
+    setTimeout(() => {
+      queue.shift();
+      if (!queue.length) load();
+    }, 100);
+    return Promise.reject(error);
+  }
+);
+
+new Vue({
+  router,
+  store,
+  render: (h) => h(App),
+}).$mount("#app");

+ 17 - 17
src/modules/client-set/ClientAccountSet.vue

@@ -58,17 +58,17 @@ export default {
           title: "序号",
           title: "序号",
           width: 100,
           width: 100,
           align: "center",
           align: "center",
-          indexMethod: row => {
+          indexMethod: (row) => {
             return (this.current - 1) * this.size + row._index + 1;
             return (this.current - 1) * this.size + row._index + 1;
-          }
+          },
         },
         },
         {
         {
           title: "账号",
           title: "账号",
-          key: "loginName"
+          key: "loginName",
         },
         },
         {
         {
           title: "密码",
           title: "密码",
-          key: "password"
+          key: "password",
         },
         },
         {
         {
           title: "操作",
           title: "操作",
@@ -81,28 +81,28 @@ export default {
               {
               {
                 icon: param.row.enabled ? "enable icon" : "disable icon",
                 icon: param.row.enabled ? "enable icon" : "disable icon",
                 attrs: {
                 attrs: {
-                  title: param.row.enabled ? "禁用" : "启用"
+                  title: param.row.enabled ? "禁用" : "启用",
                 },
                 },
                 action: () => {
                 action: () => {
                   this.toAble(param.row);
                   this.toAble(param.row);
-                }
+                },
               },
               },
               {
               {
                 icon: "md-create",
                 icon: "md-create",
                 classes: [param.row.enabled ? "" : "btn-disabled"],
                 classes: [param.row.enabled ? "" : "btn-disabled"],
                 attrs: {
                 attrs: {
-                  title: "编辑"
+                  title: "编辑",
                 },
                 },
                 action: () => {
                 action: () => {
                   this.toEdit(param.row);
                   this.toEdit(param.row);
-                }
-              }
+                },
+              },
             ];
             ];
 
 
             return h("div", this.$tableIconAction(h, actions));
             return h("div", this.$tableIconAction(h, actions));
-          }
-        }
-      ]
+          },
+        },
+      ],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -113,7 +113,7 @@ export default {
       const datas = {
       const datas = {
         workId: this.workId,
         workId: this.workId,
         page: this.current - 1,
         page: this.current - 1,
-        size: this.size
+        size: this.size,
       };
       };
       const data = await clientUserPageList(datas);
       const data = await clientUserPageList(datas);
       this.users = data.data;
       this.users = data.data;
@@ -139,7 +139,7 @@ export default {
       await updateClientUser({
       await updateClientUser({
         id: row.id,
         id: row.id,
         loginName: row.loginName,
         loginName: row.loginName,
-        enabled: !row.enabled
+        enabled: !row.enabled,
       });
       });
       this.users[row._index].enabled = !row.enabled;
       this.users[row._index].enabled = !row.enabled;
     },
     },
@@ -149,14 +149,14 @@ export default {
         content: "确定要删除当前账号吗?",
         content: "确定要删除当前账号吗?",
         onOk: () => {
         onOk: () => {
           this.toDel(row.id);
           this.toDel(row.id);
-        }
+        },
       });
       });
     },
     },
     async toDel(id) {
     async toDel(id) {
       await deleteClientUser(id);
       await deleteClientUser(id);
       this.$Message.success("删除成功!");
       this.$Message.success("删除成功!");
       this.deletePageLastItem();
       this.deletePageLastItem();
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 279 - 279
src/modules/client-set/ClientParamSet.vue

@@ -1,279 +1,279 @@
-<template>
-  <div class="client-param-set">
-    <Row :gutter="20" type="flex">
-      <Col span="12">
-        <div class="part-box">
-          <h2 class="client-param-title">科目名称设置</h2>
-          <table class="table table-noborder">
-            <template v-for="(subject, index) in subjects">
-              <tr :key="index">
-                <td>
-                  <Input
-                    v-model="subject.name"
-                    @on-blur="checkSubjectValidate(subject)"
-                    :disabled="!subject.enable"
-                    :readonly="!subject.canEdit"
-                    :clearable="subject.canEdit"
-                    :ref="subject.id"
-                  ></Input>
-                </td>
-                <td style="width: 220px;">
-                  <Button
-                    size="small"
-                    :disabled="!subject.enable"
-                    @click="toEdit(index)"
-                    >编辑</Button
-                  >
-                  <Button
-                    size="small"
-                    :type="subject.enable ? 'error' : 'success'"
-                    @click="toAble(index)"
-                  >
-                    {{ subject.enable ? "禁用" : "启用" }}</Button
-                  >
-                  <Button
-                    size="small"
-                    :disabled="!subject.enable"
-                    @click="toSave(subject)"
-                    >保存</Button
-                  >
-                </td>
-              </tr>
-              <tr
-                class="tr-tips-error"
-                v-if="subject.errors"
-                :key="index + '1'"
-              >
-                <td>{{ subject.errors.name }}</td>
-                <td></td>
-              </tr>
-            </template>
-          </table>
-        </div>
-      </Col>
-      <Col span="12">
-        <div class="part-box">
-          <h2 class="client-param-title">其他设置</h2>
-          <Form ref="modalFormComp" :model="modalForm" :label-width="140">
-            <FormItem label="重复扫描大小异常:">
-              <InputNumber
-                v-model="modalForm.repeatScanSize"
-                :disabled="!modalFormCanEdit"
-                :min="0"
-                :max="102400"
-                :precision="0"
-                :active-change="false"
-                placeholder="输入数值"
-                clearable
-              />
-              <span style="margin-left:5px">KB</span>
-            </FormItem>
-            <FormItem label="是否整包扫描:">
-              <Select
-                v-model="modalForm.packageScan"
-                :disabled="!modalFormCanEdit"
-                placeholder="是否整包扫描"
-              >
-                <Option
-                  v-for="(val, key) in BOOLEAN_TYPE"
-                  :key="key"
-                  :value="key * 1"
-                  :label="val"
-                ></Option>
-              </Select>
-            </FormItem>
-            <FormItem label="图片是否加密:">
-              <Select
-                v-model="modalForm.imageEncrypt"
-                :disabled="!modalFormCanEdit"
-                placeholder="图片是否加密"
-              >
-                <Option
-                  v-for="(val, key) in BOOLEAN_TYPE"
-                  :key="key"
-                  :value="key * 1"
-                  :label="val"
-                ></Option>
-              </Select>
-            </FormItem>
-            <FormItem label="图片命名规则:">
-              <Select
-                v-model="modalForm.nameRule"
-                :disabled="!modalFormCanEdit"
-                placeholder="请选择图片命名规则"
-              >
-                <Option
-                  v-for="(val, key) in IMAGE_NAME_TYPE"
-                  :key="key"
-                  :value="key * 1"
-                  :label="val"
-                ></Option>
-              </Select>
-            </FormItem>
-            <FormItem label="试卷档位:">
-              <Select
-                v-model="modalForm.paperStage"
-                :disabled="!modalFormCanEdit"
-                placeholder="请选择试卷档位"
-              >
-                <Option
-                  v-for="(val, key) in PAPER_LEVEL_KNOWN_TYPE"
-                  :key="key"
-                  :value="key * 1"
-                  :label="val"
-                ></Option>
-              </Select>
-            </FormItem>
-            <FormItem>
-              <Button
-                shape="circle"
-                style="width: 80px;"
-                @click="modalFormCanEdit = true"
-                >编辑</Button
-              >
-              <Button
-                shape="circle"
-                type="primary"
-                style="width: 80px;"
-                :disabled="isSubmit"
-                @click="toSubmit"
-                >保存</Button
-              >
-            </FormItem>
-          </Form>
-        </div>
-      </Col>
-    </Row>
-  </div>
-</template>
-
-<script>
-import {
-  subjectList,
-  updateSubject,
-  enableSubject,
-  getParamsSet,
-  updateCollectParams
-} from "@/api";
-import {
-  BOOLEAN_TYPE,
-  IMAGE_NAME_TYPE,
-  PAPER_LEVEL_KNOWN_TYPE
-} from "@/constants/enumerate";
-import schema from "async-validator";
-schema.warning = function() {};
-
-const initSubject = {
-  id: "",
-  name: "",
-  enable: true,
-  canEdit: false,
-  password: ""
-};
-
-export default {
-  name: "client-param-set",
-  data() {
-    return {
-      BOOLEAN_TYPE,
-      IMAGE_NAME_TYPE,
-      PAPER_LEVEL_KNOWN_TYPE,
-      workId: this.$route.params.workId,
-      subjects: [],
-      // other param
-      isSubmit: false,
-      initModalForm: {
-        workId: "",
-        repeatScanSize: 0,
-        packageScan: 0,
-        imageEncrypt: 0,
-        nameRule: 0,
-        paperStage: 0
-      },
-      modalFormCanEdit: false,
-      modalForm: {}
-    };
-  },
-  mounted() {
-    this.modalForm = { ...this.initModalForm };
-    this.getList();
-    this.getParamsSetInfo();
-  },
-  methods: {
-    async getList() {
-      const data = await subjectList(this.workId);
-      this.subjects = data.map(item => {
-        return {
-          ...item,
-          canEdit: false
-        };
-      });
-    },
-
-    toAdd() {
-      this.subjects.push({ ...initSubject });
-    },
-    toEdit(index) {
-      const row = this.subjects[index];
-      row.canEdit = true;
-      this.$refs[row.id][0].focus();
-    },
-    async toAble(index) {
-      const row = this.subjects[index];
-      await enableSubject(row.id);
-      row.enable = !row.enable;
-    },
-    checkSubjectValidate(subject) {
-      const descriptor = {
-        name: [
-          {
-            required: true,
-            min: 2,
-            max: 20,
-            message: "科目名称长度只能介于2到20之间"
-          }
-        ]
-      };
-      return new schema(descriptor)
-        .validate(subject)
-        .then(() => {
-          if (subject.errors) subject.errors = null;
-        })
-        .catch(({ errors, fields }) => {
-          let errorMsgs = {};
-          errors.map(error => {
-            errorMsgs[error.field] = error.message;
-          });
-          this.$set(subject, "errors", errorMsgs);
-          return { errors };
-        });
-    },
-    async toSave(row) {
-      const result = await this.checkSubjectValidate(row);
-      if (result) return;
-
-      await updateSubject(row);
-      row.canEdit = false;
-      this.$Message.success("保存成功!");
-    },
-    // param-set
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.modalForm = this.$objAssign(this.modalForm, data.collectConfig);
-    },
-    async toSubmit() {
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-
-      let result = true;
-      await updateCollectParams(this.modalForm).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-      if (!result) return;
-      this.modalFormCanEdit = false;
-      this.$Message.success("保存成功!");
-    }
-  }
-};
-</script>
+<template>
+  <div class="client-param-set">
+    <Row :gutter="20" type="flex">
+      <Col span="12">
+        <div class="part-box">
+          <h2 class="client-param-title">科目名称设置</h2>
+          <table class="table table-noborder">
+            <template v-for="(subject, index) in subjects">
+              <tr :key="index">
+                <td>
+                  <Input
+                    v-model="subject.name"
+                    @on-blur="checkSubjectValidate(subject)"
+                    :disabled="!subject.enable"
+                    :readonly="!subject.canEdit"
+                    :clearable="subject.canEdit"
+                    :ref="subject.id"
+                  ></Input>
+                </td>
+                <td style="width: 220px">
+                  <Button
+                    size="small"
+                    :disabled="!subject.enable"
+                    @click="toEdit(index)"
+                    >编辑</Button
+                  >
+                  <Button
+                    size="small"
+                    :type="subject.enable ? 'error' : 'success'"
+                    @click="toAble(index)"
+                  >
+                    {{ subject.enable ? "禁用" : "启用" }}</Button
+                  >
+                  <Button
+                    size="small"
+                    :disabled="!subject.enable"
+                    @click="toSave(subject)"
+                    >保存</Button
+                  >
+                </td>
+              </tr>
+              <tr
+                class="tr-tips-error"
+                v-if="subject.errors"
+                :key="index + '1'"
+              >
+                <td>{{ subject.errors.name }}</td>
+                <td></td>
+              </tr>
+            </template>
+          </table>
+        </div>
+      </Col>
+      <Col span="12">
+        <div class="part-box">
+          <h2 class="client-param-title">其他设置</h2>
+          <Form ref="modalFormComp" :model="modalForm" :label-width="140">
+            <FormItem label="重复扫描大小异常:">
+              <InputNumber
+                v-model="modalForm.repeatScanSize"
+                :disabled="!modalFormCanEdit"
+                :min="0"
+                :max="102400"
+                :precision="0"
+                :active-change="false"
+                placeholder="输入数值"
+                clearable
+              />
+              <span style="margin-left: 5px">KB</span>
+            </FormItem>
+            <FormItem label="是否整包扫描:">
+              <Select
+                v-model="modalForm.packageScan"
+                :disabled="!modalFormCanEdit"
+                placeholder="是否整包扫描"
+              >
+                <Option
+                  v-for="(val, key) in BOOLEAN_TYPE"
+                  :key="key"
+                  :value="key * 1"
+                  :label="val"
+                ></Option>
+              </Select>
+            </FormItem>
+            <FormItem label="图片是否加密:">
+              <Select
+                v-model="modalForm.imageEncrypt"
+                :disabled="!modalFormCanEdit"
+                placeholder="图片是否加密"
+              >
+                <Option
+                  v-for="(val, key) in BOOLEAN_TYPE"
+                  :key="key"
+                  :value="key * 1"
+                  :label="val"
+                ></Option>
+              </Select>
+            </FormItem>
+            <FormItem label="图片命名规则:">
+              <Select
+                v-model="modalForm.nameRule"
+                :disabled="!modalFormCanEdit"
+                placeholder="请选择图片命名规则"
+              >
+                <Option
+                  v-for="(val, key) in IMAGE_NAME_TYPE"
+                  :key="key"
+                  :value="key * 1"
+                  :label="val"
+                ></Option>
+              </Select>
+            </FormItem>
+            <FormItem label="试卷档位:">
+              <Select
+                v-model="modalForm.paperStage"
+                :disabled="!modalFormCanEdit"
+                placeholder="请选择试卷档位"
+              >
+                <Option
+                  v-for="(val, key) in PAPER_LEVEL_KNOWN_TYPE"
+                  :key="key"
+                  :value="key * 1"
+                  :label="val"
+                ></Option>
+              </Select>
+            </FormItem>
+            <FormItem>
+              <Button
+                shape="circle"
+                style="width: 80px"
+                @click="modalFormCanEdit = true"
+                >编辑</Button
+              >
+              <Button
+                shape="circle"
+                type="primary"
+                style="width: 80px"
+                :disabled="isSubmit"
+                @click="toSubmit"
+                >保存</Button
+              >
+            </FormItem>
+          </Form>
+        </div>
+      </Col>
+    </Row>
+  </div>
+</template>
+
+<script>
+import {
+  subjectList,
+  updateSubject,
+  enableSubject,
+  getParamsSet,
+  updateCollectParams,
+} from "@/api";
+import {
+  BOOLEAN_TYPE,
+  IMAGE_NAME_TYPE,
+  PAPER_LEVEL_KNOWN_TYPE,
+} from "@/constants/enumerate";
+import schema from "async-validator";
+schema.warning = function () {};
+
+const initSubject = {
+  id: "",
+  name: "",
+  enable: true,
+  canEdit: false,
+  password: "",
+};
+
+export default {
+  name: "client-param-set",
+  data() {
+    return {
+      BOOLEAN_TYPE,
+      IMAGE_NAME_TYPE,
+      PAPER_LEVEL_KNOWN_TYPE,
+      workId: this.$route.params.workId,
+      subjects: [],
+      // other param
+      isSubmit: false,
+      initModalForm: {
+        workId: "",
+        repeatScanSize: 0,
+        packageScan: 0,
+        imageEncrypt: 0,
+        nameRule: 0,
+        paperStage: 0,
+      },
+      modalFormCanEdit: false,
+      modalForm: {},
+    };
+  },
+  mounted() {
+    this.modalForm = { ...this.initModalForm };
+    this.getList();
+    this.getParamsSetInfo();
+  },
+  methods: {
+    async getList() {
+      const data = await subjectList(this.workId);
+      this.subjects = data.map((item) => {
+        return {
+          ...item,
+          canEdit: false,
+        };
+      });
+    },
+
+    toAdd() {
+      this.subjects.push({ ...initSubject });
+    },
+    toEdit(index) {
+      const row = this.subjects[index];
+      row.canEdit = true;
+      this.$refs[row.id][0].focus();
+    },
+    async toAble(index) {
+      const row = this.subjects[index];
+      await enableSubject(row.id);
+      row.enable = !row.enable;
+    },
+    checkSubjectValidate(subject) {
+      const descriptor = {
+        name: [
+          {
+            required: true,
+            min: 2,
+            max: 20,
+            message: "科目名称长度只能介于2到20之间",
+          },
+        ],
+      };
+      return new schema(descriptor)
+        .validate(subject)
+        .then(() => {
+          if (subject.errors) subject.errors = null;
+        })
+        .catch(({ errors, fields }) => {
+          let errorMsgs = {};
+          errors.map((error) => {
+            errorMsgs[error.field] = error.message;
+          });
+          this.$set(subject, "errors", errorMsgs);
+          return { errors };
+        });
+    },
+    async toSave(row) {
+      const result = await this.checkSubjectValidate(row);
+      if (result) return;
+
+      await updateSubject(row);
+      row.canEdit = false;
+      this.$Message.success("保存成功!");
+    },
+    // param-set
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.modalForm = this.$objAssign(this.modalForm, data.collectConfig);
+    },
+    async toSubmit() {
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+
+      let result = true;
+      await updateCollectParams(this.modalForm).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+      if (!result) return;
+      this.modalFormCanEdit = false;
+      this.$Message.success("保存成功!");
+    },
+  },
+};
+</script>

+ 5 - 5
src/modules/client-set/ClientSet.vue

@@ -4,7 +4,7 @@
       <div
       <div
         :class="[
         :class="[
           'set-navs-item',
           'set-navs-item',
-          { 'set-navs-item-act': curNav.name === nav.name }
+          { 'set-navs-item-act': curNav.name === nav.name },
         ]"
         ]"
         v-for="(nav, index) in navs"
         v-for="(nav, index) in navs"
         :key="index"
         :key="index"
@@ -28,19 +28,19 @@ export default {
   data() {
   data() {
     return {
     return {
       navs: clientSet,
       navs: clientSet,
-      curNav: {}
+      curNav: {},
     };
     };
   },
   },
   watch: {
   watch: {
     $route: {
     $route: {
       handler(val) {
       handler(val) {
         this.actCurNav(val);
         this.actCurNav(val);
-      }
-    }
+      },
+    },
   },
   },
   mounted() {
   mounted() {
     this.actCurNav(this.$route);
     this.actCurNav(this.$route);
   },
   },
-  methods: {}
+  methods: {},
 };
 };
 </script>
 </script>

+ 16 - 16
src/modules/client-set/InspectionAccountSet.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <div class="client-account-set ">
+  <div class="client-account-set">
     <Table
     <Table
       ref="TableList"
       ref="TableList"
       :columns="columns"
       :columns="columns"
@@ -17,7 +17,7 @@ const initModalForm = {
   id: "",
   id: "",
   roleName: "纪检",
   roleName: "纪检",
   loginName: "",
   loginName: "",
-  password: ""
+  password: "",
 };
 };
 
 
 export default {
 export default {
@@ -33,17 +33,17 @@ export default {
           title: "序号",
           title: "序号",
           width: 100,
           width: 100,
           align: "center",
           align: "center",
-          indexMethod: row => {
+          indexMethod: (row) => {
             return row._index + 1;
             return row._index + 1;
-          }
+          },
         },
         },
         {
         {
           title: "角色",
           title: "角色",
-          key: "roleName"
+          key: "roleName",
         },
         },
         {
         {
           title: "账号",
           title: "账号",
-          key: "loginName"
+          key: "loginName",
         },
         },
         {
         {
           title: "密码",
           title: "密码",
@@ -58,14 +58,14 @@ export default {
                 type: "text",
                 type: "text",
                 action: () => {
                 action: () => {
                   this.toResetPwd(param.row);
                   this.toResetPwd(param.row);
-                }
-              }
+                },
+              },
             ];
             ];
 
 
             return h("div", this.$tableAction(h, actions));
             return h("div", this.$tableAction(h, actions));
-          }
-        }
-      ]
+          },
+        },
+      ],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -74,16 +74,16 @@ export default {
   methods: {
   methods: {
     async getList() {
     async getList() {
       const datas = {
       const datas = {
-        workId: this.workId
+        workId: this.workId,
       };
       };
       const data = await inspectionUserPageList(datas);
       const data = await inspectionUserPageList(datas);
 
 
-      this.users = data.map(item => {
+      this.users = data.map((item) => {
         return {
         return {
           id: item.id,
           id: item.id,
           loginName: item.loginName,
           loginName: item.loginName,
           password: item.password,
           password: item.password,
-          roleName: "纪检"
+          roleName: "纪检",
         };
         };
       });
       });
     },
     },
@@ -98,7 +98,7 @@ export default {
 
 
       if (!result) return;
       if (!result) return;
       this.$Message.success("重置密码成功!");
       this.$Message.success("重置密码成功!");
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 10 - 10
src/modules/client-set/components/ModifyClientUser.vue

@@ -47,7 +47,7 @@ import { password } from "@/plugins/formRules";
 const initModalForm = {
 const initModalForm = {
   id: "",
   id: "",
   loginName: "",
   loginName: "",
-  password: ""
+  password: "",
 };
 };
 
 
 export default {
 export default {
@@ -57,8 +57,8 @@ export default {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
-    }
+      },
+    },
   },
   },
   computed: {
   computed: {
     isEdit() {
     isEdit() {
@@ -66,7 +66,7 @@ export default {
     },
     },
     title() {
     title() {
       return (this.isEdit ? "编辑" : "新增") + "采集账号";
       return (this.isEdit ? "编辑" : "新增") + "采集账号";
-    }
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -79,11 +79,11 @@ export default {
             required: true,
             required: true,
             pattern: /^[a-zA-Z0-9_-]{3,20}$/,
             pattern: /^[a-zA-Z0-9_-]{3,20}$/,
             message: "账号只能包含字母、数字、下划线以及短横线,长度3-20位",
             message: "账号只能包含字母、数字、下划线以及短横线,长度3-20位",
-            trigger: "change"
-          }
+            trigger: "change",
+          },
         ],
         ],
-        password
-      }
+        password,
+      },
     };
     };
   },
   },
   methods: {
   methods: {
@@ -123,7 +123,7 @@ export default {
       this.$Message.success(this.title + "成功!");
       this.$Message.success(this.title + "成功!");
       this.$emit("modified");
       this.$emit("modified");
       this.cancel();
       this.cancel();
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 636 - 637
src/modules/grading-set/GradingLevelSet.vue

@@ -1,637 +1,636 @@
-<template>
-  <div class="grading-level-set">
-    <Button
-      class="level-add-btn"
-      type="success"
-      icon="recode-white icon"
-      shape="circle"
-      @click="toAdd"
-      >新增档位</Button
-    >
-    <table class="table table-noborder grading-table">
-      <tr>
-        <th>档位</th>
-        <th>最低分</th>
-        <th>最高分</th>
-        <th>给分间隔</th>
-        <th>典型值</th>
-        <th>类型</th>
-        <th>给分项</th>
-        <template v-if="roughLevelEnable">
-          <th>粗档位</th>
-          <th>粗档位典型值</th>
-        </template>
-        <th>考区阈值%</th>
-        <th>占比阈值%</th>
-        <th>操作</th>
-      </tr>
-      <template v-for="(level, index) in levels">
-        <tr :key="index">
-          <td>
-            <Input
-              v-model="level.code"
-              style="width: 60px"
-              @on-blur="codeChange(level)"
-              v-if="level.canEdit && workDetail.modifyOtherVal"
-            ></Input>
-            <p v-else>{{ level.code }}</p>
-          </td>
-          <td>
-            <InputNumber
-              v-model="level.minScore"
-              :min="0"
-              :max="1000"
-              @on-blur="checkLevelValidate(level)"
-              @on-change="checkRoughCodeValidate()"
-              v-if="level.canEdit && workDetail.modifyOtherVal"
-            ></InputNumber>
-            <p v-else>{{ level.minScore }}</p>
-          </td>
-          <td>
-            <InputNumber
-              v-model="level.maxScore"
-              :min="1"
-              :max="1000"
-              @on-blur="checkLevelValidate(level)"
-              @on-change="checkRoughCodeValidate()"
-              v-if="level.canEdit && workDetail.modifyOtherVal"
-            ></InputNumber>
-            <p v-else>{{ level.maxScore }}</p>
-          </td>
-          <td style="min-width: 100px">
-            <InputNumber
-              v-model="level.intervalScore"
-              :min="1"
-              :max="100"
-              :precision="0"
-              :disabled="!level.canEdit"
-              @on-blur="checkLevelValidate(level)"
-              v-if="
-                level.levelType === 'ADMITED' &&
-                  level.canEdit &&
-                  workDetail.modifyOtherVal
-              "
-            ></InputNumber>
-            <p v-else>{{ level.intervalScore }}</p>
-          </td>
-          <td>
-            <InputNumber
-              v-model="level.weight"
-              :min="1"
-              :max="1000"
-              @on-blur="checkLevelValidate(level)"
-              v-if="level.canEdit && workDetail.modifyOtherVal"
-            ></InputNumber>
-            <p v-else>{{ level.weight }}</p>
-          </td>
-          <td>
-            <Select
-              v-model="level.levelType"
-              @on-change="levelTypeChange(level)"
-              style="width: 120px"
-              v-if="level.canEdit && workDetail.modifyOtherVal"
-            >
-              <Option
-                v-for="(val, key) in LEVEL_TYPE"
-                :key="key"
-                :value="key"
-                >{{ val }}</Option
-              >
-            </Select>
-            <p v-else>{{ LEVEL_TYPE[level.levelType] }}</p>
-          </td>
-          <td style="min-width: 140px">
-            <Input
-              v-model="level.scoreList"
-              @on-blur="checkLevelValidate(level)"
-              v-if="
-                level.levelType === 'UNADMIT' &&
-                  level.canEdit &&
-                  workDetail.modifyOtherVal
-              "
-            ></Input>
-            <p v-else>{{ level.scoreList }}</p>
-          </td>
-          <template v-if="roughLevelEnable">
-            <!-- rough_code -->
-            <td>
-              <Select
-                v-model="level.roughCode"
-                @on-change="roughCodeChange(level)"
-                style="min-width: 80px"
-                v-if="level.canEdit && workDetail.modifyOtherVal"
-              >
-                <Option
-                  v-for="(val, key) in ROUGH_LEVEL_TYPE"
-                  :key="key"
-                  :value="key * 1"
-                  >{{ val }}</Option
-                >
-              </Select>
-              <p v-else>{{ ROUGH_LEVEL_TYPE[level.roughCode] }}</p>
-            </td>
-            <!-- rough_weight -->
-            <td>
-              <InputNumber
-                v-model="level.roughWeight"
-                :min="1"
-                :max="100"
-                @on-change="roughWeightChange(level)"
-                v-if="level.canEdit && workDetail.modifyOtherVal"
-              ></InputNumber>
-              <p v-else>{{ level.roughWeight }}</p>
-            </td>
-          </template>
-          <td>
-            <InputNumber
-              v-model="level.kdpt"
-              :min="1"
-              :max="100"
-              @on-blur="checkLevelValidate(level)"
-              v-if="level.canEdit"
-            ></InputNumber>
-            <p v-else>{{ level.kdpt }}</p>
-          </td>
-          <td>
-            <InputNumber
-              v-model="level.pt"
-              :min="1"
-              :max="100"
-              @on-blur="checkLevelValidate(level)"
-              v-if="level.canEdit"
-            ></InputNumber>
-            <p v-else>{{ level.pt }}</p>
-          </td>
-          <td class="table-action">
-            <div style="width: 60px">
-              <Icon type="md-create" title="编辑" @click="toEdit(index)" />
-              <Icon
-                class="icon-danger"
-                type="md-trash"
-                title="删除"
-                @click="toDelete(index)"
-                v-if="workDetail.modifyOtherVal"
-              />
-            </div>
-          </td>
-        </tr>
-        <tr class="tr-tips-error" v-if="level.errors" :key="index + '1'">
-          <td>
-            {{ level.errors.code }}
-          </td>
-          <td>
-            {{ level.errors.minScore }}
-          </td>
-          <td>
-            {{ level.errors.maxScore }}
-          </td>
-          <td>
-            {{ level.errors.intervalScore }}
-          </td>
-          <td>
-            {{ level.errors.weight }}
-          </td>
-          <td></td>
-          <td>
-            {{ level.errors.scoreList }}
-          </td>
-          <template v-if="roughLevelEnable">
-            <td>
-              {{ level.errors.roughCode }}
-            </td>
-            <td>
-              {{ level.errors.roughWeight }}
-            </td>
-          </template>
-          <td>
-            {{ level.errors.kdpt }}
-          </td>
-          <td>
-            {{ level.errors.pt }}
-          </td>
-          <td></td>
-        </tr>
-      </template>
-    </table>
-
-    <div class="text-center">
-      <Button
-        type="primary"
-        shape="circle"
-        @click="toSubmit"
-        style="width: 80px;"
-        :disabled="isSubmit"
-        >确定</Button
-      >
-      <!-- <Checkbox v-model="roughLevelEnable">roughLevelEnable</Checkbox> -->
-    </div>
-  </div>
-</template>
-
-<script>
-import { workDetail, updateWork, getParamsSet } from "@/api";
-import { LEVEL_TYPE, ROUGH_LEVEL_TYPE } from "@/constants/enumerate";
-import schema from "async-validator";
-schema.warning = function() {};
-
-const initLevel = {
-  id: null,
-  workId: null,
-  code: null,
-  levelValue: 0,
-  maxScore: null,
-  minScore: null,
-  intervalScore: null,
-  weight: null,
-  roughCode: null,
-  roughWeight: null,
-  levelType: "ADMITED",
-  scoreList: null,
-  pt: null,
-  kdpt: null
-};
-
-export default {
-  name: "grading-level-set",
-  data() {
-    return {
-      LEVEL_TYPE,
-      ROUGH_LEVEL_TYPE,
-      workId: this.$route.params.workId,
-      letterRelateNumber: {},
-      levels: [],
-      workDetail: {},
-      isSubmit: false,
-      roughLevelEnable: false
-    };
-  },
-  mounted() {
-    this.initData();
-  },
-  methods: {
-    initData() {
-      const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-      letters.split("").map((item, index) => {
-        this.letterRelateNumber[item] = index + 1;
-      });
-
-      this.getData();
-      this.getParamsSetInfo();
-    },
-    async getData() {
-      const data = await workDetail(this.workId);
-      this.workDetail = data;
-      this.levels = data.levels.map(item => {
-        let nitem = { ...item };
-        nitem.canEdit = false;
-        nitem.roughCode = nitem.roughCode * 1;
-        return nitem;
-      });
-    },
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.roughLevelEnable = data.levelConfig.roughLevelEnable;
-    },
-    checkLevelCodeIsContinuous() {
-      let levelIsContinuous = true;
-      for (var i = 0, num = this.levels.length; i < num; i++) {
-        if (i > 0) {
-          const beforeCodeNum = this.letterRelateNumber[
-            this.levels[i - 1].code
-          ];
-          const curCodeNum = this.letterRelateNumber[this.levels[i].code];
-          levelIsContinuous =
-            levelIsContinuous && curCodeNum - beforeCodeNum === 1;
-
-          if (!levelIsContinuous) {
-            return false;
-          }
-        }
-      }
-
-      return true;
-    },
-    levelTypeChange(level) {
-      if (level.levelType === "ADMITED") {
-        level.scoreList = null;
-      } else {
-        level.intervalScore = null;
-      }
-    },
-    codeChange(level) {
-      level.code = level.code.toUpperCase();
-      this.levels.sort((a, b) => {
-        if (
-          !a.code ||
-          !b.code ||
-          !this.letterRelateNumber[a.code] ||
-          !this.letterRelateNumber[b.code]
-        )
-          return 0;
-
-        return (
-          this.letterRelateNumber[a.code] - this.letterRelateNumber[b.code]
-        );
-      });
-      this.checkLevelValidate(level);
-    },
-    getNextLevelCode() {
-      const codeNumbers = this.levels.map(
-        level => this.letterRelateNumber[level.code] || 0
-      );
-      const maxCodeNumber = Math.max.apply(null, codeNumbers);
-      const nextLevel = Object.entries(this.letterRelateNumber).find(
-        ([key, val]) => {
-          return maxCodeNumber < val;
-        }
-      );
-      return nextLevel ? nextLevel[0] : "";
-    },
-    toAdd() {
-      let level = { ...initLevel };
-      level.workId = this.workId;
-      level.code = this.getNextLevelCode();
-      this.levels.push(level);
-    },
-    toEdit(index) {
-      this.levels[index].canEdit = true;
-      this.$forceUpdate();
-    },
-    toDelete(index) {
-      this.levels.splice(index, 1);
-    },
-    roughCodeChange(level) {
-      let codeWeight = {};
-      this.levels.forEach(item => {
-        if (item.roughCode && item.roughWeight) {
-          codeWeight[item.roughCode] = item.roughWeight;
-        }
-      });
-      level.roughWeight = codeWeight[level.roughCode] || null;
-
-      this.checkRoughCodeValidate();
-    },
-    roughWeightChange(level) {
-      this.levels
-        .filter(
-          item =>
-            item.roughCode &&
-            item.roughCode === level.roughCode &&
-            item.code !== level.code
-        )
-        .forEach(item => {
-          item.roughWeight = level.roughWeight;
-        });
-      this.checkRoughCodeValidate();
-    },
-    resetError(errors, fields, fieldVals) {
-      if (!errors) return null;
-      let nerrors = { ...errors };
-      fields.forEach(field => {
-        if (fieldVals && fieldVals[field]) {
-          this.$set(nerrors, field, fieldVals[field]);
-        } else {
-          delete nerrors[field];
-        }
-      });
-      return Object.keys(nerrors).length ? nerrors : null;
-    },
-    checkLevelValidate(level) {
-      const descriptor = {
-        code: {
-          type: "string",
-          required: true,
-          pattern: /^[A-Z]{1}$/,
-          message: "请输入单个大写字母"
-        },
-        minScore: {
-          type: "number",
-          required: true,
-          message: "请输入最低分"
-        },
-        maxScore: {
-          type: "number",
-          required: true,
-          validator: (rule, value, callback) => {
-            if (!value || value < level.minScore) {
-              callback(new Error("最高分不得小于最低分"));
-            } else {
-              callback();
-            }
-          }
-        },
-        intervalScore: {
-          type: "number",
-          validator: (rule, value, callback) => {
-            if (level.levelType === "ADMITED" && !value) {
-              callback(new Error("请输入给分间隔"));
-            } else {
-              callback();
-            }
-          }
-        },
-        weight: {
-          type: "number",
-          validator: (rule, value, callback) => {
-            if (!value) return callback(new Error("请输入典型值"));
-
-            if (value < level.minScore || value > level.maxScore) {
-              return callback(
-                new Error(
-                  `典型值只能介于${level.minScore}和${level.maxScore}之间`
-                )
-              );
-            }
-
-            callback();
-          }
-        },
-        scoreList: {
-          type: "string",
-          validator: (rule, value, callback) => {
-            if (level.levelType !== "UNADMIT") return callback();
-
-            if (level.levelType === "UNADMIT" && !value) {
-              return callback(new Error("请输入给分项"));
-            }
-            if (!value.match(/^[0-9,]+$/)) {
-              return callback(new Error("给分项只能包含数字和英文逗号"));
-            }
-            const unvalid = value
-              .split(",")
-              .filter(item => item)
-              .some(item => {
-                const num = item * 1;
-                return num < level.minScore || num > level.maxScore;
-              });
-            if (unvalid) {
-              return callback(
-                new Error("给分项包含的分值只能介于最低分和最高分之间")
-              );
-            }
-
-            callback();
-          }
-        },
-        pt: {
-          type: "number",
-          required: true,
-          message: "请输入占比阀值"
-        },
-        kdpt: {
-          type: "number",
-          required: true,
-          message: "请输入考区阀值"
-        }
-      };
-      const fields = Object.keys(descriptor);
-      return new schema(descriptor)
-        .validate(level)
-        .then(() => {
-          this.$set(level, "errors", this.resetError(level.errors, fields));
-        })
-        .catch(({ errors }) => {
-          if (!errors) return;
-
-          let errorMsgs = {};
-          errors.map(error => {
-            errorMsgs[error.field] = error.message;
-          });
-          this.$set(
-            level,
-            "errors",
-            this.resetError(level.errors || {}, fields, errorMsgs)
-          );
-          return errors;
-        });
-    },
-    async checkRoughCodeValidate(checkCodeRequired) {
-      if (!this.roughLevelEnable) return;
-      let weightRanges = {};
-      this.levels.forEach(level => {
-        if (!level.roughCode) return;
-        let range = weightRanges[level.roughCode] || {
-          sn: 100,
-          en: 0
-        };
-        range.sn = Math.min(range.sn, level.minScore);
-        range.en = Math.max(range.en, level.maxScore);
-        weightRanges[level.roughCode] = range;
-      });
-
-      const roughCodeValidate = level => {
-        const descriptor = {
-          roughCode: {
-            validator: (rule, value, callback) => {
-              if (!checkCodeRequired && !value) return callback();
-
-              if (checkCodeRequired && !value)
-                return callback(new Error(`请选择粗档位`));
-
-              const pos = this.levels.findIndex(
-                item => item.code === level.code
-              );
-              if (pos === 0 && value !== 1)
-                return callback(new Error(`只能选择粗档位"一"`));
-
-              if (pos > 0) {
-                const prevLevel = this.levels[pos - 1];
-                if (prevLevel && prevLevel.roughCode) {
-                  const codeDis = value - prevLevel.roughCode;
-                  if (codeDis < 0 || codeDis > 1) {
-                    return callback(new Error(`请保持粗档位连续`));
-                  }
-                }
-
-                // const nextLevel = this.levels[pos + 1];
-                // if (nextLevel && nextLevel.roughCode) {
-                //   const codeDis = nextLevel.roughCode - value;
-                //   if (codeDis < 0 || codeDis > 1) {
-                //     return callback(new Error(`请保持粗档位连续`));
-                //   }
-                // }
-              }
-
-              callback();
-            }
-          },
-          roughWeight: {
-            validator: (rule, value, callback) => {
-              if (!checkCodeRequired) {
-                if (level.roughCode && !value)
-                  return callback(new Error(`请输入粗档位典型值`));
-                if (!level.roughCode) return callback();
-              }
-              if (checkCodeRequired && !value)
-                return callback(new Error(`请输入粗档位典型值`));
-
-              const range = weightRanges[level.roughCode];
-              if (value < range.sn || value > range.en)
-                return callback(
-                  new Error(`粗档位典型值只能介于${range.sn}和${range.en}之间`)
-                );
-
-              callback();
-            }
-          }
-        };
-        const fields = Object.keys(descriptor);
-
-        return new schema(descriptor)
-          .validate(level)
-          .then(() => {
-            this.$set(level, "errors", this.resetError(level.errors, fields));
-          })
-          .catch(({ errors }) => {
-            if (!errors) return;
-            let errorMsgs = {};
-            errors.map(error => {
-              errorMsgs[error.field] = error.message;
-            });
-            this.$set(
-              level,
-              "errors",
-              this.resetError(level.errors || {}, fields, errorMsgs)
-            );
-            return errors;
-          });
-      };
-
-      const validatorAll = this.levels.map(level => roughCodeValidate(level));
-      const result = await Promise.all(validatorAll);
-      const hasUnvalidate = result.some(item => !!item);
-
-      return hasUnvalidate;
-    },
-    async toSubmit() {
-      const validatorAll = this.levels.map(level =>
-        this.checkLevelValidate(level)
-      );
-      const result = await Promise.all(validatorAll);
-      let hasUnvalidate = result.some(item => !!item);
-      if (hasUnvalidate) return;
-
-      hasUnvalidate = await this.checkRoughCodeValidate(true);
-      if (hasUnvalidate) return;
-
-      if (!this.checkLevelCodeIsContinuous()) {
-        this.$Message.error("请保持档位连续!");
-        return;
-      }
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      this.workDetail.levels = this.levels;
-      const data = await updateWork(this.workDetail).catch(() => {
-        this.isSubmit = false;
-      });
-
-      if (!data) return;
-
-      this.isSubmit = false;
-      this.getData();
-      this.$Message.success("保存成功!");
-    }
-  }
-};
-</script>
+<template>
+  <div class="grading-level-set">
+    <Button
+      class="level-add-btn"
+      type="success"
+      icon="recode-white icon"
+      shape="circle"
+      @click="toAdd"
+      >新增档位</Button
+    >
+    <table class="table table-noborder grading-table">
+      <tr>
+        <th>档位</th>
+        <th>最低分</th>
+        <th>最高分</th>
+        <th>给分间隔</th>
+        <th>典型值</th>
+        <th>类型</th>
+        <th>给分项</th>
+        <template v-if="roughLevelEnable">
+          <th>粗档位</th>
+          <th>粗档位典型值</th>
+        </template>
+        <th>考区阈值%</th>
+        <th>占比阈值%</th>
+        <th>操作</th>
+      </tr>
+      <template v-for="(level, index) in levels">
+        <tr :key="index">
+          <td>
+            <Input
+              v-model="level.code"
+              style="width: 60px"
+              @on-blur="codeChange(level)"
+              v-if="level.canEdit && workDetail.modifyOtherVal"
+            ></Input>
+            <p v-else>{{ level.code }}</p>
+          </td>
+          <td>
+            <InputNumber
+              v-model="level.minScore"
+              :min="0"
+              :max="1000"
+              @on-blur="checkLevelValidate(level)"
+              @on-change="checkRoughCodeValidate()"
+              v-if="level.canEdit && workDetail.modifyOtherVal"
+            ></InputNumber>
+            <p v-else>{{ level.minScore }}</p>
+          </td>
+          <td>
+            <InputNumber
+              v-model="level.maxScore"
+              :min="1"
+              :max="1000"
+              @on-blur="checkLevelValidate(level)"
+              @on-change="checkRoughCodeValidate()"
+              v-if="level.canEdit && workDetail.modifyOtherVal"
+            ></InputNumber>
+            <p v-else>{{ level.maxScore }}</p>
+          </td>
+          <td style="min-width: 100px">
+            <InputNumber
+              v-model="level.intervalScore"
+              :min="1"
+              :max="100"
+              :precision="0"
+              :disabled="!level.canEdit"
+              @on-blur="checkLevelValidate(level)"
+              v-if="
+                level.levelType === 'ADMITED' &&
+                level.canEdit &&
+                workDetail.modifyOtherVal
+              "
+            ></InputNumber>
+            <p v-else>{{ level.intervalScore }}</p>
+          </td>
+          <td>
+            <InputNumber
+              v-model="level.weight"
+              :min="1"
+              :max="1000"
+              @on-blur="checkLevelValidate(level)"
+              v-if="level.canEdit && workDetail.modifyOtherVal"
+            ></InputNumber>
+            <p v-else>{{ level.weight }}</p>
+          </td>
+          <td>
+            <Select
+              v-model="level.levelType"
+              @on-change="levelTypeChange(level)"
+              style="width: 120px"
+              v-if="level.canEdit && workDetail.modifyOtherVal"
+            >
+              <Option
+                v-for="(val, key) in LEVEL_TYPE"
+                :key="key"
+                :value="key"
+                >{{ val }}</Option
+              >
+            </Select>
+            <p v-else>{{ LEVEL_TYPE[level.levelType] }}</p>
+          </td>
+          <td style="min-width: 140px">
+            <Input
+              v-model="level.scoreList"
+              @on-blur="checkLevelValidate(level)"
+              v-if="
+                level.levelType === 'UNADMIT' &&
+                level.canEdit &&
+                workDetail.modifyOtherVal
+              "
+            ></Input>
+            <p v-else>{{ level.scoreList }}</p>
+          </td>
+          <template v-if="roughLevelEnable">
+            <!-- rough_code -->
+            <td>
+              <Select
+                v-model="level.roughCode"
+                @on-change="roughCodeChange(level)"
+                style="min-width: 80px"
+                v-if="level.canEdit && workDetail.modifyOtherVal"
+              >
+                <Option
+                  v-for="(val, key) in ROUGH_LEVEL_TYPE"
+                  :key="key"
+                  :value="key * 1"
+                  >{{ val }}</Option
+                >
+              </Select>
+              <p v-else>{{ ROUGH_LEVEL_TYPE[level.roughCode] }}</p>
+            </td>
+            <!-- rough_weight -->
+            <td>
+              <InputNumber
+                v-model="level.roughWeight"
+                :min="1"
+                :max="100"
+                @on-change="roughWeightChange(level)"
+                v-if="level.canEdit && workDetail.modifyOtherVal"
+              ></InputNumber>
+              <p v-else>{{ level.roughWeight }}</p>
+            </td>
+          </template>
+          <td>
+            <InputNumber
+              v-model="level.kdpt"
+              :min="1"
+              :max="100"
+              @on-blur="checkLevelValidate(level)"
+              v-if="level.canEdit"
+            ></InputNumber>
+            <p v-else>{{ level.kdpt }}</p>
+          </td>
+          <td>
+            <InputNumber
+              v-model="level.pt"
+              :min="1"
+              :max="100"
+              @on-blur="checkLevelValidate(level)"
+              v-if="level.canEdit"
+            ></InputNumber>
+            <p v-else>{{ level.pt }}</p>
+          </td>
+          <td class="table-action">
+            <div style="width: 60px">
+              <Icon type="md-create" title="编辑" @click="toEdit(index)" />
+              <Icon
+                class="icon-danger"
+                type="md-trash"
+                title="删除"
+                @click="toDelete(index)"
+                v-if="workDetail.modifyOtherVal"
+              />
+            </div>
+          </td>
+        </tr>
+        <tr class="tr-tips-error" v-if="level.errors" :key="index + '1'">
+          <td>
+            {{ level.errors.code }}
+          </td>
+          <td>
+            {{ level.errors.minScore }}
+          </td>
+          <td>
+            {{ level.errors.maxScore }}
+          </td>
+          <td>
+            {{ level.errors.intervalScore }}
+          </td>
+          <td>
+            {{ level.errors.weight }}
+          </td>
+          <td></td>
+          <td>
+            {{ level.errors.scoreList }}
+          </td>
+          <template v-if="roughLevelEnable">
+            <td>
+              {{ level.errors.roughCode }}
+            </td>
+            <td>
+              {{ level.errors.roughWeight }}
+            </td>
+          </template>
+          <td>
+            {{ level.errors.kdpt }}
+          </td>
+          <td>
+            {{ level.errors.pt }}
+          </td>
+          <td></td>
+        </tr>
+      </template>
+    </table>
+
+    <div class="text-center">
+      <Button
+        type="primary"
+        shape="circle"
+        @click="toSubmit"
+        style="width: 80px"
+        :disabled="isSubmit"
+        >确定</Button
+      >
+      <!-- <Checkbox v-model="roughLevelEnable">roughLevelEnable</Checkbox> -->
+    </div>
+  </div>
+</template>
+
+<script>
+import { workDetail, updateWork, getParamsSet } from "@/api";
+import { LEVEL_TYPE, ROUGH_LEVEL_TYPE } from "@/constants/enumerate";
+import schema from "async-validator";
+schema.warning = function () {};
+
+const initLevel = {
+  id: null,
+  workId: null,
+  code: null,
+  levelValue: 0,
+  maxScore: null,
+  minScore: null,
+  intervalScore: null,
+  weight: null,
+  roughCode: null,
+  roughWeight: null,
+  levelType: "ADMITED",
+  scoreList: null,
+  pt: null,
+  kdpt: null,
+};
+
+export default {
+  name: "grading-level-set",
+  data() {
+    return {
+      LEVEL_TYPE,
+      ROUGH_LEVEL_TYPE,
+      workId: this.$route.params.workId,
+      letterRelateNumber: {},
+      levels: [],
+      workDetail: {},
+      isSubmit: false,
+      roughLevelEnable: false,
+    };
+  },
+  mounted() {
+    this.initData();
+  },
+  methods: {
+    initData() {
+      const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+      letters.split("").map((item, index) => {
+        this.letterRelateNumber[item] = index + 1;
+      });
+
+      this.getData();
+      this.getParamsSetInfo();
+    },
+    async getData() {
+      const data = await workDetail(this.workId);
+      this.workDetail = data;
+      this.levels = data.levels.map((item) => {
+        let nitem = { ...item };
+        nitem.canEdit = false;
+        nitem.roughCode = nitem.roughCode * 1;
+        return nitem;
+      });
+    },
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.roughLevelEnable = data.levelConfig.roughLevelEnable;
+    },
+    checkLevelCodeIsContinuous() {
+      let levelIsContinuous = true;
+      for (var i = 0, num = this.levels.length; i < num; i++) {
+        if (i > 0) {
+          const beforeCodeNum =
+            this.letterRelateNumber[this.levels[i - 1].code];
+          const curCodeNum = this.letterRelateNumber[this.levels[i].code];
+          levelIsContinuous =
+            levelIsContinuous && curCodeNum - beforeCodeNum === 1;
+
+          if (!levelIsContinuous) {
+            return false;
+          }
+        }
+      }
+
+      return true;
+    },
+    levelTypeChange(level) {
+      if (level.levelType === "ADMITED") {
+        level.scoreList = null;
+      } else {
+        level.intervalScore = null;
+      }
+    },
+    codeChange(level) {
+      level.code = level.code.toUpperCase();
+      this.levels.sort((a, b) => {
+        if (
+          !a.code ||
+          !b.code ||
+          !this.letterRelateNumber[a.code] ||
+          !this.letterRelateNumber[b.code]
+        )
+          return 0;
+
+        return (
+          this.letterRelateNumber[a.code] - this.letterRelateNumber[b.code]
+        );
+      });
+      this.checkLevelValidate(level);
+    },
+    getNextLevelCode() {
+      const codeNumbers = this.levels.map(
+        (level) => this.letterRelateNumber[level.code] || 0
+      );
+      const maxCodeNumber = Math.max.apply(null, codeNumbers);
+      const nextLevel = Object.entries(this.letterRelateNumber).find(
+        ([key, val]) => {
+          return maxCodeNumber < val;
+        }
+      );
+      return nextLevel ? nextLevel[0] : "";
+    },
+    toAdd() {
+      let level = { ...initLevel };
+      level.workId = this.workId;
+      level.code = this.getNextLevelCode();
+      this.levels.push(level);
+    },
+    toEdit(index) {
+      this.levels[index].canEdit = true;
+      this.$forceUpdate();
+    },
+    toDelete(index) {
+      this.levels.splice(index, 1);
+    },
+    roughCodeChange(level) {
+      let codeWeight = {};
+      this.levels.forEach((item) => {
+        if (item.roughCode && item.roughWeight) {
+          codeWeight[item.roughCode] = item.roughWeight;
+        }
+      });
+      level.roughWeight = codeWeight[level.roughCode] || null;
+
+      this.checkRoughCodeValidate();
+    },
+    roughWeightChange(level) {
+      this.levels
+        .filter(
+          (item) =>
+            item.roughCode &&
+            item.roughCode === level.roughCode &&
+            item.code !== level.code
+        )
+        .forEach((item) => {
+          item.roughWeight = level.roughWeight;
+        });
+      this.checkRoughCodeValidate();
+    },
+    resetError(errors, fields, fieldVals) {
+      if (!errors) return null;
+      let nerrors = { ...errors };
+      fields.forEach((field) => {
+        if (fieldVals && fieldVals[field]) {
+          this.$set(nerrors, field, fieldVals[field]);
+        } else {
+          delete nerrors[field];
+        }
+      });
+      return Object.keys(nerrors).length ? nerrors : null;
+    },
+    checkLevelValidate(level) {
+      const descriptor = {
+        code: {
+          type: "string",
+          required: true,
+          pattern: /^[A-Z]{1}$/,
+          message: "请输入单个大写字母",
+        },
+        minScore: {
+          type: "number",
+          required: true,
+          message: "请输入最低分",
+        },
+        maxScore: {
+          type: "number",
+          required: true,
+          validator: (rule, value, callback) => {
+            if (!value || value < level.minScore) {
+              callback(new Error("最高分不得小于最低分"));
+            } else {
+              callback();
+            }
+          },
+        },
+        intervalScore: {
+          type: "number",
+          validator: (rule, value, callback) => {
+            if (level.levelType === "ADMITED" && !value) {
+              callback(new Error("请输入给分间隔"));
+            } else {
+              callback();
+            }
+          },
+        },
+        weight: {
+          type: "number",
+          validator: (rule, value, callback) => {
+            if (!value) return callback(new Error("请输入典型值"));
+
+            if (value < level.minScore || value > level.maxScore) {
+              return callback(
+                new Error(
+                  `典型值只能介于${level.minScore}和${level.maxScore}之间`
+                )
+              );
+            }
+
+            callback();
+          },
+        },
+        scoreList: {
+          type: "string",
+          validator: (rule, value, callback) => {
+            if (level.levelType !== "UNADMIT") return callback();
+
+            if (level.levelType === "UNADMIT" && !value) {
+              return callback(new Error("请输入给分项"));
+            }
+            if (!value.match(/^[0-9,]+$/)) {
+              return callback(new Error("给分项只能包含数字和英文逗号"));
+            }
+            const unvalid = value
+              .split(",")
+              .filter((item) => item)
+              .some((item) => {
+                const num = item * 1;
+                return num < level.minScore || num > level.maxScore;
+              });
+            if (unvalid) {
+              return callback(
+                new Error("给分项包含的分值只能介于最低分和最高分之间")
+              );
+            }
+
+            callback();
+          },
+        },
+        pt: {
+          type: "number",
+          required: true,
+          message: "请输入占比阀值",
+        },
+        kdpt: {
+          type: "number",
+          required: true,
+          message: "请输入考区阀值",
+        },
+      };
+      const fields = Object.keys(descriptor);
+      return new schema(descriptor)
+        .validate(level)
+        .then(() => {
+          this.$set(level, "errors", this.resetError(level.errors, fields));
+        })
+        .catch(({ errors }) => {
+          if (!errors) return;
+
+          let errorMsgs = {};
+          errors.map((error) => {
+            errorMsgs[error.field] = error.message;
+          });
+          this.$set(
+            level,
+            "errors",
+            this.resetError(level.errors || {}, fields, errorMsgs)
+          );
+          return errors;
+        });
+    },
+    async checkRoughCodeValidate(checkCodeRequired) {
+      if (!this.roughLevelEnable) return;
+      let weightRanges = {};
+      this.levels.forEach((level) => {
+        if (!level.roughCode) return;
+        let range = weightRanges[level.roughCode] || {
+          sn: 100,
+          en: 0,
+        };
+        range.sn = Math.min(range.sn, level.minScore);
+        range.en = Math.max(range.en, level.maxScore);
+        weightRanges[level.roughCode] = range;
+      });
+
+      const roughCodeValidate = (level) => {
+        const descriptor = {
+          roughCode: {
+            validator: (rule, value, callback) => {
+              if (!checkCodeRequired && !value) return callback();
+
+              if (checkCodeRequired && !value)
+                return callback(new Error(`请选择粗档位`));
+
+              const pos = this.levels.findIndex(
+                (item) => item.code === level.code
+              );
+              if (pos === 0 && value !== 1)
+                return callback(new Error(`只能选择粗档位"一"`));
+
+              if (pos > 0) {
+                const prevLevel = this.levels[pos - 1];
+                if (prevLevel && prevLevel.roughCode) {
+                  const codeDis = value - prevLevel.roughCode;
+                  if (codeDis < 0 || codeDis > 1) {
+                    return callback(new Error(`请保持粗档位连续`));
+                  }
+                }
+
+                // const nextLevel = this.levels[pos + 1];
+                // if (nextLevel && nextLevel.roughCode) {
+                //   const codeDis = nextLevel.roughCode - value;
+                //   if (codeDis < 0 || codeDis > 1) {
+                //     return callback(new Error(`请保持粗档位连续`));
+                //   }
+                // }
+              }
+
+              callback();
+            },
+          },
+          roughWeight: {
+            validator: (rule, value, callback) => {
+              if (!checkCodeRequired) {
+                if (level.roughCode && !value)
+                  return callback(new Error(`请输入粗档位典型值`));
+                if (!level.roughCode) return callback();
+              }
+              if (checkCodeRequired && !value)
+                return callback(new Error(`请输入粗档位典型值`));
+
+              const range = weightRanges[level.roughCode];
+              if (value < range.sn || value > range.en)
+                return callback(
+                  new Error(`粗档位典型值只能介于${range.sn}和${range.en}之间`)
+                );
+
+              callback();
+            },
+          },
+        };
+        const fields = Object.keys(descriptor);
+
+        return new schema(descriptor)
+          .validate(level)
+          .then(() => {
+            this.$set(level, "errors", this.resetError(level.errors, fields));
+          })
+          .catch(({ errors }) => {
+            if (!errors) return;
+            let errorMsgs = {};
+            errors.map((error) => {
+              errorMsgs[error.field] = error.message;
+            });
+            this.$set(
+              level,
+              "errors",
+              this.resetError(level.errors || {}, fields, errorMsgs)
+            );
+            return errors;
+          });
+      };
+
+      const validatorAll = this.levels.map((level) => roughCodeValidate(level));
+      const result = await Promise.all(validatorAll);
+      const hasUnvalidate = result.some((item) => !!item);
+
+      return hasUnvalidate;
+    },
+    async toSubmit() {
+      const validatorAll = this.levels.map((level) =>
+        this.checkLevelValidate(level)
+      );
+      const result = await Promise.all(validatorAll);
+      let hasUnvalidate = result.some((item) => !!item);
+      if (hasUnvalidate) return;
+
+      hasUnvalidate = await this.checkRoughCodeValidate(true);
+      if (hasUnvalidate) return;
+
+      if (!this.checkLevelCodeIsContinuous()) {
+        this.$Message.error("请保持档位连续!");
+        return;
+      }
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      this.workDetail.levels = this.levels;
+      const data = await updateWork(this.workDetail).catch(() => {
+        this.isSubmit = false;
+      });
+
+      if (!data) return;
+
+      this.isSubmit = false;
+      this.getData();
+      this.$Message.success("保存成功!");
+    },
+  },
+};
+</script>

+ 492 - 492
src/modules/grading-set/GradingRuleSet.vue

@@ -1,492 +1,492 @@
-<template>
-  <div class="grading-rule-set part-box">
-    <div class="rule-part">
-      <h3 v-show="modalForm.roughLevelEnable" class="rule-part-title">
-        细分档设置
-      </h3>
-      <Form
-        ref="modalFormComp"
-        :model="modalForm"
-        :rules="rules"
-        :label-width="230"
-        style="width: 400px;"
-      >
-        <FormItem prop="deviation" label="仲裁档位差:">
-          <InputNumber
-            v-model="modalForm.deviation"
-            :min="1"
-            :max="100"
-            :disabled="!modalFormCanEdit"
-            style="width: 160px;"
-          ></InputNumber>
-        </FormItem>
-        <FormItem label="系统自动打回:">
-          <Select
-            v-model="modalForm.autoCallback"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem
-          v-if="modalForm.autoCallback"
-          prop="cumulativeError"
-          label="打回累计误差:"
-        >
-          <InputNumber
-            v-model="modalForm.cumulativeError"
-            :min="1"
-            :max="100"
-            :disabled="!modalFormCanEdit"
-            style="width: 160px;"
-          ></InputNumber>
-        </FormItem>
-        <FormItem v-if="modalForm.autoCallback" label="打回是否显示偏差方向:">
-          <Select
-            v-model="modalForm.autoCallbackShowDeviation"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否过半定档:">
-          <Select
-            v-model="modalForm.majority"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否启用取优原则:">
-          <Select
-            v-model="modalForm.takeBest"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="阅卷员是否显示所有试卷:">
-          <Select
-            v-model="modalForm.levelShowAllPaper"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="档位百分比分母:">
-          <Select
-            v-model="modalForm.propDenominator"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in PROP_DENOMINATOR_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否显示标准卷管理:">
-          <Select
-            v-model="modalForm.showStandardPaperManage"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否显示清除当前阅卷数据:">
-          <Select
-            v-model="modalForm.clearData"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否开启去高去低再加权评卷:">
-          <Select
-            v-model="modalForm.removeHighAndLow"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否增加粗档位环节:">
-          <Select
-            v-model="modalForm.roughLevelEnable"
-            :disabled="!modalFormCanEdit"
-            placeholder="请选择"
-            @on-change="roughLevelChange"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="自查卷发卷频率:">
-          <InputNumber
-            v-model="modalForm.selfCheckFrequency"
-            :disabled="!modalFormCanEdit"
-            :min="0"
-            :max="100000"
-            :precision="0"
-            :active-change="false"
-            placeholder="输入数值"
-            clearable
-          />
-        </FormItem>
-      </Form>
-      <div class="rule-part-footer">
-        <Button
-          shape="circle"
-          style="width: 80px;"
-          @click="modalFormCanEdit = true"
-          >编辑</Button
-        >
-        <Button
-          type="primary"
-          shape="circle"
-          style="width: 80px;"
-          :disabled="isSubmit"
-          @click="submit"
-          >保存</Button
-        >
-      </div>
-    </div>
-    <div v-if="modalForm.roughLevelEnable" class="rule-part">
-      <h3 class="rule-part-title">粗分档设置</h3>
-      <Form
-        ref="modalFormRoughComp"
-        :model="modalFormRough"
-        :rules="rules"
-        :label-width="230"
-        style="width: 400px;"
-      >
-        <FormItem prop="deviation" label="仲裁档位差:">
-          <InputNumber
-            v-model="modalFormRough.deviation"
-            :min="1"
-            :max="100"
-            :disabled="!modalFormRoughCanEdit"
-            style="width: 160px;"
-          ></InputNumber>
-        </FormItem>
-        <FormItem label="系统自动打回:">
-          <Select
-            v-model="modalFormRough.autoCallback"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem
-          v-if="modalFormRough.autoCallback"
-          prop="cumulativeError"
-          label="打回累计误差:"
-        >
-          <InputNumber
-            v-model="modalFormRough.cumulativeError"
-            :min="1"
-            :max="100"
-            :disabled="!modalFormRoughCanEdit"
-            style="width: 160px;"
-          ></InputNumber>
-        </FormItem>
-        <FormItem
-          v-if="modalFormRough.autoCallback"
-          label="打回是否显示偏差方向:"
-        >
-          <Select
-            v-model="modalFormRough.autoCallbackShowDeviation"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否过半定档:">
-          <Select
-            v-model="modalFormRough.majority"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否启用取优原则:">
-          <Select
-            v-model="modalFormRough.takeBest"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="阅卷员是否显示所有试卷:">
-          <Select
-            v-model="modalFormRough.levelShowAllPaper"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="档位百分比分母:">
-          <Select
-            v-model="modalFormRough.propDenominator"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in PROP_DENOMINATOR_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否显示标准卷管理:">
-          <Select
-            v-model="modalFormRough.showStandardPaperManage"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否显示清除当前阅卷数据:">
-          <Select
-            v-model="modalFormRough.clearData"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="是否开启去高去低再加权评卷:">
-          <Select
-            v-model="modalFormRough.removeHighAndLow"
-            :disabled="!modalFormRoughCanEdit"
-            placeholder="请选择"
-          >
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem label="自查卷发卷频率:">
-          <InputNumber
-            v-model="modalFormRough.selfCheckFrequency"
-            :disabled="!modalFormRoughCanEdit"
-            :min="0"
-            :max="100000"
-            :precision="0"
-            :active-change="false"
-            placeholder="输入数值"
-            clearable
-          />
-        </FormItem>
-      </Form>
-      <div class="rule-part-footer">
-        <Button
-          shape="circle"
-          style="width: 80px;"
-          @click="modalFormRoughCanEdit = true"
-          >编辑</Button
-        >
-        <Button
-          type="primary"
-          shape="circle"
-          style="width: 80px;"
-          :disabled="isRoughSubmit"
-          @click="submitRough"
-          >保存</Button
-        >
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { getParamsSet, updateLevelParams, updateRoughLevelParams } from "@/api";
-import { BOOLEAN_TYPE, PROP_DENOMINATOR_TYPE } from "@/constants/enumerate";
-import { numberValidator } from "@/plugins/formRules";
-
-const initModalForm = {
-  workId: "",
-  deviation: 3,
-  cumulativeError: null,
-  autoCallbackShowDeviation: 1,
-  autoCallback: 0,
-  majority: 0,
-  takeBest: 1,
-  levelShowAllPaper: 0,
-  propDenominator: 1,
-  showStandardPaperManage: 1,
-  clearData: 0,
-  removeHighAndLow: 0,
-  selfCheckFrequency: 0
-};
-
-export default {
-  name: "grading-rule-set",
-  data() {
-    return {
-      isSubmit: false,
-      isRoughSubmit: false,
-      workId: this.$route.params.workId,
-      BOOLEAN_TYPE,
-      PROP_DENOMINATOR_TYPE,
-      modalFormCanEdit: false,
-      modalForm: {},
-      modalFormRoughCanEdit: false,
-      modalFormRough: {},
-      rules: {
-        deviation: numberValidator("请输入仲裁档位差"),
-        cumulativeError: numberValidator("请输入打回累计误差")
-      }
-    };
-  },
-  mounted() {
-    this.modalForm = { ...initModalForm, roughLevelEnable: 0 };
-    this.getParamsSetInfo();
-  },
-  methods: {
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.modalForm = this.$objAssign(this.modalForm, data.levelConfig);
-      this.modalFormRough = this.$objAssign(
-        initModalForm,
-        data.roughLevelConfig
-      );
-    },
-    roughLevelChange(val) {
-      if (val) {
-        this.modalFormRoughCanEdit = true;
-      }
-    },
-    async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
-      if (!valid) return;
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      let result = true;
-      await updateLevelParams(this.modalForm).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-
-      if (!result) return;
-      this.modalFormCanEdit = false;
-      this.$Message.success("保存成功!");
-    },
-    async submitRough() {
-      const valid = await this.$refs.modalFormRoughComp.validate();
-      if (!valid) return;
-
-      if (this.isRoughSubmit) return;
-      this.isRoughSubmit = true;
-      let result = true;
-      await updateRoughLevelParams(this.modalFormRough).catch(() => {
-        result = false;
-      });
-      this.isRoughSubmit = false;
-
-      if (!result) return;
-      this.modalFormRoughCanEdit = false;
-      this.$Message.success("保存成功!");
-    }
-  }
-};
-</script>
+<template>
+  <div class="grading-rule-set part-box">
+    <div class="rule-part">
+      <h3 v-show="modalForm.roughLevelEnable" class="rule-part-title">
+        细分档设置
+      </h3>
+      <Form
+        ref="modalFormComp"
+        :model="modalForm"
+        :rules="rules"
+        :label-width="230"
+        style="width: 400px"
+      >
+        <FormItem prop="deviation" label="仲裁档位差:">
+          <InputNumber
+            v-model="modalForm.deviation"
+            :min="1"
+            :max="100"
+            :disabled="!modalFormCanEdit"
+            style="width: 160px"
+          ></InputNumber>
+        </FormItem>
+        <FormItem label="系统自动打回:">
+          <Select
+            v-model="modalForm.autoCallback"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem
+          v-if="modalForm.autoCallback"
+          prop="cumulativeError"
+          label="打回累计误差:"
+        >
+          <InputNumber
+            v-model="modalForm.cumulativeError"
+            :min="1"
+            :max="100"
+            :disabled="!modalFormCanEdit"
+            style="width: 160px"
+          ></InputNumber>
+        </FormItem>
+        <FormItem v-if="modalForm.autoCallback" label="打回是否显示偏差方向:">
+          <Select
+            v-model="modalForm.autoCallbackShowDeviation"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否过半定档:">
+          <Select
+            v-model="modalForm.majority"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否启用取优原则:">
+          <Select
+            v-model="modalForm.takeBest"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="阅卷员是否显示所有试卷:">
+          <Select
+            v-model="modalForm.levelShowAllPaper"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="档位百分比分母:">
+          <Select
+            v-model="modalForm.propDenominator"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in PROP_DENOMINATOR_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否显示标准卷管理:">
+          <Select
+            v-model="modalForm.showStandardPaperManage"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否显示清除当前阅卷数据:">
+          <Select
+            v-model="modalForm.clearData"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否开启去高去低再加权评卷:">
+          <Select
+            v-model="modalForm.removeHighAndLow"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否增加粗档位环节:">
+          <Select
+            v-model="modalForm.roughLevelEnable"
+            :disabled="!modalFormCanEdit"
+            placeholder="请选择"
+            @on-change="roughLevelChange"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="自查卷发卷频率:">
+          <InputNumber
+            v-model="modalForm.selfCheckFrequency"
+            :disabled="!modalFormCanEdit"
+            :min="0"
+            :max="100000"
+            :precision="0"
+            :active-change="false"
+            placeholder="输入数值"
+            clearable
+          />
+        </FormItem>
+      </Form>
+      <div class="rule-part-footer">
+        <Button
+          shape="circle"
+          style="width: 80px"
+          @click="modalFormCanEdit = true"
+          >编辑</Button
+        >
+        <Button
+          type="primary"
+          shape="circle"
+          style="width: 80px"
+          :disabled="isSubmit"
+          @click="submit"
+          >保存</Button
+        >
+      </div>
+    </div>
+    <div v-if="modalForm.roughLevelEnable" class="rule-part">
+      <h3 class="rule-part-title">粗分档设置</h3>
+      <Form
+        ref="modalFormRoughComp"
+        :model="modalFormRough"
+        :rules="rules"
+        :label-width="230"
+        style="width: 400px"
+      >
+        <FormItem prop="deviation" label="仲裁档位差:">
+          <InputNumber
+            v-model="modalFormRough.deviation"
+            :min="1"
+            :max="100"
+            :disabled="!modalFormRoughCanEdit"
+            style="width: 160px"
+          ></InputNumber>
+        </FormItem>
+        <FormItem label="系统自动打回:">
+          <Select
+            v-model="modalFormRough.autoCallback"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem
+          v-if="modalFormRough.autoCallback"
+          prop="cumulativeError"
+          label="打回累计误差:"
+        >
+          <InputNumber
+            v-model="modalFormRough.cumulativeError"
+            :min="1"
+            :max="100"
+            :disabled="!modalFormRoughCanEdit"
+            style="width: 160px"
+          ></InputNumber>
+        </FormItem>
+        <FormItem
+          v-if="modalFormRough.autoCallback"
+          label="打回是否显示偏差方向:"
+        >
+          <Select
+            v-model="modalFormRough.autoCallbackShowDeviation"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否过半定档:">
+          <Select
+            v-model="modalFormRough.majority"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否启用取优原则:">
+          <Select
+            v-model="modalFormRough.takeBest"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="阅卷员是否显示所有试卷:">
+          <Select
+            v-model="modalFormRough.levelShowAllPaper"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="档位百分比分母:">
+          <Select
+            v-model="modalFormRough.propDenominator"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in PROP_DENOMINATOR_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否显示标准卷管理:">
+          <Select
+            v-model="modalFormRough.showStandardPaperManage"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否显示清除当前阅卷数据:">
+          <Select
+            v-model="modalFormRough.clearData"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="是否开启去高去低再加权评卷:">
+          <Select
+            v-model="modalFormRough.removeHighAndLow"
+            :disabled="!modalFormRoughCanEdit"
+            placeholder="请选择"
+          >
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem label="自查卷发卷频率:">
+          <InputNumber
+            v-model="modalFormRough.selfCheckFrequency"
+            :disabled="!modalFormRoughCanEdit"
+            :min="0"
+            :max="100000"
+            :precision="0"
+            :active-change="false"
+            placeholder="输入数值"
+            clearable
+          />
+        </FormItem>
+      </Form>
+      <div class="rule-part-footer">
+        <Button
+          shape="circle"
+          style="width: 80px"
+          @click="modalFormRoughCanEdit = true"
+          >编辑</Button
+        >
+        <Button
+          type="primary"
+          shape="circle"
+          style="width: 80px"
+          :disabled="isRoughSubmit"
+          @click="submitRough"
+          >保存</Button
+        >
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getParamsSet, updateLevelParams, updateRoughLevelParams } from "@/api";
+import { BOOLEAN_TYPE, PROP_DENOMINATOR_TYPE } from "@/constants/enumerate";
+import { numberValidator } from "@/plugins/formRules";
+
+const initModalForm = {
+  workId: "",
+  deviation: 3,
+  cumulativeError: null,
+  autoCallbackShowDeviation: 1,
+  autoCallback: 0,
+  majority: 0,
+  takeBest: 1,
+  levelShowAllPaper: 0,
+  propDenominator: 1,
+  showStandardPaperManage: 1,
+  clearData: 0,
+  removeHighAndLow: 0,
+  selfCheckFrequency: 0,
+};
+
+export default {
+  name: "grading-rule-set",
+  data() {
+    return {
+      isSubmit: false,
+      isRoughSubmit: false,
+      workId: this.$route.params.workId,
+      BOOLEAN_TYPE,
+      PROP_DENOMINATOR_TYPE,
+      modalFormCanEdit: false,
+      modalForm: {},
+      modalFormRoughCanEdit: false,
+      modalFormRough: {},
+      rules: {
+        deviation: numberValidator("请输入仲裁档位差"),
+        cumulativeError: numberValidator("请输入打回累计误差"),
+      },
+    };
+  },
+  mounted() {
+    this.modalForm = { ...initModalForm, roughLevelEnable: 0 };
+    this.getParamsSetInfo();
+  },
+  methods: {
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.modalForm = this.$objAssign(this.modalForm, data.levelConfig);
+      this.modalFormRough = this.$objAssign(
+        initModalForm,
+        data.roughLevelConfig
+      );
+    },
+    roughLevelChange(val) {
+      if (val) {
+        this.modalFormRoughCanEdit = true;
+      }
+    },
+    async submit() {
+      const valid = await this.$refs.modalFormComp.validate();
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      let result = true;
+      await updateLevelParams(this.modalForm).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+
+      if (!result) return;
+      this.modalFormCanEdit = false;
+      this.$Message.success("保存成功!");
+    },
+    async submitRough() {
+      const valid = await this.$refs.modalFormRoughComp.validate();
+      if (!valid) return;
+
+      if (this.isRoughSubmit) return;
+      this.isRoughSubmit = true;
+      let result = true;
+      await updateRoughLevelParams(this.modalFormRough).catch(() => {
+        result = false;
+      });
+      this.isRoughSubmit = false;
+
+      if (!result) return;
+      this.modalFormRoughCanEdit = false;
+      this.$Message.success("保存成功!");
+    },
+  },
+};
+</script>

+ 5 - 5
src/modules/grading-set/GradingSet.vue

@@ -4,7 +4,7 @@
       <div
       <div
         :class="[
         :class="[
           'set-navs-item',
           'set-navs-item',
-          { 'set-navs-item-act': curNav.name === nav.name }
+          { 'set-navs-item-act': curNav.name === nav.name },
         ]"
         ]"
         v-for="(nav, index) in navs"
         v-for="(nav, index) in navs"
         :key="index"
         :key="index"
@@ -28,18 +28,18 @@ export default {
   data() {
   data() {
     return {
     return {
       navs: gradingSet,
       navs: gradingSet,
-      curNav: {}
+      curNav: {},
     };
     };
   },
   },
   watch: {
   watch: {
     $route: {
     $route: {
       handler(val) {
       handler(val) {
         this.actCurNav(val);
         this.actCurNav(val);
-      }
-    }
+      },
+    },
   },
   },
   mounted() {
   mounted() {
     this.actCurNav(this.$route);
     this.actCurNav(this.$route);
-  }
+  },
 };
 };
 </script>
 </script>

+ 6 - 6
src/modules/grading-set/UploadPaper.vue

@@ -35,7 +35,7 @@ export default {
     return {
     return {
       workId: this.$route.params.workId,
       workId: this.$route.params.workId,
       papers: [],
       papers: [],
-      subjects: []
+      subjects: [],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -44,17 +44,17 @@ export default {
   methods: {
   methods: {
     async getData() {
     async getData() {
       const data = await uploadPaperList(this.workId);
       const data = await uploadPaperList(this.workId);
-      this.papers = data.map(area => {
+      this.papers = data.map((area) => {
         area.subjects = area.subjects
         area.subjects = area.subjects
-          .filter(item => item.enable)
-          .map(subject => {
+          .filter((item) => item.enable)
+          .map((subject) => {
             subject.uploadUrl = `${this.GLOBAL.domain}/api/papers/${this.workId}/${area.questionId}/${subject.subject}/uploadPaperFile`;
             subject.uploadUrl = `${this.GLOBAL.domain}/api/papers/${this.workId}/${area.questionId}/${subject.subject}/uploadPaperFile`;
             return subject;
             return subject;
           });
           });
         return area;
         return area;
       });
       });
       this.subjects = this.papers[0].subjects;
       this.subjects = this.papers[0].subjects;
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 178 - 178
src/modules/grading/Grading.vue

@@ -1,178 +1,178 @@
-<template>
-  <div class="grading home">
-    <view-header key="1" :show-reset-pwd="false" v-if="IS_ADMIN">
-      <div class="grading-subnav" slot="navSub">
-        <div class="grading-title">
-          <h1>{{ curSubject.name }}</h1>
-          <span>当前阶段:{{ stepName }}</span
-          ><span>进度:{{ stepProgress }}</span>
-        </div>
-        <div class="home-navs">
-          <ul>
-            <li
-              :class="{ act: curNav.name === nav.name }"
-              v-for="(nav, index) in navs"
-              :key="index"
-              @click="switchNav(nav)"
-            >
-              <i
-                :class="[
-                  'icon',
-                  curNav.name === nav.name ? `${nav.icon}-act` : nav.icon
-                ]"
-                v-if="nav.icon"
-              ></i>
-              <span class="nav-item-cont">{{ nav.title }}</span>
-            </li>
-          </ul>
-        </div>
-      </div>
-    </view-header>
-    <view-header key="2" v-else>
-      <div class="home-navs" slot="navSub">
-        <ul>
-          <li
-            :class="{ act: curNav.name === nav.name }"
-            v-for="(nav, index) in navs"
-            :key="index"
-            @click="switchNav(nav)"
-          >
-            <i
-              :class="[
-                'icon',
-                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon
-              ]"
-              v-if="nav.icon"
-            ></i>
-            <span class="nav-item-cont">{{ nav.title }}</span>
-          </li>
-        </ul>
-      </div>
-    </view-header>
-
-    <div class="home-body">
-      <div class="home-main">
-        <router-view />
-
-        <!-- <view-footer></view-footer> -->
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-import { subjectDetail, gradingProgressDetail, getParamsSet } from "@/api";
-import { grading, main } from "@/constants/authority";
-import menuMixins from "@/components/homeMenuMixins";
-import { SUBJECT_STAGE } from "@/constants/enumerate";
-import { deepCopy } from "@/plugins/utils";
-
-export default {
-  name: "grading",
-  mixins: [menuMixins],
-  data() {
-    return {
-      subjectId: this.$route.params.subjectId,
-      workId: this.$route.params.workId,
-      navs: [],
-      curNav: {},
-      SUBJECT_STAGE,
-      IS_ADMIN: true,
-      stepName: "",
-      stepProgress: ""
-    };
-  },
-  computed: {
-    ...mapState("marker", ["paramsSet", "curSubject"])
-  },
-  watch: {
-    $route: {
-      handler(val) {
-        this.actSubNav();
-      }
-    }
-  },
-  mounted() {
-    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.IS_ADMIN = curUserRoleType === "ADMIN";
-    this.initData();
-  },
-  methods: {
-    ...mapMutations("marker", ["setParamSet", "setCurSubject"]),
-    async initData() {
-      if (this.IS_ADMIN) {
-        const curSubject = await subjectDetail(this.subjectId);
-        this.setCurSubject(curSubject || {});
-
-        if (this.curSubject.stage === "SCORE") {
-          this.$router.replace({
-            name: "Mark",
-            params: {
-              workId: this.subjectId.split("-")[0],
-              subjectId: this.subjectId
-            }
-          });
-          return;
-        }
-        // this.getProgressDetail();
-        this.stepName =
-          this.curSubject.test === 2
-            ? "试评"
-            : this.getStageName(
-                this.curSubject.stage,
-                this.curSubject.roughLevelEnable
-              );
-      } else {
-        await this.getParamsSetInfo();
-        if (
-          this.$route.name === "GradingStandardPaperManage" &&
-          !this.paramsSet.levelConfig.showStandardPaperManage
-        ) {
-          this.$Message.error("非法操作!");
-          this.$router.replace({ name: "Login" });
-          return;
-        }
-      }
-
-      this.buildNavs();
-      this.actSubNav();
-    },
-    getStageName(stage, roughLevelEnable) {
-      let stageName = SUBJECT_STAGE[stage];
-      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档阶段";
-      return stageName;
-    },
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.setParamSet(data || {});
-    },
-    setProgress(progress) {
-      this.stepProgress = progress.toFixed(2) + "%";
-    },
-    async getProgressDetail() {
-      const data = await gradingProgressDetail({
-        workId: this.curSubject.workId,
-        subject: this.curSubject.subject
-      });
-      this.stepProgress = data.totalProgress.progress.toFixed(2) + "%";
-    },
-    buildNavs() {
-      this.navs = deepCopy(grading);
-      if (this.IS_ADMIN) {
-        this.navs = [...main.slice(0, 2), ...this.navs.slice(0, -2)];
-      } else {
-        this.paramsSet.levelConfig.showStandardPaperManage
-          ? this.navs.splice(3, 2)
-          : this.navs.splice(3, 3);
-      }
-    },
-    actSubNav() {
-      const router = this.$route.matched.filter(
-        item => item.name !== "Grading"
-      )[0];
-      this.actCurNav(router);
-    }
-  }
-};
-</script>
+<template>
+  <div class="grading home">
+    <view-header key="1" :show-reset-pwd="false" v-if="IS_ADMIN">
+      <div class="grading-subnav" slot="navSub">
+        <div class="grading-title">
+          <h1>{{ curSubject.name }}</h1>
+          <span>当前阶段:{{ stepName }}</span
+          ><span>进度:{{ stepProgress }}</span>
+        </div>
+        <div class="home-navs">
+          <ul>
+            <li
+              :class="{ act: curNav.name === nav.name }"
+              v-for="(nav, index) in navs"
+              :key="index"
+              @click="switchNav(nav)"
+            >
+              <i
+                :class="[
+                  'icon',
+                  curNav.name === nav.name ? `${nav.icon}-act` : nav.icon,
+                ]"
+                v-if="nav.icon"
+              ></i>
+              <span class="nav-item-cont">{{ nav.title }}</span>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </view-header>
+    <view-header key="2" v-else>
+      <div class="home-navs" slot="navSub">
+        <ul>
+          <li
+            :class="{ act: curNav.name === nav.name }"
+            v-for="(nav, index) in navs"
+            :key="index"
+            @click="switchNav(nav)"
+          >
+            <i
+              :class="[
+                'icon',
+                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon,
+              ]"
+              v-if="nav.icon"
+            ></i>
+            <span class="nav-item-cont">{{ nav.title }}</span>
+          </li>
+        </ul>
+      </div>
+    </view-header>
+
+    <div class="home-body">
+      <div class="home-main">
+        <router-view />
+
+        <!-- <view-footer></view-footer> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import { subjectDetail, gradingProgressDetail, getParamsSet } from "@/api";
+import { grading, main } from "@/constants/authority";
+import menuMixins from "@/components/homeMenuMixins";
+import { SUBJECT_STAGE } from "@/constants/enumerate";
+import { deepCopy } from "@/plugins/utils";
+
+export default {
+  name: "grading",
+  mixins: [menuMixins],
+  data() {
+    return {
+      subjectId: this.$route.params.subjectId,
+      workId: this.$route.params.workId,
+      navs: [],
+      curNav: {},
+      SUBJECT_STAGE,
+      IS_ADMIN: true,
+      stepName: "",
+      stepProgress: "",
+    };
+  },
+  computed: {
+    ...mapState("marker", ["paramsSet", "curSubject"]),
+  },
+  watch: {
+    $route: {
+      handler(val) {
+        this.actSubNav();
+      },
+    },
+  },
+  mounted() {
+    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    this.IS_ADMIN = curUserRoleType === "ADMIN";
+    this.initData();
+  },
+  methods: {
+    ...mapMutations("marker", ["setParamSet", "setCurSubject"]),
+    async initData() {
+      if (this.IS_ADMIN) {
+        const curSubject = await subjectDetail(this.subjectId);
+        this.setCurSubject(curSubject || {});
+
+        if (this.curSubject.stage === "SCORE") {
+          this.$router.replace({
+            name: "Mark",
+            params: {
+              workId: this.subjectId.split("-")[0],
+              subjectId: this.subjectId,
+            },
+          });
+          return;
+        }
+        // this.getProgressDetail();
+        this.stepName =
+          this.curSubject.test === 2
+            ? "试评"
+            : this.getStageName(
+                this.curSubject.stage,
+                this.curSubject.roughLevelEnable
+              );
+      } else {
+        await this.getParamsSetInfo();
+        if (
+          this.$route.name === "GradingStandardPaperManage" &&
+          !this.paramsSet.levelConfig.showStandardPaperManage
+        ) {
+          this.$Message.error("非法操作!");
+          this.$router.replace({ name: "Login" });
+          return;
+        }
+      }
+
+      this.buildNavs();
+      this.actSubNav();
+    },
+    getStageName(stage, roughLevelEnable) {
+      let stageName = SUBJECT_STAGE[stage];
+      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档阶段";
+      return stageName;
+    },
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.setParamSet(data || {});
+    },
+    setProgress(progress) {
+      this.stepProgress = progress.toFixed(2) + "%";
+    },
+    async getProgressDetail() {
+      const data = await gradingProgressDetail({
+        workId: this.curSubject.workId,
+        subject: this.curSubject.subject,
+      });
+      this.stepProgress = data.totalProgress.progress.toFixed(2) + "%";
+    },
+    buildNavs() {
+      this.navs = deepCopy(grading);
+      if (this.IS_ADMIN) {
+        this.navs = [...main.slice(0, 2), ...this.navs.slice(0, -2)];
+      } else {
+        this.paramsSet.levelConfig.showStandardPaperManage
+          ? this.navs.splice(3, 2)
+          : this.navs.splice(3, 3);
+      }
+    },
+    actSubNav() {
+      const router = this.$route.matched.filter(
+        (item) => item.name !== "Grading"
+      )[0];
+      this.actCurNav(router);
+    },
+  },
+};
+</script>

+ 11 - 11
src/modules/grading/GradingAnalysis.vue

@@ -65,7 +65,7 @@ export default {
     return {
     return {
       filter: {
       filter: {
         questionId: "",
         questionId: "",
-        sort: "secretNumber"
+        sort: "secretNumber",
       },
       },
       workId: this.$route.params.workId,
       workId: this.$route.params.workId,
       subjectId: this.$route.params.subjectId,
       subjectId: this.$route.params.subjectId,
@@ -75,7 +75,7 @@ export default {
       renderExportPage: false,
       renderExportPage: false,
       renderChartData: {},
       renderChartData: {},
       renderPageInfo: {},
       renderPageInfo: {},
-      isDownload: false
+      isDownload: false,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -84,7 +84,7 @@ export default {
         this.curUserRoleType === "ADMIN" ||
         this.curUserRoleType === "ADMIN" ||
         this.curUserRoleType === "SUPER_ADMIN"
         this.curUserRoleType === "SUPER_ADMIN"
       );
       );
-    }
+    },
   },
   },
   mounted() {
   mounted() {
     this.subject = this.subjectId.split("-")[1];
     this.subject = this.subjectId.split("-")[1];
@@ -104,13 +104,13 @@ export default {
     async getAreaList() {
     async getAreaList() {
       const data = await areaList({
       const data = await areaList({
         workId: this.workId,
         workId: this.workId,
-        subject: this.subject
+        subject: this.subject,
       });
       });
-      this.areas = data.map(item => {
+      this.areas = data.map((item) => {
         return {
         return {
           id: item.id,
           id: item.id,
           areaName: item.areaName,
           areaName: item.areaName,
-          areaCode: item.areaCode
+          areaCode: item.areaCode,
         };
         };
       });
       });
     },
     },
@@ -121,15 +121,15 @@ export default {
     toExport() {
     toExport() {
       this.isDownload = true;
       this.isDownload = true;
       const curArea = this.areas.find(
       const curArea = this.areas.find(
-        item => item.id === this.filter.questionId
+        (item) => item.id === this.filter.questionId
       );
       );
       this.renderPageInfo = {
       this.renderPageInfo = {
         subjectName: this.curSubject.name,
         subjectName: this.curSubject.name,
-        areaName: curArea.areaName
+        areaName: curArea.areaName,
       };
       };
       this.renderChartData = {
       this.renderChartData = {
         levelData: this.$refs.GradeAnalysis.levelData,
         levelData: this.$refs.GradeAnalysis.levelData,
-        lineChartData: this.$refs.GradeAnalysis.lineChartData
+        lineChartData: this.$refs.GradeAnalysis.lineChartData,
       };
       };
       this.renderExportPage = true;
       this.renderExportPage = true;
     },
     },
@@ -139,7 +139,7 @@ export default {
       }
       }
       this.renderExportPage = false;
       this.renderExportPage = false;
       this.isDownload = false;
       this.isDownload = false;
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 622 - 622
src/modules/grading/GradingDetail.vue

@@ -1,622 +1,622 @@
-<template>
-  <div :class="compClasses">
-    <grade-filter
-      ref="GradeFilter"
-      :data="workSubject"
-      @change="areaChange"
-    ></grade-filter>
-    <grade-step
-      :steps="steps"
-      :init-step="curStep"
-      @on-change="stepChange"
-      ref="GradeStep"
-      v-if="steps.levelStep"
-    ></grade-step>
-    <div class="detail-body">
-      <!-- detail-papers -->
-      <div :class="detailPapersClasses">
-        <div class="detail-papers-carousel">
-          <grade-standard-paper
-            :levels="levels"
-            :question-id="filter.questionId"
-            @on-paper-click="
-              (index, papers) => {
-                toViewCarouselPaper(index, papers, 'sample');
-              }
-            "
-            @on-paper-change="standardPaperChange"
-            v-if="levels.length && filter.questionId"
-            ref="GradeStandardPaper"
-          ></grade-standard-paper>
-          <grade-history-paper
-            :question-id="filter.questionId"
-            :stage="curSubject.stage"
-            @on-paper-click="
-              (index, papers) => {
-                toViewCarouselPaper(index, papers, 'history');
-              }
-            "
-            v-if="filter.questionId && !IS_ADMIN"
-            ref="GradeHistoryPaper"
-          ></grade-history-paper>
-        </div>
-        <div class="detail-papers-list" v-if="papers.length">
-          <div :class="imageViewClasses">
-            <div
-              :class="[
-                'image-view',
-                { 'image-view-act': curPaperIndex === index || image.selected }
-              ]"
-              v-for="(image, index) in papers"
-              :key="index"
-            >
-              <div class="image-view-container">
-                <h5 class="image-view-title">{{ image.title }}</h5>
-                <div class="image-view-contain">
-                  <img
-                    :src="image.thumbSrc"
-                    :alt="image.title"
-                    @click="toReview(index)"
-                  />
-                </div>
-                <div class="image-view-actions" v-if="ACTION_CAN_BATCH">
-                  <div
-                    :class="[
-                      'image-view-multibar',
-                      { 'image-view-selected': image.selected },
-                      { 'image-view-disabled': image.sample }
-                    ]"
-                    :title="image.sample ? '标准卷' : '选中批量操作'"
-                    @click="selectMultiplePaper(image)"
-                  ></div>
-                </div>
-              </div>
-            </div>
-          </div>
-          <div class="part-page">
-            <Page
-              :current="current"
-              :total="total"
-              :page-size="size"
-              show-total
-              show-elevator
-              @on-change="toPage"
-            ></Page>
-          </div>
-        </div>
-        <div class="detail-papers-list" v-else>
-          <p class="detail-papers-none">暂无数据</p>
-        </div>
-      </div>
-      <!-- detail-aciton -->
-      <div
-        :class="[
-          'detail-action',
-          { 'detail-action-fullscreen': isFullscreenMarking }
-        ]"
-        v-show="!multipleGradingList.length"
-      >
-        <grade-action
-          :key="paperKey"
-          :cur-paper-or-task="curPaper"
-          :levels="levels"
-          :params-set="paramsSet"
-          @on-leader-level="leaderSelectLevel"
-          @on-code-search="serachPaperByCode"
-          ref="GradeAction"
-          v-if="curPaper.id"
-        ></grade-action>
-      </div>
-      <!-- 占位 -->
-      <div class="detail-action" v-if="isFullscreenMarking"></div>
-      <!-- multiple grading action -->
-      <div class="detail-action" v-show="multipleGradingList.length">
-        <div class="grade-action">
-          <div class="action-paper-state">
-            <p class="paper-state-cont">批量操作</p>
-          </div>
-          <div class="action-grade-list">
-            <div
-              class="action-grade-item"
-              v-for="(level, index) in levels"
-              :key="index"
-            >
-              <div
-                :class="[
-                  'action-grade-item-content',
-                  { 'action-item-content-disabled': multiplebtnClicked }
-                ]"
-                @click="multipleSelectLevel(level)"
-              >
-                <p>{{ level.name | levelNameFilter }}</p>
-                <p>{{ level.minScore }}~{{ level.maxScore }}</p>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :class="imagePreviewClasses"
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      @on-close="isFullscreenMarking = false"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-    <!-- carousel paper review -->
-    <simple-image-preview
-      :class="imagePreviewClasses"
-      :cur-image="curPaper"
-      @on-prev="toCarousePaper('prev')"
-      @on-next="toCarousePaper('next')"
-      @on-close="carouseImagePreviewClose"
-      ref="CarouselPapersPreview"
-    ></simple-image-preview>
-    <!-- modify-leader-grading -->
-    <modify-leader-grading
-      :level-info="levelInfo"
-      :markers="markers"
-      :stage="curSubject.stage"
-      @modified="leaderGradingSuccess"
-      @canceled="leaderGradingCancel"
-      ref="ModifyLeaderGrading"
-    ></modify-leader-grading>
-  </div>
-</template>
-
-<script>
-import {
-  paperList,
-  levelStatData,
-  workLevelList,
-  taskSnSearch,
-  subjectDetail,
-  markHistoryList,
-  getParamsSet,
-  leaderGradingPaper
-} from "@/api";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import GradeFilter from "./components/GradeFilter";
-import GradeStep from "./components/GradeStep";
-import GradeStandardPaper from "./components/GradeStandardPaper";
-import GradeHistoryPaper from "./components/GradeHistoryPaper";
-import GradeAction from "./components/GradeAction";
-import ModifyLeaderGrading from "./components/ModifyLeaderGrading";
-// 三种情况:
-// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
-// 管理员:标准卷,试卷列表,操作盘
-// 科组长:标准卷,操作记录,试卷列表,操作盘(定档,标准卷,打回)
-
-// TIP:不考虑评卷员的情况
-// 评卷员:标准卷,操作记录,试卷列表,操作盘(只分档)
-
-export default {
-  name: "grading-detail",
-  components: {
-    SimpleImagePreview,
-    GradeFilter,
-    GradeStep,
-    GradeHistoryPaper,
-    GradeStandardPaper,
-    GradeAction,
-    ModifyLeaderGrading
-  },
-  data() {
-    return {
-      filter: {
-        questionId: "",
-        sort: "secretNumber"
-      },
-      typeFilter: {
-        done: {
-          level: ""
-        },
-        reject: {
-          reject: true
-        },
-        arbitrate: {
-          arbi: true
-        }
-      },
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      workSubject: {},
-      curSubject: {},
-      curUserRoleType: "MARKER",
-      current: 1,
-      size: 6,
-      total: 0,
-      totalPage: 1,
-      curStep: { type: "", name: "" },
-      steps: {},
-      levels: [],
-      curArea: {},
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      paramsSet: { collectConfig: {} },
-      paperKey: "",
-      // leader-grade
-      levelInfo: {},
-      markers: [],
-      // carousel paper review,
-      carouselType: "",
-      carouselPapers: [],
-      curCarouselPaperIndex: 0,
-      isFullscreenMarking: false,
-      // multiple grading
-      multiplebtnClicked: false,
-      multipleGradingList: []
-    };
-  },
-  computed: {
-    compClasses() {
-      return [
-        "page-container-flex",
-        "grading-detail",
-        { "grading-operation": this.IS_MARK_LEADER }
-      ];
-    },
-    detailPapersClasses() {
-      return ["detail-papers", `detail-papers-col-${1 + this.size / 2}`];
-    },
-    imageViewClasses() {
-      return ["image-view-list", `image-view-list-${this.size / 2}`];
-    },
-    IS_ADMIN() {
-      return this.curUserRoleType === "ADMIN";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    },
-    IS_TEST() {
-      return this.curSubject.test === 2;
-    },
-    ACTION_CAN_BATCH() {
-      return (
-        this.curStep.type === "done" &&
-        this.IS_MARK_LEADER &&
-        !this.paramsSet.collectConfig.paperStage
-      );
-    },
-    imagePreviewClasses() {
-      return this.IS_ADMIN
-        ? "grading-detail-image-preview"
-        : "grading-operation-image-preview";
-    }
-  },
-  created() {
-    this.subject = this.subjectId.split("-")[1];
-    this.workSubject = {
-      workId: this.workId,
-      subject: this.subject
-    };
-    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.initData();
-  },
-  methods: {
-    async initData() {
-      await this.getParamsSetInfo();
-      await this.getSubjectDetail();
-      // 获取档位列表
-      this.getWorkLevels();
-    },
-    async getParamsSetInfo() {
-      this.paramsSet = await getParamsSet(this.workId);
-    },
-    async getList() {
-      this.multipleGradingList = [];
-      const datas = {
-        ...this.filter,
-        ...this.typeFilter[this.curStep.type],
-        page: this.current - 1,
-        size: this.size
-      };
-      if (this.curStep.type === "done") datas.level = this.curStep.name;
-
-      const data = await paperList(datas);
-      this.papers = data.data.map(paper => {
-        paper.title = `NO.${paper.sn}`;
-        // paper.title = this.IS_ADMIN ? paper.examNumber : `NO.${paper.sn}`;
-        paper.selected = false;
-        return paper;
-      });
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-    },
-    async toPage(page) {
-      this.current = page;
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async getSubjectDetail() {
-      this.curSubject = await subjectDetail(this.subjectId);
-    },
-    async getStepLevels() {
-      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,
-        arbitrated: 0
-      };
-      if (undoIndex !== -1) {
-        undo = { ...data[undoIndex] };
-        data.splice(undoIndex, 1);
-      }
-
-      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 => {
-        return {
-          ...item,
-          name: item.id,
-          type: "done"
-        };
-      });
-      this.steps = { levelStep, otherStep };
-
-      if (!this.curStep.type) {
-        this.curStep = levelStep[0];
-      }
-    },
-    async getWorkLevels() {
-      const data = await workLevelList(this.workId, this.curSubject.stage);
-      this.levels = data || [];
-    },
-    async stepChange(step) {
-      this.curStep = step;
-
-      this.current = 1;
-      await this.getList();
-      if (this.papers.length) {
-        this.selectPaper(0);
-      } else {
-        this.curPaper = {};
-      }
-    },
-    async areaChange(curArea) {
-      this.curArea = curArea;
-      this.filter.questionId = curArea.id;
-      await this.getStepLevels();
-      this.toPage(1);
-    },
-    // selectMultiplePaper
-    selectMultiplePaper(paper) {
-      if (paper.sample) return;
-      paper.selected = !paper.selected;
-      this.multipleGradingList = this.papers.filter(paper => paper.selected);
-    },
-    async multipleSelectLevel(level) {
-      if (!this.multipleGradingList.length) return;
-      if (this.multiplebtnClicked) return;
-      this.multiplebtnClicked = true;
-
-      const data = await markHistoryList(
-        this.multipleGradingList[0].id,
-        this.curSubject.stage
-      ).catch(() => {});
-      this.multiplebtnClicked = false;
-      if (!data) return;
-
-      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();
-    },
-    // to review
-    toReview(index) {
-      this.isFullscreenMarking = true;
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      this.paperKey = this.$randomCode();
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toActionNextPaper() {
-      if (this.current > 1 && this.papers.length === 1) {
-        this.current--;
-        this.curPaperIndex = this.size;
-      }
-
-      await this.getList();
-      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
-      this.selectPaper(this.curPaperIndex);
-    },
-    updateHistory() {
-      this.$refs.GradeHistoryPaper.updatePapers();
-    },
-    async serachPaperByCode(params) {
-      const data = await taskSnSearch(
-        params.codeType,
-        params.code,
-        this.filter.questionId,
-        this.curSubject.stage
-      );
-      if (!data) {
-        this.$Message.error("没有查找到结果!");
-        return;
-      }
-      data.title = `NO.${data.sn}`;
-      data.key = this.$randomCode();
-      // data.title = this.IS_ADMIN ? data.examNumber : `NO.${data.sn}`;
-      this.papers = [data];
-      this.total = 1;
-      this.selectPaper(0);
-    },
-    async leaderSelectLevel(levelInfo, markers) {
-      // 唯一权限时,直接操作
-      // TODO:
-      if (levelInfo.markLeaderOnlyRight && !this.paramsSet.leaderConfirm) {
-        const datas = {
-          action: levelInfo.markLeaderOnlyRight.action,
-          level: levelInfo.selectedLevel,
-          originLevel: levelInfo.curLevel,
-          paperIds: levelInfo.paperIds,
-          stage: this.curSubject.stage
-        };
-        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.GradeStandardPaper) {
-        this.$refs.GradeStandardPaper.updateLevelPapers(datas.level);
-      }
-      this.getStepLevels();
-      this.updateHistory();
-
-      if (this.multipleGradingList && this.multipleGradingList.length) {
-        // 批量处理逻辑
-        if (
-          this.current > 1 &&
-          this.current === this.pageCount &&
-          this.papers.length === this.multipleGradingList.length
-        ) {
-          this.current--;
-        }
-
-        this.multipleGradingList = [];
-        await this.getList();
-        this.selectPaper(this.curPaperIndex);
-      } else {
-        // 单张处理逻辑
-        this.toActionNextPaper();
-      }
-    },
-    leaderGradingCancel() {
-      this.$refs.GradeAction.btnClicked = false;
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers, type) {
-      this.carouselType = type;
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-      });
-    },
-    selectCarouselPaper(index) {
-      this.paperKey = this.$randomCode();
-      this.curCarouselPaperIndex = index;
-      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 (
-        type === "next" &&
-        this.curCarouselPaperIndex < this.carouselPapers.length - 1
-      ) {
-        this.curCarouselPaperIndex++;
-      }
-      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 = "";
-      this.selectPaper(this.curPaperIndex);
-    },
-    standardPaperChange(curPaper) {
-      if (!this.isFullscreenMarking) return;
-      this.curPaper = { ...curPaper };
-    }
-  }
-};
-</script>
+<template>
+  <div :class="compClasses">
+    <grade-filter
+      ref="GradeFilter"
+      :data="workSubject"
+      @change="areaChange"
+    ></grade-filter>
+    <grade-step
+      :steps="steps"
+      :init-step="curStep"
+      @on-change="stepChange"
+      ref="GradeStep"
+      v-if="steps.levelStep"
+    ></grade-step>
+    <div class="detail-body">
+      <!-- detail-papers -->
+      <div :class="detailPapersClasses">
+        <div class="detail-papers-carousel">
+          <grade-standard-paper
+            :levels="levels"
+            :question-id="filter.questionId"
+            @on-paper-click="
+              (index, papers) => {
+                toViewCarouselPaper(index, papers, 'sample');
+              }
+            "
+            @on-paper-change="standardPaperChange"
+            v-if="levels.length && filter.questionId"
+            ref="GradeStandardPaper"
+          ></grade-standard-paper>
+          <grade-history-paper
+            :question-id="filter.questionId"
+            :stage="curSubject.stage"
+            @on-paper-click="
+              (index, papers) => {
+                toViewCarouselPaper(index, papers, 'history');
+              }
+            "
+            v-if="filter.questionId && !IS_ADMIN"
+            ref="GradeHistoryPaper"
+          ></grade-history-paper>
+        </div>
+        <div class="detail-papers-list" v-if="papers.length">
+          <div :class="imageViewClasses">
+            <div
+              :class="[
+                'image-view',
+                { 'image-view-act': curPaperIndex === index || image.selected },
+              ]"
+              v-for="(image, index) in papers"
+              :key="index"
+            >
+              <div class="image-view-container">
+                <h5 class="image-view-title">{{ image.title }}</h5>
+                <div class="image-view-contain">
+                  <img
+                    :src="image.thumbSrc"
+                    :alt="image.title"
+                    @click="toReview(index)"
+                  />
+                </div>
+                <div class="image-view-actions" v-if="ACTION_CAN_BATCH">
+                  <div
+                    :class="[
+                      'image-view-multibar',
+                      { 'image-view-selected': image.selected },
+                      { 'image-view-disabled': image.sample },
+                    ]"
+                    :title="image.sample ? '标准卷' : '选中批量操作'"
+                    @click="selectMultiplePaper(image)"
+                  ></div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="part-page">
+            <Page
+              :current="current"
+              :total="total"
+              :page-size="size"
+              show-total
+              show-elevator
+              @on-change="toPage"
+            ></Page>
+          </div>
+        </div>
+        <div class="detail-papers-list" v-else>
+          <p class="detail-papers-none">暂无数据</p>
+        </div>
+      </div>
+      <!-- detail-aciton -->
+      <div
+        :class="[
+          'detail-action',
+          { 'detail-action-fullscreen': isFullscreenMarking },
+        ]"
+        v-show="!multipleGradingList.length"
+      >
+        <grade-action
+          :key="paperKey"
+          :cur-paper-or-task="curPaper"
+          :levels="levels"
+          :params-set="paramsSet"
+          @on-leader-level="leaderSelectLevel"
+          @on-code-search="serachPaperByCode"
+          ref="GradeAction"
+          v-if="curPaper.id"
+        ></grade-action>
+      </div>
+      <!-- 占位 -->
+      <div class="detail-action" v-if="isFullscreenMarking"></div>
+      <!-- multiple grading action -->
+      <div class="detail-action" v-show="multipleGradingList.length">
+        <div class="grade-action">
+          <div class="action-paper-state">
+            <p class="paper-state-cont">批量操作</p>
+          </div>
+          <div class="action-grade-list">
+            <div
+              class="action-grade-item"
+              v-for="(level, index) in levels"
+              :key="index"
+            >
+              <div
+                :class="[
+                  'action-grade-item-content',
+                  { 'action-item-content-disabled': multiplebtnClicked },
+                ]"
+                @click="multipleSelectLevel(level)"
+              >
+                <p>{{ level.name | levelNameFilter }}</p>
+                <p>{{ level.minScore }}~{{ level.maxScore }}</p>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :class="imagePreviewClasses"
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      @on-close="isFullscreenMarking = false"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+    <!-- carousel paper review -->
+    <simple-image-preview
+      :class="imagePreviewClasses"
+      :cur-image="curPaper"
+      @on-prev="toCarousePaper('prev')"
+      @on-next="toCarousePaper('next')"
+      @on-close="carouseImagePreviewClose"
+      ref="CarouselPapersPreview"
+    ></simple-image-preview>
+    <!-- modify-leader-grading -->
+    <modify-leader-grading
+      :level-info="levelInfo"
+      :markers="markers"
+      :stage="curSubject.stage"
+      @modified="leaderGradingSuccess"
+      @canceled="leaderGradingCancel"
+      ref="ModifyLeaderGrading"
+    ></modify-leader-grading>
+  </div>
+</template>
+
+<script>
+import {
+  paperList,
+  levelStatData,
+  workLevelList,
+  taskSnSearch,
+  subjectDetail,
+  markHistoryList,
+  getParamsSet,
+  leaderGradingPaper,
+} from "@/api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import GradeFilter from "./components/GradeFilter";
+import GradeStep from "./components/GradeStep";
+import GradeStandardPaper from "./components/GradeStandardPaper";
+import GradeHistoryPaper from "./components/GradeHistoryPaper";
+import GradeAction from "./components/GradeAction";
+import ModifyLeaderGrading from "./components/ModifyLeaderGrading";
+// 三种情况:
+// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
+// 管理员:标准卷,试卷列表,操作盘
+// 科组长:标准卷,操作记录,试卷列表,操作盘(定档,标准卷,打回)
+
+// TIP:不考虑评卷员的情况
+// 评卷员:标准卷,操作记录,试卷列表,操作盘(只分档)
+
+export default {
+  name: "grading-detail",
+  components: {
+    SimpleImagePreview,
+    GradeFilter,
+    GradeStep,
+    GradeHistoryPaper,
+    GradeStandardPaper,
+    GradeAction,
+    ModifyLeaderGrading,
+  },
+  data() {
+    return {
+      filter: {
+        questionId: "",
+        sort: "secretNumber",
+      },
+      typeFilter: {
+        done: {
+          level: "",
+        },
+        reject: {
+          reject: true,
+        },
+        arbitrate: {
+          arbi: true,
+        },
+      },
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      workSubject: {},
+      curSubject: {},
+      curUserRoleType: "MARKER",
+      current: 1,
+      size: 6,
+      total: 0,
+      totalPage: 1,
+      curStep: { type: "", name: "" },
+      steps: {},
+      levels: [],
+      curArea: {},
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      paramsSet: { collectConfig: {} },
+      paperKey: "",
+      // leader-grade
+      levelInfo: {},
+      markers: [],
+      // carousel paper review,
+      carouselType: "",
+      carouselPapers: [],
+      curCarouselPaperIndex: 0,
+      isFullscreenMarking: false,
+      // multiple grading
+      multiplebtnClicked: false,
+      multipleGradingList: [],
+    };
+  },
+  computed: {
+    compClasses() {
+      return [
+        "page-container-flex",
+        "grading-detail",
+        { "grading-operation": this.IS_MARK_LEADER },
+      ];
+    },
+    detailPapersClasses() {
+      return ["detail-papers", `detail-papers-col-${1 + this.size / 2}`];
+    },
+    imageViewClasses() {
+      return ["image-view-list", `image-view-list-${this.size / 2}`];
+    },
+    IS_ADMIN() {
+      return this.curUserRoleType === "ADMIN";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    },
+    IS_TEST() {
+      return this.curSubject.test === 2;
+    },
+    ACTION_CAN_BATCH() {
+      return (
+        this.curStep.type === "done" &&
+        this.IS_MARK_LEADER &&
+        !this.paramsSet.collectConfig.paperStage
+      );
+    },
+    imagePreviewClasses() {
+      return this.IS_ADMIN
+        ? "grading-detail-image-preview"
+        : "grading-operation-image-preview";
+    },
+  },
+  created() {
+    this.subject = this.subjectId.split("-")[1];
+    this.workSubject = {
+      workId: this.workId,
+      subject: this.subject,
+    };
+    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      await this.getParamsSetInfo();
+      await this.getSubjectDetail();
+      // 获取档位列表
+      this.getWorkLevels();
+    },
+    async getParamsSetInfo() {
+      this.paramsSet = await getParamsSet(this.workId);
+    },
+    async getList() {
+      this.multipleGradingList = [];
+      const datas = {
+        ...this.filter,
+        ...this.typeFilter[this.curStep.type],
+        page: this.current - 1,
+        size: this.size,
+      };
+      if (this.curStep.type === "done") datas.level = this.curStep.name;
+
+      const data = await paperList(datas);
+      this.papers = data.data.map((paper) => {
+        paper.title = `NO.${paper.sn}`;
+        // paper.title = this.IS_ADMIN ? paper.examNumber : `NO.${paper.sn}`;
+        paper.selected = false;
+        return paper;
+      });
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+    },
+    async toPage(page) {
+      this.current = page;
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async getSubjectDetail() {
+      this.curSubject = await subjectDetail(this.subjectId);
+    },
+    async getStepLevels() {
+      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,
+        arbitrated: 0,
+      };
+      if (undoIndex !== -1) {
+        undo = { ...data[undoIndex] };
+        data.splice(undoIndex, 1);
+      }
+
+      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) => {
+        return {
+          ...item,
+          name: item.id,
+          type: "done",
+        };
+      });
+      this.steps = { levelStep, otherStep };
+
+      if (!this.curStep.type) {
+        this.curStep = levelStep[0];
+      }
+    },
+    async getWorkLevels() {
+      const data = await workLevelList(this.workId, this.curSubject.stage);
+      this.levels = data || [];
+    },
+    async stepChange(step) {
+      this.curStep = step;
+
+      this.current = 1;
+      await this.getList();
+      if (this.papers.length) {
+        this.selectPaper(0);
+      } else {
+        this.curPaper = {};
+      }
+    },
+    async areaChange(curArea) {
+      this.curArea = curArea;
+      this.filter.questionId = curArea.id;
+      await this.getStepLevels();
+      this.toPage(1);
+    },
+    // selectMultiplePaper
+    selectMultiplePaper(paper) {
+      if (paper.sample) return;
+      paper.selected = !paper.selected;
+      this.multipleGradingList = this.papers.filter((paper) => paper.selected);
+    },
+    async multipleSelectLevel(level) {
+      if (!this.multipleGradingList.length) return;
+      if (this.multiplebtnClicked) return;
+      this.multiplebtnClicked = true;
+
+      const data = await markHistoryList(
+        this.multipleGradingList[0].id,
+        this.curSubject.stage
+      ).catch(() => {});
+      this.multiplebtnClicked = false;
+      if (!data) return;
+
+      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();
+    },
+    // to review
+    toReview(index) {
+      this.isFullscreenMarking = true;
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      this.paperKey = this.$randomCode();
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toActionNextPaper() {
+      if (this.current > 1 && this.papers.length === 1) {
+        this.current--;
+        this.curPaperIndex = this.size;
+      }
+
+      await this.getList();
+      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
+      this.selectPaper(this.curPaperIndex);
+    },
+    updateHistory() {
+      this.$refs.GradeHistoryPaper.updatePapers();
+    },
+    async serachPaperByCode(params) {
+      const data = await taskSnSearch(
+        params.codeType,
+        params.code,
+        this.filter.questionId,
+        this.curSubject.stage
+      );
+      if (!data) {
+        this.$Message.error("没有查找到结果!");
+        return;
+      }
+      data.title = `NO.${data.sn}`;
+      data.key = this.$randomCode();
+      // data.title = this.IS_ADMIN ? data.examNumber : `NO.${data.sn}`;
+      this.papers = [data];
+      this.total = 1;
+      this.selectPaper(0);
+    },
+    async leaderSelectLevel(levelInfo, markers) {
+      // 唯一权限时,直接操作
+      // TODO:
+      if (levelInfo.markLeaderOnlyRight && !this.paramsSet.leaderConfirm) {
+        const datas = {
+          action: levelInfo.markLeaderOnlyRight.action,
+          level: levelInfo.selectedLevel,
+          originLevel: levelInfo.curLevel,
+          paperIds: levelInfo.paperIds,
+          stage: this.curSubject.stage,
+        };
+        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.GradeStandardPaper) {
+        this.$refs.GradeStandardPaper.updateLevelPapers(datas.level);
+      }
+      this.getStepLevels();
+      this.updateHistory();
+
+      if (this.multipleGradingList && this.multipleGradingList.length) {
+        // 批量处理逻辑
+        if (
+          this.current > 1 &&
+          this.current === this.pageCount &&
+          this.papers.length === this.multipleGradingList.length
+        ) {
+          this.current--;
+        }
+
+        this.multipleGradingList = [];
+        await this.getList();
+        this.selectPaper(this.curPaperIndex);
+      } else {
+        // 单张处理逻辑
+        this.toActionNextPaper();
+      }
+    },
+    leaderGradingCancel() {
+      this.$refs.GradeAction.btnClicked = false;
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers, type) {
+      this.carouselType = type;
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+      });
+    },
+    selectCarouselPaper(index) {
+      this.paperKey = this.$randomCode();
+      this.curCarouselPaperIndex = index;
+      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 (
+        type === "next" &&
+        this.curCarouselPaperIndex < this.carouselPapers.length - 1
+      ) {
+        this.curCarouselPaperIndex++;
+      }
+      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 = "";
+      this.selectPaper(this.curPaperIndex);
+    },
+    standardPaperChange(curPaper) {
+      if (!this.isFullscreenMarking) return;
+      this.curPaper = { ...curPaper };
+    },
+  },
+};
+</script>

+ 260 - 260
src/modules/grading/GradingGroupManage.vue

@@ -1,260 +1,260 @@
-<template>
-  <div class="grading-group-manage">
-    <div class="group-user part-box" v-if="users.length">
-      <draggable class="group-user-list" group="user" :list="users">
-        <Button size="small" v-for="user in users" :key="user.id">
-          {{ user.loginName }}
-        </Button>
-      </draggable>
-      <Button
-        class="group-user-action"
-        shape="circle"
-        type="success"
-        icon="recode-white icon"
-        @click="toAddGroup"
-        >新增分组</Button
-      >
-    </div>
-    <div :class="groupListClasses">
-      <div class="group-box" v-for="(group, gindex) in groups" :key="gindex">
-        <div class="group-container">
-          <div class="group-head">
-            <h2 class="group-name">{{ group.name }}</h2>
-            <div class="group-del" @click="delGroup(gindex)">
-              <Icon type="md-close" />
-            </div>
-          </div>
-          <div class="group-body">
-            <draggable class="group-drag" group="user" :list="group.markers">
-              <Tag
-                size="large"
-                v-for="(user, uindex) in group.markers"
-                :key="uindex"
-                @on-close="removeGroupUser(uindex, group)"
-                closable
-              >
-                {{ user.loginName }}
-              </Tag>
-            </draggable>
-          </div>
-          <div v-if="group.id && !IS_SCORE" class="group-footer">
-            <Button
-              shape="circle"
-              type="primary"
-              ghost
-              icon="upload icon"
-              @click="toImportGroupStudent(group)"
-              >导入考生</Button
-            >
-            <Button
-              shape="circle"
-              icon="md-trash"
-              type="error"
-              ghost
-              :disabled="!group.hasStudent"
-              @click="toDeleteGroupStudent(group)"
-              >删除考生</Button
-            >
-          </div>
-        </div>
-      </div>
-    </div>
-    <div class="group-action">
-      <Button
-        shape="circle"
-        type="primary"
-        @click="submit"
-        :disabled="!this.groups.length || isSubmit"
-        >确认</Button
-      >
-    </div>
-
-    <!-- import student  -->
-    <import-file
-      :title="uploadTitle"
-      :upload-url="uploadStudentUrl"
-      :upload-data="uploadData"
-      :download-url="downloadStudentTemplateUrl"
-      :download-filename="downloadStudentTemplateFilename"
-      :headers="headers"
-      :format="['xls', 'xlsx']"
-      @upload-success="uploadSuccess"
-      ref="ExportStudent"
-    >
-      <div class="tips-info" slot="head">
-        <Icon type="md-alert" /> 进入试评后,导入的数据将被清理!
-      </div>
-    </import-file>
-  </div>
-</template>
-
-<script>
-import { mapState } from "vuex";
-import {
-  gradingGroupList,
-  markUserList,
-  updateGradingGroup,
-  deleteGradingGroup,
-  deleteGradeGroupStudent
-} from "@/api";
-import draggable from "vuedraggable";
-import ImportFile from "@/components/common/ImportFile";
-
-export default {
-  name: "grading-group-manage",
-  components: { draggable, ImportFile },
-  data() {
-    return {
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      groups: [],
-      users: [],
-      isSubmit: false,
-      // upload
-      uploadTitle: "",
-      headers: {
-        Authorization: this.$ls.get("user", { token: "" }).token,
-        workId: this.$route.params.workId,
-        userId: this.$ls.get("user", { id: "" }).id
-      },
-      uploadData: {
-        workId: this.$route.params.workId,
-        subject: "",
-        stage: null,
-        groupId: null
-      },
-      uploadStudentUrl:
-        this.GLOBAL.domain + "/api/import/students/import_group_student",
-      downloadStudentTemplateUrl: "/templates/考生信息表-模板.xlsx",
-      downloadStudentTemplateFilename: "考生名单表-模板.xlsx"
-    };
-  },
-  computed: {
-    ...mapState("marker", ["curSubject"]),
-    groupListClasses() {
-      const num = this.groups.length;
-      return ["group-list", `group-list-${num}`];
-    },
-    IS_SCORE() {
-      return this.curSubject.stage === "SCORE";
-    }
-  },
-  mounted() {
-    this.subject = this.subjectId.split("-")[1];
-    this.uploadData.subject = this.subject;
-    this.initData();
-  },
-  methods: {
-    initData() {
-      this.getGroupList();
-      this.getMarkUserList();
-    },
-    async getGroupList() {
-      this.groups = await gradingGroupList(this.subjectId);
-    },
-    async getMarkUserList() {
-      const data = await markUserList({
-        workId: this.workId,
-        subjectId: this.subjectId.split("-")[1]
-      });
-      this.users = data.filter(user => !user.groupId);
-    },
-    submit() {
-      if (this.isSubmit) return;
-      const hasNoneGroup = this.groups.some(group => !group.markers.length);
-      if (hasNoneGroup) {
-        this.$Message.error("当前分组列表中存在空组!");
-        return;
-      }
-      const hasNoneLeaderGroup = this.groups.some(
-        group => !group.markers.some(marker => marker.role === "MARK_LEADER")
-      );
-      if (hasNoneLeaderGroup) {
-        this.$Message.error("请确认每一个分组都有科组长!");
-        return;
-      }
-      this.save();
-    },
-    async save() {
-      this.isSubmit = true;
-      for (let i = 0; i < this.groups.length; i++) {
-        const group = this.groups[i];
-        let result = await updateGradingGroup(
-          this.subjectId,
-          group
-        ).catch(() => {});
-        if (!result) {
-          this.isSubmit = false;
-          this.$Message.error("保存失败,请重新尝试!");
-          return;
-        }
-      }
-      this.isSubmit = false;
-      this.$Message.success("保存成功!");
-      this.initData();
-    },
-    toAddGroup() {
-      this.groups.push({
-        id: "",
-        name: "评卷组" + (this.groups.length + 1),
-        markers: [],
-        subject: this.subject,
-        workId: this.workId
-      });
-    },
-    removeGroupUser(uindex, group) {
-      this.users.push({ ...group.markers[uindex] });
-      group.markers.splice(uindex, 1);
-    },
-    delGroup(gindex) {
-      const group = this.groups[gindex];
-      if (!group.id) {
-        this.removeGroup(gindex);
-        return;
-      }
-
-      this.$Modal.confirm({
-        content: "确定要删除当前分组吗?",
-        onOk: async () => {
-          await deleteGradingGroup(this.subjectId, group.id);
-          this.removeGroup(gindex);
-          this.$Message.success("删除成功!");
-        }
-      });
-    },
-    removeGroup(gindex) {
-      const group = this.groups[gindex];
-      this.users = [...this.users, ...group.markers];
-      this.groups.splice(gindex, 1);
-      this.groups.map((group, index) => {
-        group.name = "评卷组" + (index + 1);
-      });
-    },
-    toImportGroupStudent(group) {
-      this.uploadTitle = `导入考生名单-${group.name}`;
-      this.uploadData.groupId = group.id;
-      this.uploadData.stage = this.curSubject.stage;
-      this.$refs.ExportStudent.open();
-    },
-    uploadSuccess() {
-      this.getGroupList();
-      this.$Notice.success({
-        title: "导入提示",
-        desc: "考生名单导入成功!",
-        duration: 0
-      });
-    },
-    toDeleteGroupStudent(group) {
-      this.$Modal.confirm({
-        content: "确定要删除当前分组下的考生吗?",
-        onOk: async () => {
-          await deleteGradeGroupStudent(this.subject, group.id);
-          this.getGroupList();
-          this.$Message.success("删除成功!");
-        }
-      });
-    }
-  }
-};
-</script>
+<template>
+  <div class="grading-group-manage">
+    <div class="group-user part-box" v-if="users.length">
+      <draggable class="group-user-list" group="user" :list="users">
+        <Button size="small" v-for="user in users" :key="user.id">
+          {{ user.loginName }}
+        </Button>
+      </draggable>
+      <Button
+        class="group-user-action"
+        shape="circle"
+        type="success"
+        icon="recode-white icon"
+        @click="toAddGroup"
+        >新增分组</Button
+      >
+    </div>
+    <div :class="groupListClasses">
+      <div class="group-box" v-for="(group, gindex) in groups" :key="gindex">
+        <div class="group-container">
+          <div class="group-head">
+            <h2 class="group-name">{{ group.name }}</h2>
+            <div class="group-del" @click="delGroup(gindex)">
+              <Icon type="md-close" />
+            </div>
+          </div>
+          <div class="group-body">
+            <draggable class="group-drag" group="user" :list="group.markers">
+              <Tag
+                size="large"
+                v-for="(user, uindex) in group.markers"
+                :key="uindex"
+                @on-close="removeGroupUser(uindex, group)"
+                closable
+              >
+                {{ user.loginName }}
+              </Tag>
+            </draggable>
+          </div>
+          <div v-if="group.id && !IS_SCORE" class="group-footer">
+            <Button
+              shape="circle"
+              type="primary"
+              ghost
+              icon="upload icon"
+              @click="toImportGroupStudent(group)"
+              >导入考生</Button
+            >
+            <Button
+              shape="circle"
+              icon="md-trash"
+              type="error"
+              ghost
+              :disabled="!group.hasStudent"
+              @click="toDeleteGroupStudent(group)"
+              >删除考生</Button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="group-action">
+      <Button
+        shape="circle"
+        type="primary"
+        @click="submit"
+        :disabled="!this.groups.length || isSubmit"
+        >确认</Button
+      >
+    </div>
+
+    <!-- import student  -->
+    <import-file
+      :title="uploadTitle"
+      :upload-url="uploadStudentUrl"
+      :upload-data="uploadData"
+      :download-url="downloadStudentTemplateUrl"
+      :download-filename="downloadStudentTemplateFilename"
+      :headers="headers"
+      :format="['xls', 'xlsx']"
+      @upload-success="uploadSuccess"
+      ref="ExportStudent"
+    >
+      <div class="tips-info" slot="head">
+        <Icon type="md-alert" /> 进入试评后,导入的数据将被清理!
+      </div>
+    </import-file>
+  </div>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import {
+  gradingGroupList,
+  markUserList,
+  updateGradingGroup,
+  deleteGradingGroup,
+  deleteGradeGroupStudent,
+} from "@/api";
+import draggable from "vuedraggable";
+import ImportFile from "@/components/common/ImportFile";
+
+export default {
+  name: "grading-group-manage",
+  components: { draggable, ImportFile },
+  data() {
+    return {
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      groups: [],
+      users: [],
+      isSubmit: false,
+      // upload
+      uploadTitle: "",
+      headers: {
+        Authorization: this.$ls.get("user", { token: "" }).token,
+        workId: this.$route.params.workId,
+        userId: this.$ls.get("user", { id: "" }).id,
+      },
+      uploadData: {
+        workId: this.$route.params.workId,
+        subject: "",
+        stage: null,
+        groupId: null,
+      },
+      uploadStudentUrl:
+        this.GLOBAL.domain + "/api/import/students/import_group_student",
+      downloadStudentTemplateUrl: "/templates/考生信息表-模板.xlsx",
+      downloadStudentTemplateFilename: "考生名单表-模板.xlsx",
+    };
+  },
+  computed: {
+    ...mapState("marker", ["curSubject"]),
+    groupListClasses() {
+      const num = this.groups.length;
+      return ["group-list", `group-list-${num}`];
+    },
+    IS_SCORE() {
+      return this.curSubject.stage === "SCORE";
+    },
+  },
+  mounted() {
+    this.subject = this.subjectId.split("-")[1];
+    this.uploadData.subject = this.subject;
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.getGroupList();
+      this.getMarkUserList();
+    },
+    async getGroupList() {
+      this.groups = await gradingGroupList(this.subjectId);
+    },
+    async getMarkUserList() {
+      const data = await markUserList({
+        workId: this.workId,
+        subjectId: this.subjectId.split("-")[1],
+      });
+      this.users = data.filter((user) => !user.groupId);
+    },
+    submit() {
+      if (this.isSubmit) return;
+      const hasNoneGroup = this.groups.some((group) => !group.markers.length);
+      if (hasNoneGroup) {
+        this.$Message.error("当前分组列表中存在空组!");
+        return;
+      }
+      const hasNoneLeaderGroup = this.groups.some(
+        (group) =>
+          !group.markers.some((marker) => marker.role === "MARK_LEADER")
+      );
+      if (hasNoneLeaderGroup) {
+        this.$Message.error("请确认每一个分组都有科组长!");
+        return;
+      }
+      this.save();
+    },
+    async save() {
+      this.isSubmit = true;
+      for (let i = 0; i < this.groups.length; i++) {
+        const group = this.groups[i];
+        let result = await updateGradingGroup(this.subjectId, group).catch(
+          () => {}
+        );
+        if (!result) {
+          this.isSubmit = false;
+          this.$Message.error("保存失败,请重新尝试!");
+          return;
+        }
+      }
+      this.isSubmit = false;
+      this.$Message.success("保存成功!");
+      this.initData();
+    },
+    toAddGroup() {
+      this.groups.push({
+        id: "",
+        name: "评卷组" + (this.groups.length + 1),
+        markers: [],
+        subject: this.subject,
+        workId: this.workId,
+      });
+    },
+    removeGroupUser(uindex, group) {
+      this.users.push({ ...group.markers[uindex] });
+      group.markers.splice(uindex, 1);
+    },
+    delGroup(gindex) {
+      const group = this.groups[gindex];
+      if (!group.id) {
+        this.removeGroup(gindex);
+        return;
+      }
+
+      this.$Modal.confirm({
+        content: "确定要删除当前分组吗?",
+        onOk: async () => {
+          await deleteGradingGroup(this.subjectId, group.id);
+          this.removeGroup(gindex);
+          this.$Message.success("删除成功!");
+        },
+      });
+    },
+    removeGroup(gindex) {
+      const group = this.groups[gindex];
+      this.users = [...this.users, ...group.markers];
+      this.groups.splice(gindex, 1);
+      this.groups.map((group, index) => {
+        group.name = "评卷组" + (index + 1);
+      });
+    },
+    toImportGroupStudent(group) {
+      this.uploadTitle = `导入考生名单-${group.name}`;
+      this.uploadData.groupId = group.id;
+      this.uploadData.stage = this.curSubject.stage;
+      this.$refs.ExportStudent.open();
+    },
+    uploadSuccess() {
+      this.getGroupList();
+      this.$Notice.success({
+        title: "导入提示",
+        desc: "考生名单导入成功!",
+        duration: 0,
+      });
+    },
+    toDeleteGroupStudent(group) {
+      this.$Modal.confirm({
+        content: "确定要删除当前分组下的考生吗?",
+        onOk: async () => {
+          await deleteGradeGroupStudent(this.subject, group.id);
+          this.getGroupList();
+          this.$Message.success("删除成功!");
+        },
+      });
+    },
+  },
+};
+</script>

+ 30 - 30
src/modules/grading/GradingOperation.vue

@@ -50,8 +50,8 @@
                       'image-view',
                       'image-view',
                       {
                       {
                         'image-view-act':
                         'image-view-act':
-                          curPaperIndex === index || image.selected
-                      }
+                          curPaperIndex === index || image.selected,
+                      },
                     ]"
                     ]"
                     v-for="(image, index) in papers"
                     v-for="(image, index) in papers"
                     :key="index"
                     :key="index"
@@ -70,7 +70,7 @@
                           :class="[
                           :class="[
                             'image-view-multibar',
                             'image-view-multibar',
                             { 'image-view-selected': image.selected },
                             { 'image-view-selected': image.selected },
-                            { 'image-view-disabled': image.sample }
+                            { 'image-view-disabled': image.sample },
                           ]"
                           ]"
                           :title="image.sample ? '标准卷' : '选中批量分档'"
                           :title="image.sample ? '标准卷' : '选中批量分档'"
                           @click="selectMultiplePaper(image)"
                           @click="selectMultiplePaper(image)"
@@ -101,7 +101,7 @@
             <div
             <div
               :class="[
               :class="[
                 'detail-action',
                 'detail-action',
-                { 'detail-action-fullscreen': isFullscreenMarking }
+                { 'detail-action-fullscreen': isFullscreenMarking },
               ]"
               ]"
               v-show="!multipleGradingList.length"
               v-show="!multipleGradingList.length"
             >
             >
@@ -133,7 +133,7 @@
                     <div
                     <div
                       :class="[
                       :class="[
                         'action-grade-item-content',
                         'action-grade-item-content',
-                        { 'action-item-content-disabled': multiplebtnClicked }
+                        { 'action-item-content-disabled': multiplebtnClicked },
                       ]"
                       ]"
                       @click="multipleSelectLevel(level)"
                       @click="multipleSelectLevel(level)"
                     >
                     >
@@ -180,7 +180,7 @@ import {
   workLevelList,
   workLevelList,
   paperSelectLevelOrScore,
   paperSelectLevelOrScore,
   paperSelectLevelBatch,
   paperSelectLevelBatch,
-  paperTaskPass
+  paperTaskPass,
 } from "@/api";
 } from "@/api";
 import SimpleImagePreview from "@/components/SimpleImagePreview";
 import SimpleImagePreview from "@/components/SimpleImagePreview";
 import GradeFilter from "./components/GradeFilter";
 import GradeFilter from "./components/GradeFilter";
@@ -204,7 +204,7 @@ export default {
     GradeStep,
     GradeStep,
     GradeHistoryPaper,
     GradeHistoryPaper,
     GradeStandardPaper,
     GradeStandardPaper,
-    GradeAction
+    GradeAction,
   },
   },
   data() {
   data() {
     return {
     return {
@@ -212,16 +212,16 @@ export default {
         markerId: this.$ls.get("user").id,
         markerId: this.$ls.get("user").id,
         questionId: "",
         questionId: "",
         sort: "randomSeq,asc",
         sort: "randomSeq,asc",
-        stage: "LEVEL"
+        stage: "LEVEL",
       },
       },
       typeFilter: {
       typeFilter: {
         done: {
         done: {
-          level: ""
+          level: "",
         },
         },
         undo: {},
         undo: {},
         reject: {
         reject: {
-          reject: true
-        }
+          reject: true,
+        },
       },
       },
       workId: this.$route.params.workId,
       workId: this.$route.params.workId,
       subjectId: this.$route.params.subjectId,
       subjectId: this.$route.params.subjectId,
@@ -250,7 +250,7 @@ export default {
       carouselType: "",
       carouselType: "",
       carouselPapers: [],
       carouselPapers: [],
       curCarouselPaperIndex: 0,
       curCarouselPaperIndex: 0,
-      isFullscreenMarking: false
+      isFullscreenMarking: false,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -259,13 +259,13 @@ export default {
     },
     },
     imageViewClasses() {
     imageViewClasses() {
       return ["image-view-list", `image-view-list-${this.size / 2}`];
       return ["image-view-list", `image-view-list-${this.size / 2}`];
-    }
+    },
   },
   },
   created() {
   created() {
     this.subject = this.subjectId.split("-")[1];
     this.subject = this.subjectId.split("-")[1];
     this.workSubject = {
     this.workSubject = {
       workId: this.workId,
       workId: this.workId,
-      subject: this.subject
+      subject: this.subject,
     };
     };
     this.initData();
     this.initData();
   },
   },
@@ -290,7 +290,7 @@ export default {
         ...this.typeFilter[this.curStep.type],
         ...this.typeFilter[this.curStep.type],
         workId: this.workId,
         workId: this.workId,
         page: this.current - 1,
         page: this.current - 1,
-        size: this.size
+        size: this.size,
       };
       };
       if (this.curStep.type === "done") {
       if (this.curStep.type === "done") {
         datas.level = this.curStep.name;
         datas.level = this.curStep.name;
@@ -298,7 +298,7 @@ export default {
       }
       }
 
 
       const data = await markerTaskList(datas);
       const data = await markerTaskList(datas);
-      this.papers = data.data.map(paper => {
+      this.papers = data.data.map((paper) => {
         paper.title = `NO.${paper.sn}`;
         paper.title = `NO.${paper.sn}`;
         paper.selected = false;
         paper.selected = false;
         return paper;
         return paper;
@@ -316,11 +316,11 @@ export default {
         this.filter.markerId,
         this.filter.markerId,
         this.filter.questionId
         this.filter.questionId
       );
       );
-      const undoIndex = data.findIndex(item => item.id === null);
+      const undoIndex = data.findIndex((item) => item.id === null);
       let otherStep = [];
       let otherStep = [];
       let undo = {
       let undo = {
         count: 0,
         count: 0,
-        rejected: 0
+        rejected: 0,
       };
       };
       if (undoIndex !== -1) {
       if (undoIndex !== -1) {
         undo = { ...data[undoIndex] };
         undo = { ...data[undoIndex] };
@@ -330,20 +330,20 @@ export default {
       otherStep.push({
       otherStep.push({
         name: "待评",
         name: "待评",
         count: undo.count,
         count: undo.count,
-        type: "undo"
+        type: "undo",
       });
       });
       otherStep.push({
       otherStep.push({
         name: "打回",
         name: "打回",
         count: undo.rejected,
         count: undo.rejected,
-        type: "reject"
+        type: "reject",
       });
       });
-      let levelStep = data.map(item => {
+      let levelStep = data.map((item) => {
         // 评卷员不展示kdpt
         // 评卷员不展示kdpt
         item.kdpt = null;
         item.kdpt = null;
         return {
         return {
           ...item,
           ...item,
           name: item.id,
           name: item.id,
-          type: "done"
+          type: "done",
         };
         };
       });
       });
       this.steps = { levelStep, otherStep };
       this.steps = { levelStep, otherStep };
@@ -361,22 +361,22 @@ export default {
     updateStepLevel(curStep, curLevel, count) {
     updateStepLevel(curStep, curLevel, count) {
       if (curStep.type === "done") {
       if (curStep.type === "done") {
         const lpos = this.steps.levelStep.findIndex(
         const lpos = this.steps.levelStep.findIndex(
-          item => item.name === curStep.name
+          (item) => item.name === curStep.name
         );
         );
         this.steps.levelStep[lpos].count -= count;
         this.steps.levelStep[lpos].count -= count;
       } else {
       } else {
         const opos = this.steps.otherStep.findIndex(
         const opos = this.steps.otherStep.findIndex(
-          item => item.type === curStep.type
+          (item) => item.type === curStep.type
         );
         );
         this.steps.otherStep[opos].count -= count;
         this.steps.otherStep[opos].count -= count;
       }
       }
 
 
       const pos = this.steps.levelStep.findIndex(
       const pos = this.steps.levelStep.findIndex(
-        item => item.name === curLevel
+        (item) => item.name === curLevel
       );
       );
       this.steps.levelStep[pos].count += count;
       this.steps.levelStep[pos].count += count;
 
 
-      this.steps.levelStep.forEach(item => {
+      this.steps.levelStep.forEach((item) => {
         item.percent =
         item.percent =
           item.finalKdTotal && item.count
           item.finalKdTotal && item.count
             ? ((100 * item.count) / item.finalKdTotal).toFixed(3)
             ? ((100 * item.count) / item.finalKdTotal).toFixed(3)
@@ -415,7 +415,7 @@ export default {
     selectMultiplePaper(paper) {
     selectMultiplePaper(paper) {
       if (paper.sample) return;
       if (paper.sample) return;
       paper.selected = !paper.selected;
       paper.selected = !paper.selected;
-      this.multipleGradingList = this.papers.filter(paper => paper.selected);
+      this.multipleGradingList = this.papers.filter((paper) => paper.selected);
     },
     },
     async multipleSelectLevel(level) {
     async multipleSelectLevel(level) {
       if (!this.multipleGradingList.length) return;
       if (!this.multipleGradingList.length) return;
@@ -425,7 +425,7 @@ export default {
 
 
       let result = true;
       let result = true;
       const papers = await paperSelectLevelBatch(
       const papers = await paperSelectLevelBatch(
-        this.multipleGradingList.map(item => item.id).join(), // is taskId
+        this.multipleGradingList.map((item) => item.id).join(), // is taskId
         level.name,
         level.name,
         this.curSubject.stage
         this.curSubject.stage
       ).catch(() => {
       ).catch(() => {
@@ -580,7 +580,7 @@ export default {
     standardPaperChange(curPaper) {
     standardPaperChange(curPaper) {
       if (!this.isFullscreenMarking) return;
       if (!this.isFullscreenMarking) return;
       this.curPaper = { ...curPaper };
       this.curPaper = { ...curPaper };
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 343 - 343
src/modules/grading/GradingProgress.vue

@@ -1,343 +1,343 @@
-<template>
-  <div class="grading-progress">
-    <div class="part-box-head" v-if="IS_ADMIN">
-      <div class="part-box-head-left">
-        <template v-if="IS_LEVEL">
-          <Button shape="circle" icon="md-download" @click="toExportStandard"
-            >导出标准卷信息</Button
-          >
-          <Button shape="circle" icon="md-download" @click="toExportGrading"
-            >导出一键定档信息</Button
-          >
-        </template>
-        <template v-if="IS_SCORE">
-          <Button shape="circle" icon="md-download" @click="toExportChangeLevel"
-            >导出改档信息</Button
-          >
-        </template>
-      </div>
-      <div class="part-box-head-right">
-        <Button
-          type="error"
-          shape="circle"
-          icon="area icon"
-          @click="toCleanData"
-          v-if="showClearDataBtn"
-          >清除当前阅卷数据</Button
-        >
-        <Button
-          type="success"
-          shape="circle"
-          icon="recode-white icon"
-          @click="toGrading"
-          v-if="showGradingBtn"
-          >正评任务创建</Button
-        >
-        <Button
-          type="warning"
-          shape="circle"
-          icon="recode-white icon"
-          @click="toTryGrading"
-          v-if="showTryGradingBtn"
-          >试评任务创建</Button
-        >
-        <Button v-if="!IS_SCORE" shape="circle" @click="toNextStage"
-          >进入下一阶段
-          <Icon type="arrow-right-long icon" style="margin-left:8px;" />
-        </Button>
-      </div>
-    </div>
-    <Row :gutter="20" type="flex">
-      <Col span="12">
-        <div class="part-box progress-table">
-          <table class="table table-noborder">
-            <tr v-for="(item, aindex) in areaProgress" :key="aindex">
-              <td>{{ item.areaName }}</td>
-              <td>
-                <progress-line
-                  :sum="item.totalCount"
-                  :current="item.successCount"
-                ></progress-line>
-              </td>
-              <td>进度:{{ item.progress }}%</td>
-              <td></td>
-            </tr>
-          </table>
-        </div>
-      </Col>
-      <Col span="12">
-        <div class="part-box progress-table">
-          <table class="table table-noborder kzz-table" v-if="kzzInfo.length">
-            <tr v-for="kzz in kzzInfo" :key="kzz.loginName">
-              <td>{{ kzz.loginName }}</td>
-              <td v-if="IS_LEVEL" style="text-align:left">
-                仲裁:{{ kzz.arbitrated }}
-              </td>
-              <td v-else></td>
-            </tr>
-          </table>
-
-          <div v-for="(group, index) in groupMarkers" :key="index">
-            <table v-if="IS_LEVEL" class="table table-noborder kzz-table">
-              <tr v-for="kzz in group.kzzProgress" :key="kzz.loginName">
-                <td>{{ kzz.loginName }}</td>
-                <td colspan="3" style="text-align:left">
-                  仲裁:{{ kzz.arbitrated }}
-                </td>
-              </tr>
-              <tr v-for="(item, aindex) in group.markerProgress" :key="aindex">
-                <td>{{ item.loginName }}</td>
-                <td>
-                  <progress-line
-                    :sum="item.totalCount"
-                    :current="item.successCount"
-                  ></progress-line>
-                </td>
-                <td>进度:{{ item.progress }}%</td>
-                <td>打回:{{ item.rejectedCount }}</td>
-                <td v-if="IS_ROUGH_THIN_LEVEL">
-                  改大档:{{ item.shiftCount }}
-                </td>
-                <td v-if="IS_ROUGH_THIN_LEVEL">
-                  改大档打小档:{{ item.shiftScoreCount }}
-                </td>
-              </tr>
-            </table>
-
-            <table v-if="IS_SCORE" class="table table-noborder kzz-table">
-              <tr v-for="kzz in group.kzzProgress" :key="kzz.loginName">
-                <td>{{ kzz.loginName }}</td>
-                <td colspan="3"></td>
-              </tr>
-              <tr v-for="(item, aindex) in group.markerProgress" :key="aindex">
-                <td>{{ item.loginName }}</td>
-                <td>
-                  <progress-line
-                    :sum="item.totalCount"
-                    :current="item.successCount"
-                  ></progress-line>
-                </td>
-                <td>进度:{{ item.progress }}%</td>
-                <td>改档:{{ item.shiftCount }}</td>
-                <td>改档打分:{{ item.shiftScoreCount }}</td>
-              </tr>
-            </table>
-          </div>
-        </div>
-      </Col>
-    </Row>
-
-    <!-- clean-grading-data-dialog -->
-    <clean-grading-data-dialog
-      :cur-subject="curSubject"
-      @modified="initData"
-      ref="CleanGradingDataDialog"
-    ></clean-grading-data-dialog>
-    <!-- modify-unformal-grading-task -->
-    <modify-unformal-grading-task
-      :cur-subject="curSubject"
-      @modified="taskSubmitSuccess"
-      ref="ModifyUnformalGradingTask"
-      v-if="curSubject.id"
-    ></modify-unformal-grading-task>
-    <!-- modify-formal-grading-task -->
-    <modify-formal-grading-task
-      :subject-id="subjectId"
-      @modified="taskSubmitSuccess"
-      ref="ModifyFormalGradingTask"
-    ></modify-formal-grading-task>
-  </div>
-</template>
-
-<script>
-import ProgressLine from "./components/ProgressLine";
-import ModifyUnformalGradingTask from "./components/ModifyUnformalGradingTask";
-import ModifyFormalGradingTask from "./components/ModifyFormalGradingTask";
-import CleanGradingDataDialog from "./components/CleanGradingDataDialog";
-import {
-  gradingProgressDetail,
-  subjectDetail,
-  gotoNextStage,
-  getParamsSet
-} from "@/api";
-
-export default {
-  name: "grading-progress",
-  components: {
-    ProgressLine,
-    ModifyUnformalGradingTask,
-    ModifyFormalGradingTask,
-    CleanGradingDataDialog
-  },
-  data() {
-    return {
-      subjectId: this.$route.params.subjectId,
-      workId: this.$route.params.workId,
-      paramsSet: { levelConfig: {}, collectConfig: {} },
-      curSubject: {},
-      kzzInfo: [],
-      totalProgress: {},
-      areaProgress: [],
-      groupMarkers: [],
-      curUserRoleType: ""
-    };
-  },
-  computed: {
-    showClearDataBtn() {
-      return (
-        this.paramsSet.levelConfig.clearData && (this.IS_LEVEL || this.IS_SCORE)
-      );
-    },
-    showGradingBtn() {
-      // 采集时已知档位,则不显示正评任务按钮
-      if (this.paramsSet.collectConfig.paperStage) return false;
-
-      return (
-        this.IS_LEVEL &&
-        this.curSubject.test !== 2 &&
-        this.totalProgress.progress !== 100
-      );
-    },
-    showTryGradingBtn() {
-      // 采集时已知档位,则不显示试评任务按钮
-      if (this.paramsSet.collectConfig.paperStage) return false;
-
-      return this.IS_LEVEL && !this.curSubject.formal;
-    },
-    IS_ADMIN() {
-      return this.curUserRoleType === "ADMIN";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    },
-    IS_LEVEL() {
-      return (
-        this.curSubject.stage === "LEVEL" ||
-        this.curSubject.stage === "ROUGH_LEVEL"
-      );
-    },
-    IS_SCORE() {
-      return this.curSubject.stage === "SCORE";
-    },
-    IS_ROUGH_THIN_LEVEL() {
-      return (
-        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
-      );
-    }
-  },
-  mounted() {
-    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.initData();
-  },
-  methods: {
-    async initData() {
-      await this.getSubjectDetail();
-      this.getParamsSetInfo();
-      this.getProgressDetail();
-    },
-    async getParamsSetInfo() {
-      this.paramsSet = await getParamsSet(this.workId);
-      if (
-        this.curSubject.roughLevelEnable &&
-        this.curSubject.stage === "ROUGH_LEVEL"
-      ) {
-        this.paramsSet.levelConfig = this.paramsSet.roughLevelConfig;
-      }
-    },
-    async getProgressDetail() {
-      const data = await gradingProgressDetail({
-        workId: this.curSubject.workId,
-        subject: this.curSubject.subject
-      });
-      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.groupMarkers = [];
-      } else {
-        this.areaProgress = [totalInfo, ...this.addProgress(data.areaProgress)];
-        this.groupMarkers = data.groupMarkers.map(group => {
-          group.markerProgress = this.addProgress(group.markerProgress);
-          return group;
-        });
-      }
-      this.$parent.setProgress &&
-        this.$parent.setProgress(data.totalProgress.progress);
-    },
-    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;
-      });
-    },
-    async getSubjectDetail() {
-      this.curSubject = await subjectDetail(this.subjectId);
-    },
-    toCleanData() {
-      this.$refs.CleanGradingDataDialog.open();
-    },
-    toGrading() {
-      this.$refs.ModifyFormalGradingTask.open();
-    },
-    toTryGrading() {
-      this.$refs.ModifyUnformalGradingTask.open();
-    },
-    toNextStage() {
-      this.$Modal.confirm({
-        content: "确定要进入下一阶段吗?",
-        onOk: async () => {
-          await gotoNextStage({
-            workId: this.curSubject.workId,
-            subject: this.curSubject.subject
-          });
-          if (this.IS_SCORE) {
-            this.$router.replace({
-              name: "Mark",
-              params: {
-                workId: this.workId,
-                subjectId: this.subjectId
-              }
-            });
-          } else {
-            window.location.reload();
-          }
-        }
-      });
-    },
-    taskSubmitSuccess() {
-      this.$parent.initData();
-      this.initData();
-    },
-    toExportStandard() {
-      window.open(
-        this.urlAddAuthor(
-          `${this.GLOBAL.domain}/api/export/paper/${this.curSubject.workId}/${this.curSubject.subject}/sample`
-        )
-      );
-    },
-    toExportGrading() {
-      window.open(
-        this.urlAddAuthor(
-          `${this.GLOBAL.domain}/api/export/paper/${this.curSubject.workId}/${this.curSubject.subject}/oneClick`
-        )
-      );
-    },
-    toExportChangeLevel() {
-      window.open(
-        this.urlAddAuthor(
-          `${this.GLOBAL.domain}/api/export/paper/${this.curSubject.workId}/${this.curSubject.subject}/changeLevel`
-        )
-      );
-    }
-  }
-};
-</script>
+<template>
+  <div class="grading-progress">
+    <div class="part-box-head" v-if="IS_ADMIN">
+      <div class="part-box-head-left">
+        <template v-if="IS_LEVEL">
+          <Button shape="circle" icon="md-download" @click="toExportStandard"
+            >导出标准卷信息</Button
+          >
+          <Button shape="circle" icon="md-download" @click="toExportGrading"
+            >导出一键定档信息</Button
+          >
+        </template>
+        <template v-if="IS_SCORE">
+          <Button shape="circle" icon="md-download" @click="toExportChangeLevel"
+            >导出改档信息</Button
+          >
+        </template>
+      </div>
+      <div class="part-box-head-right">
+        <Button
+          type="error"
+          shape="circle"
+          icon="area icon"
+          @click="toCleanData"
+          v-if="showClearDataBtn"
+          >清除当前阅卷数据</Button
+        >
+        <Button
+          type="success"
+          shape="circle"
+          icon="recode-white icon"
+          @click="toGrading"
+          v-if="showGradingBtn"
+          >正评任务创建</Button
+        >
+        <Button
+          type="warning"
+          shape="circle"
+          icon="recode-white icon"
+          @click="toTryGrading"
+          v-if="showTryGradingBtn"
+          >试评任务创建</Button
+        >
+        <Button v-if="!IS_SCORE" shape="circle" @click="toNextStage"
+          >进入下一阶段
+          <Icon type="arrow-right-long icon" style="margin-left: 8px" />
+        </Button>
+      </div>
+    </div>
+    <Row :gutter="20" type="flex">
+      <Col span="12">
+        <div class="part-box progress-table">
+          <table class="table table-noborder">
+            <tr v-for="(item, aindex) in areaProgress" :key="aindex">
+              <td>{{ item.areaName }}</td>
+              <td>
+                <progress-line
+                  :sum="item.totalCount"
+                  :current="item.successCount"
+                ></progress-line>
+              </td>
+              <td>进度:{{ item.progress }}%</td>
+              <td></td>
+            </tr>
+          </table>
+        </div>
+      </Col>
+      <Col span="12">
+        <div class="part-box progress-table">
+          <table class="table table-noborder kzz-table" v-if="kzzInfo.length">
+            <tr v-for="kzz in kzzInfo" :key="kzz.loginName">
+              <td>{{ kzz.loginName }}</td>
+              <td v-if="IS_LEVEL" style="text-align: left">
+                仲裁:{{ kzz.arbitrated }}
+              </td>
+              <td v-else></td>
+            </tr>
+          </table>
+
+          <div v-for="(group, index) in groupMarkers" :key="index">
+            <table v-if="IS_LEVEL" class="table table-noborder kzz-table">
+              <tr v-for="kzz in group.kzzProgress" :key="kzz.loginName">
+                <td>{{ kzz.loginName }}</td>
+                <td colspan="3" style="text-align: left">
+                  仲裁:{{ kzz.arbitrated }}
+                </td>
+              </tr>
+              <tr v-for="(item, aindex) in group.markerProgress" :key="aindex">
+                <td>{{ item.loginName }}</td>
+                <td>
+                  <progress-line
+                    :sum="item.totalCount"
+                    :current="item.successCount"
+                  ></progress-line>
+                </td>
+                <td>进度:{{ item.progress }}%</td>
+                <td>打回:{{ item.rejectedCount }}</td>
+                <td v-if="IS_ROUGH_THIN_LEVEL">
+                  改大档:{{ item.shiftCount }}
+                </td>
+                <td v-if="IS_ROUGH_THIN_LEVEL">
+                  改大档打小档:{{ item.shiftScoreCount }}
+                </td>
+              </tr>
+            </table>
+
+            <table v-if="IS_SCORE" class="table table-noborder kzz-table">
+              <tr v-for="kzz in group.kzzProgress" :key="kzz.loginName">
+                <td>{{ kzz.loginName }}</td>
+                <td colspan="3"></td>
+              </tr>
+              <tr v-for="(item, aindex) in group.markerProgress" :key="aindex">
+                <td>{{ item.loginName }}</td>
+                <td>
+                  <progress-line
+                    :sum="item.totalCount"
+                    :current="item.successCount"
+                  ></progress-line>
+                </td>
+                <td>进度:{{ item.progress }}%</td>
+                <td>改档:{{ item.shiftCount }}</td>
+                <td>改档打分:{{ item.shiftScoreCount }}</td>
+              </tr>
+            </table>
+          </div>
+        </div>
+      </Col>
+    </Row>
+
+    <!-- clean-grading-data-dialog -->
+    <clean-grading-data-dialog
+      :cur-subject="curSubject"
+      @modified="initData"
+      ref="CleanGradingDataDialog"
+    ></clean-grading-data-dialog>
+    <!-- modify-unformal-grading-task -->
+    <modify-unformal-grading-task
+      :cur-subject="curSubject"
+      @modified="taskSubmitSuccess"
+      ref="ModifyUnformalGradingTask"
+      v-if="curSubject.id"
+    ></modify-unformal-grading-task>
+    <!-- modify-formal-grading-task -->
+    <modify-formal-grading-task
+      :subject-id="subjectId"
+      @modified="taskSubmitSuccess"
+      ref="ModifyFormalGradingTask"
+    ></modify-formal-grading-task>
+  </div>
+</template>
+
+<script>
+import ProgressLine from "./components/ProgressLine";
+import ModifyUnformalGradingTask from "./components/ModifyUnformalGradingTask";
+import ModifyFormalGradingTask from "./components/ModifyFormalGradingTask";
+import CleanGradingDataDialog from "./components/CleanGradingDataDialog";
+import {
+  gradingProgressDetail,
+  subjectDetail,
+  gotoNextStage,
+  getParamsSet,
+} from "@/api";
+
+export default {
+  name: "grading-progress",
+  components: {
+    ProgressLine,
+    ModifyUnformalGradingTask,
+    ModifyFormalGradingTask,
+    CleanGradingDataDialog,
+  },
+  data() {
+    return {
+      subjectId: this.$route.params.subjectId,
+      workId: this.$route.params.workId,
+      paramsSet: { levelConfig: {}, collectConfig: {} },
+      curSubject: {},
+      kzzInfo: [],
+      totalProgress: {},
+      areaProgress: [],
+      groupMarkers: [],
+      curUserRoleType: "",
+    };
+  },
+  computed: {
+    showClearDataBtn() {
+      return (
+        this.paramsSet.levelConfig.clearData && (this.IS_LEVEL || this.IS_SCORE)
+      );
+    },
+    showGradingBtn() {
+      // 采集时已知档位,则不显示正评任务按钮
+      if (this.paramsSet.collectConfig.paperStage) return false;
+
+      return (
+        this.IS_LEVEL &&
+        this.curSubject.test !== 2 &&
+        this.totalProgress.progress !== 100
+      );
+    },
+    showTryGradingBtn() {
+      // 采集时已知档位,则不显示试评任务按钮
+      if (this.paramsSet.collectConfig.paperStage) return false;
+
+      return this.IS_LEVEL && !this.curSubject.formal;
+    },
+    IS_ADMIN() {
+      return this.curUserRoleType === "ADMIN";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    },
+    IS_LEVEL() {
+      return (
+        this.curSubject.stage === "LEVEL" ||
+        this.curSubject.stage === "ROUGH_LEVEL"
+      );
+    },
+    IS_SCORE() {
+      return this.curSubject.stage === "SCORE";
+    },
+    IS_ROUGH_THIN_LEVEL() {
+      return (
+        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
+      );
+    },
+  },
+  mounted() {
+    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      await this.getSubjectDetail();
+      this.getParamsSetInfo();
+      this.getProgressDetail();
+    },
+    async getParamsSetInfo() {
+      this.paramsSet = await getParamsSet(this.workId);
+      if (
+        this.curSubject.roughLevelEnable &&
+        this.curSubject.stage === "ROUGH_LEVEL"
+      ) {
+        this.paramsSet.levelConfig = this.paramsSet.roughLevelConfig;
+      }
+    },
+    async getProgressDetail() {
+      const data = await gradingProgressDetail({
+        workId: this.curSubject.workId,
+        subject: this.curSubject.subject,
+      });
+      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.groupMarkers = [];
+      } else {
+        this.areaProgress = [totalInfo, ...this.addProgress(data.areaProgress)];
+        this.groupMarkers = data.groupMarkers.map((group) => {
+          group.markerProgress = this.addProgress(group.markerProgress);
+          return group;
+        });
+      }
+      this.$parent.setProgress &&
+        this.$parent.setProgress(data.totalProgress.progress);
+    },
+    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;
+      });
+    },
+    async getSubjectDetail() {
+      this.curSubject = await subjectDetail(this.subjectId);
+    },
+    toCleanData() {
+      this.$refs.CleanGradingDataDialog.open();
+    },
+    toGrading() {
+      this.$refs.ModifyFormalGradingTask.open();
+    },
+    toTryGrading() {
+      this.$refs.ModifyUnformalGradingTask.open();
+    },
+    toNextStage() {
+      this.$Modal.confirm({
+        content: "确定要进入下一阶段吗?",
+        onOk: async () => {
+          await gotoNextStage({
+            workId: this.curSubject.workId,
+            subject: this.curSubject.subject,
+          });
+          if (this.IS_SCORE) {
+            this.$router.replace({
+              name: "Mark",
+              params: {
+                workId: this.workId,
+                subjectId: this.subjectId,
+              },
+            });
+          } else {
+            window.location.reload();
+          }
+        },
+      });
+    },
+    taskSubmitSuccess() {
+      this.$parent.initData();
+      this.initData();
+    },
+    toExportStandard() {
+      window.open(
+        this.urlAddAuthor(
+          `${this.GLOBAL.domain}/api/export/paper/${this.curSubject.workId}/${this.curSubject.subject}/sample`
+        )
+      );
+    },
+    toExportGrading() {
+      window.open(
+        this.urlAddAuthor(
+          `${this.GLOBAL.domain}/api/export/paper/${this.curSubject.workId}/${this.curSubject.subject}/oneClick`
+        )
+      );
+    },
+    toExportChangeLevel() {
+      window.open(
+        this.urlAddAuthor(
+          `${this.GLOBAL.domain}/api/export/paper/${this.curSubject.workId}/${this.curSubject.subject}/changeLevel`
+        )
+      );
+    },
+  },
+};
+</script>

+ 364 - 362
src/modules/grading/GradingStandardPaperManage.vue

@@ -1,362 +1,364 @@
-<template>
-  <div class="grading-standard-paper-manage">
-    <div class="part-box-head">
-      <Form
-        class="part-box-head-left"
-        ref="FilterForm"
-        label-position="left"
-        inline
-      >
-        <FormItem>
-          <Select v-model="questionId" placeholder="选择考区">
-            <Option
-              v-for="area in areas"
-              :key="area.id"
-              :value="area.id"
-              :label="area.areaName"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Button
-            size="small"
-            class="btn-form-search"
-            type="primary"
-            @click="search"
-            >查询</Button
-          >
-        </FormItem>
-      </Form>
-      <div class="part-box-head-right">
-        <div class="level-list">
-          <p
-            v-for="(level, index) in levels"
-            :key="level"
-            :class="['level-item', { 'level-item-act': curLevel === level }]"
-            @click="switchLevel(index)"
-          >
-            {{ level }}
-          </p>
-          <p
-            :class="['level-item', { 'level-item-act': !curLevel }]"
-            @click="showAllLevel"
-          >
-            全部
-          </p>
-        </div>
-      </div>
-    </div>
-
-    <div class="standard-papers-list" v-if="papers.length">
-      <div class="image-view-list image-view-list-5">
-        <div
-          :class="['image-view']"
-          v-for="(image, index) in papers"
-          :key="index"
-        >
-          <div class="image-view-container">
-            <h5 class="image-view-title">
-              {{ image.title }}
-            </h5>
-            <div class="image-view-contain">
-              <img
-                :src="image.thumbSrc"
-                :alt="image.title"
-                @click="toReview(index)"
-              />
-            </div>
-            <div class="image-view-actions">
-              <Button disabled>{{ image.level }}</Button>
-              <Button
-                type="error"
-                size="small"
-                @click="cancelPaper(image)"
-                :disabled="image.loading"
-                v-if="canCancel"
-                >取消</Button
-              >
-              <Button type="primary" size="small" @click="toChangePaper(image)"
-                >修改</Button
-              >
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-    <div class="standard-papers-list" v-else>
-      <p class="standard-papers-none">暂无数据</p>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-    <!-- change-standard-paper-dialog -->
-    <Modal
-      class="change-standard-paper-dialog"
-      v-model="modalIsShow"
-      title="修改标准卷"
-      :mask-closable="false"
-    >
-      <div class="level-list">
-        <p
-          v-for="level in levels"
-          :key="level"
-          :class="[
-            'level-item',
-            {
-              'level-item-act': level === curSelectLevel,
-              'level-item-disabled': level === curChangePaper.level
-            }
-          ]"
-          @click="selectLevel(level)"
-        >
-          {{ level }}
-        </p>
-      </div>
-
-      <div slot="footer">
-        <Button
-          shape="circle"
-          type="primary"
-          :disabled="isSubmit || !curSelectLevel"
-          @click="confirmChange"
-          >确认</Button
-        >
-        <Button shape="circle" @click="cancelChange">取消</Button>
-      </div>
-    </Modal>
-  </div>
-</template>
-
-<script>
-import {
-  paperList,
-  sampleAreaList,
-  workLevelList,
-  cancelStandardPaper,
-  leaderGradingPaper,
-  subjectDetail
-} from "@/api";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-
-export default {
-  name: "grading-standard-paper-manage",
-  components: { SimpleImagePreview },
-  data() {
-    return {
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      canCancel: true,
-      questionId: "",
-      lastQuestionId: "",
-      curLevel: "",
-      curLevelIndex: -1,
-      levels: [],
-      areas: [],
-      paperList: [],
-      papers: [],
-      curPaper: {},
-      curSubject: {},
-      curPaperIndex: 0,
-      // change standard
-      modalIsShow: false,
-      curChangePaper: {},
-      curSelectLevel: null,
-      isSubmit: false
-    };
-  },
-  mounted() {
-    this.subject = this.subjectId.split("-")[1];
-    this.initData();
-  },
-  methods: {
-    async initData() {
-      await this.getAreaList();
-      this.questionId = this.areas[0] && this.areas[0].id;
-      if (!this.questionId) return;
-      await this.getSubjectDetail();
-      await this.getWorkLevels();
-      this.search();
-    },
-    async getWorkLevels() {
-      const data = await workLevelList(this.workId, this.curSubject.stage);
-      this.levels = data.map(item => item.name);
-    },
-    async getAreaList() {
-      const data = await sampleAreaList({
-        workId: this.workId,
-        subject: this.subject
-      });
-      this.areas = data.map(item => {
-        return {
-          id: item.id,
-          areaName: `${item.areaName}-${item.name}`,
-          areaCode: item.areaCode
-        };
-      });
-    },
-    async getSubjectDetail() {
-      const curSubject = await subjectDetail(this.subjectId);
-      this.curSubject = curSubject || {};
-    },
-    async search() {
-      this.lastQuestionId = this.questionId;
-      await this.getPaperList();
-      this.updatePapers();
-    },
-    updatePapers() {
-      if (this.curLevel) {
-        this.papers = this.paperList.filter(
-          paper => paper.level === this.curLevel
-        );
-      } else {
-        this.papers = this.paperList;
-      }
-    },
-    async getPaperList() {
-      const datas = {
-        questionId: this.questionId,
-        level: "",
-        sort: "secretNumber",
-        isSample: true,
-        page: 0,
-        size: 100
-      };
-      const data = await paperList(datas);
-      this.paperList = data.data.map(item => {
-        item.title = `NO.${item.sn}`;
-        item.loading = false;
-        return item;
-      });
-      this.paperList.sort((a, b) => (a.level < b.level ? -1 : 1));
-    },
-    switchLevel(index) {
-      this.curLevelIndex = index;
-      this.curLevel = this.levels[index];
-
-      this.updatePapers();
-    },
-    showAllLevel() {
-      this.curLevelIndex = -1;
-      this.curLevel = "";
-      this.updatePapers();
-    },
-    cancelPaper(paper) {
-      if (paper.loading) return;
-      this.$Modal.confirm({
-        content: "确定要取消当前标准卷吗?",
-        onOk: async () => {
-          paper.loading = true;
-          const res = await cancelStandardPaper(paper.id).catch(() => {});
-          paper.loading = false;
-          if (!res) return;
-
-          this.paperList = this.paperList.filter(
-            item => paper.level !== item.level
-          );
-          this.papers = this.papers.filter(item => paper.level !== item.level);
-        }
-      });
-    },
-    // change standard paper
-    toChangePaper(paper) {
-      this.curChangePaper = paper;
-      this.modalIsShow = true;
-    },
-    selectLevel(level) {
-      if (level === this.curChangePaper.level) return;
-      this.curSelectLevel = level;
-    },
-    async confirmChange() {
-      if (!this.curSelectLevel) return;
-      if (this.isSubmit) return;
-
-      this.isSubmit = true;
-      const datas = {
-        action: "sampling",
-        level: this.curSelectLevel,
-        originLevel: this.curChangePaper.level,
-        paperIds: this.curChangePaper.id,
-        stage: this.curSubject.stage
-      };
-      let result = true;
-      await leaderGradingPaper(datas).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-
-      if (!result) return;
-
-      this.$Message.success("操作成功!");
-      this.cancelChange();
-      this.search();
-    },
-    cancelChange() {
-      this.curSelectLevel = null;
-      this.modalIsShow = false;
-    },
-    // to review
-    toReview(index) {
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.curLevelIndex === 0 || this.curLevelIndex === -1) {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        } else {
-          this.curLevelIndex--;
-          this.curLevel = this.levels[this.curLevelIndex];
-          await this.updatePapers();
-          this.curPaperIndex = this.papers.length - 1;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (
-        this.curPaperIndex === this.papers.length - 1 ||
-        !this.papers.length
-      ) {
-        if (
-          this.curLevelIndex === this.levels.length - 1 ||
-          this.curLevelIndex === -1
-        ) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.curLevelIndex++;
-          this.curLevel = this.levels[this.curLevelIndex];
-          await this.updatePapers();
-          this.curPaperIndex = 0;
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="grading-standard-paper-manage">
+    <div class="part-box-head">
+      <Form
+        class="part-box-head-left"
+        ref="FilterForm"
+        label-position="left"
+        inline
+      >
+        <FormItem>
+          <Select v-model="questionId" placeholder="选择考区">
+            <Option
+              v-for="area in areas"
+              :key="area.id"
+              :value="area.id"
+              :label="area.areaName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Button
+            size="small"
+            class="btn-form-search"
+            type="primary"
+            @click="search"
+            >查询</Button
+          >
+        </FormItem>
+      </Form>
+      <div class="part-box-head-right">
+        <div class="level-list">
+          <p
+            v-for="(level, index) in levels"
+            :key="level"
+            :class="['level-item', { 'level-item-act': curLevel === level }]"
+            @click="switchLevel(index)"
+          >
+            {{ level }}
+          </p>
+          <p
+            :class="['level-item', { 'level-item-act': !curLevel }]"
+            @click="showAllLevel"
+          >
+            全部
+          </p>
+        </div>
+      </div>
+    </div>
+
+    <div class="standard-papers-list" v-if="papers.length">
+      <div class="image-view-list image-view-list-5">
+        <div
+          :class="['image-view']"
+          v-for="(image, index) in papers"
+          :key="index"
+        >
+          <div class="image-view-container">
+            <h5 class="image-view-title">
+              {{ image.title }}
+            </h5>
+            <div class="image-view-contain">
+              <img
+                :src="image.thumbSrc"
+                :alt="image.title"
+                @click="toReview(index)"
+              />
+            </div>
+            <div class="image-view-actions">
+              <Button disabled>{{ image.level }}</Button>
+              <Button
+                type="error"
+                size="small"
+                @click="cancelPaper(image)"
+                :disabled="image.loading"
+                v-if="canCancel"
+                >取消</Button
+              >
+              <Button type="primary" size="small" @click="toChangePaper(image)"
+                >修改</Button
+              >
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="standard-papers-list" v-else>
+      <p class="standard-papers-none">暂无数据</p>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+    <!-- change-standard-paper-dialog -->
+    <Modal
+      class="change-standard-paper-dialog"
+      v-model="modalIsShow"
+      title="修改标准卷"
+      :mask-closable="false"
+    >
+      <div class="level-list">
+        <p
+          v-for="level in levels"
+          :key="level"
+          :class="[
+            'level-item',
+            {
+              'level-item-act': level === curSelectLevel,
+              'level-item-disabled': level === curChangePaper.level,
+            },
+          ]"
+          @click="selectLevel(level)"
+        >
+          {{ level }}
+        </p>
+      </div>
+
+      <div slot="footer">
+        <Button
+          shape="circle"
+          type="primary"
+          :disabled="isSubmit || !curSelectLevel"
+          @click="confirmChange"
+          >确认</Button
+        >
+        <Button shape="circle" @click="cancelChange">取消</Button>
+      </div>
+    </Modal>
+  </div>
+</template>
+
+<script>
+import {
+  paperList,
+  sampleAreaList,
+  workLevelList,
+  cancelStandardPaper,
+  leaderGradingPaper,
+  subjectDetail,
+} from "@/api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "grading-standard-paper-manage",
+  components: { SimpleImagePreview },
+  data() {
+    return {
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      canCancel: true,
+      questionId: "",
+      lastQuestionId: "",
+      curLevel: "",
+      curLevelIndex: -1,
+      levels: [],
+      areas: [],
+      paperList: [],
+      papers: [],
+      curPaper: {},
+      curSubject: {},
+      curPaperIndex: 0,
+      // change standard
+      modalIsShow: false,
+      curChangePaper: {},
+      curSelectLevel: null,
+      isSubmit: false,
+    };
+  },
+  mounted() {
+    this.subject = this.subjectId.split("-")[1];
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      await this.getAreaList();
+      this.questionId = this.areas[0] && this.areas[0].id;
+      if (!this.questionId) return;
+      await this.getSubjectDetail();
+      await this.getWorkLevels();
+      this.search();
+    },
+    async getWorkLevels() {
+      const data = await workLevelList(this.workId, this.curSubject.stage);
+      this.levels = data.map((item) => item.name);
+    },
+    async getAreaList() {
+      const data = await sampleAreaList({
+        workId: this.workId,
+        subject: this.subject,
+      });
+      this.areas = data.map((item) => {
+        return {
+          id: item.id,
+          areaName: `${item.areaName}-${item.name}`,
+          areaCode: item.areaCode,
+        };
+      });
+    },
+    async getSubjectDetail() {
+      const curSubject = await subjectDetail(this.subjectId);
+      this.curSubject = curSubject || {};
+    },
+    async search() {
+      this.lastQuestionId = this.questionId;
+      await this.getPaperList();
+      this.updatePapers();
+    },
+    updatePapers() {
+      if (this.curLevel) {
+        this.papers = this.paperList.filter(
+          (paper) => paper.level === this.curLevel
+        );
+      } else {
+        this.papers = this.paperList;
+      }
+    },
+    async getPaperList() {
+      const datas = {
+        questionId: this.questionId,
+        level: "",
+        sort: "secretNumber",
+        isSample: true,
+        page: 0,
+        size: 100,
+      };
+      const data = await paperList(datas);
+      this.paperList = data.data.map((item) => {
+        item.title = `NO.${item.sn}`;
+        item.loading = false;
+        return item;
+      });
+      this.paperList.sort((a, b) => (a.level < b.level ? -1 : 1));
+    },
+    switchLevel(index) {
+      this.curLevelIndex = index;
+      this.curLevel = this.levels[index];
+
+      this.updatePapers();
+    },
+    showAllLevel() {
+      this.curLevelIndex = -1;
+      this.curLevel = "";
+      this.updatePapers();
+    },
+    cancelPaper(paper) {
+      if (paper.loading) return;
+      this.$Modal.confirm({
+        content: "确定要取消当前标准卷吗?",
+        onOk: async () => {
+          paper.loading = true;
+          const res = await cancelStandardPaper(paper.id).catch(() => {});
+          paper.loading = false;
+          if (!res) return;
+
+          this.paperList = this.paperList.filter(
+            (item) => paper.level !== item.level
+          );
+          this.papers = this.papers.filter(
+            (item) => paper.level !== item.level
+          );
+        },
+      });
+    },
+    // change standard paper
+    toChangePaper(paper) {
+      this.curChangePaper = paper;
+      this.modalIsShow = true;
+    },
+    selectLevel(level) {
+      if (level === this.curChangePaper.level) return;
+      this.curSelectLevel = level;
+    },
+    async confirmChange() {
+      if (!this.curSelectLevel) return;
+      if (this.isSubmit) return;
+
+      this.isSubmit = true;
+      const datas = {
+        action: "sampling",
+        level: this.curSelectLevel,
+        originLevel: this.curChangePaper.level,
+        paperIds: this.curChangePaper.id,
+        stage: this.curSubject.stage,
+      };
+      let result = true;
+      await leaderGradingPaper(datas).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+
+      if (!result) return;
+
+      this.$Message.success("操作成功!");
+      this.cancelChange();
+      this.search();
+    },
+    cancelChange() {
+      this.curSelectLevel = null;
+      this.modalIsShow = false;
+    },
+    // to review
+    toReview(index) {
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.curLevelIndex === 0 || this.curLevelIndex === -1) {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        } else {
+          this.curLevelIndex--;
+          this.curLevel = this.levels[this.curLevelIndex];
+          await this.updatePapers();
+          this.curPaperIndex = this.papers.length - 1;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (
+        this.curPaperIndex === this.papers.length - 1 ||
+        !this.papers.length
+      ) {
+        if (
+          this.curLevelIndex === this.levels.length - 1 ||
+          this.curLevelIndex === -1
+        ) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.curLevelIndex++;
+          this.curLevel = this.levels[this.curLevelIndex];
+          await this.updatePapers();
+          this.curPaperIndex = 0;
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

+ 26 - 26
src/modules/grading/GradingUserManage.vue

@@ -41,7 +41,7 @@ import {
   gradingUserList,
   gradingUserList,
   deleteGradingUser,
   deleteGradingUser,
   resetPwd,
   resetPwd,
-  subjectDetail
+  subjectDetail,
 } from "@/api";
 } from "@/api";
 import ModifyGradingUser from "./components/ModifyGradingUser";
 import ModifyGradingUser from "./components/ModifyGradingUser";
 import { ROLE_TYPE, MARKER_RIGHT_TYPE } from "@/constants/enumerate";
 import { ROLE_TYPE, MARKER_RIGHT_TYPE } from "@/constants/enumerate";
@@ -62,31 +62,31 @@ export default {
           type: "index",
           type: "index",
           title: "序号",
           title: "序号",
           width: 80,
           width: 80,
-          align: "center"
+          align: "center",
         },
         },
         {
         {
           title: "科目",
           title: "科目",
-          key: "subject"
+          key: "subject",
         },
         },
         {
         {
           title: "账号",
           title: "账号",
-          key: "loginName"
+          key: "loginName",
         },
         },
         {
         {
           title: "姓名",
           title: "姓名",
-          key: "name"
+          key: "name",
         },
         },
         {
         {
           title: "角色",
           title: "角色",
-          key: "roleName"
+          key: "roleName",
         },
         },
         {
         {
           title: "权限",
           title: "权限",
-          key: "rightName"
+          key: "rightName",
         },
         },
         {
         {
           title: "权重",
           title: "权重",
-          key: "weight"
+          key: "weight",
         },
         },
         {
         {
           title: "操作",
           title: "操作",
@@ -99,38 +99,38 @@ export default {
               {
               {
                 icon: "md-settings",
                 icon: "md-settings",
                 attrs: {
                 attrs: {
-                  title: "重置密码"
+                  title: "重置密码",
                 },
                 },
                 action: () => {
                 action: () => {
                   this.toResetPwd(param.row);
                   this.toResetPwd(param.row);
-                }
+                },
               },
               },
               {
               {
                 icon: "md-create",
                 icon: "md-create",
                 attrs: {
                 attrs: {
-                  title: "编辑"
+                  title: "编辑",
                 },
                 },
                 action: () => {
                 action: () => {
                   this.toEdit(param.row);
                   this.toEdit(param.row);
-                }
-              }
+                },
+              },
             ];
             ];
             if (param.row.role !== "MARK_LEADER") {
             if (param.row.role !== "MARK_LEADER") {
               actions.push({
               actions.push({
                 icon: "md-trash",
                 icon: "md-trash",
                 classes: ["icon-danger"],
                 classes: ["icon-danger"],
                 attrs: {
                 attrs: {
-                  title: "删除"
+                  title: "删除",
                 },
                 },
                 action: () => {
                 action: () => {
                   this.toDelete(param.row);
                   this.toDelete(param.row);
-                }
+                },
               });
               });
             }
             }
             return h("div", this.$tableIconAction(h, actions));
             return h("div", this.$tableIconAction(h, actions));
-          }
-        }
-      ]
+          },
+        },
+      ],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -142,10 +142,10 @@ export default {
     async getList() {
     async getList() {
       const datas = {
       const datas = {
         workId: this.workId,
         workId: this.workId,
-        subject: this.subject
+        subject: this.subject,
       };
       };
       const data = await gradingUserList(datas);
       const data = await gradingUserList(datas);
-      this.users = data.map(item => {
+      this.users = data.map((item) => {
         item.roleName = ROLE_TYPE[item.role];
         item.roleName = ROLE_TYPE[item.role];
         item.rightName =
         item.rightName =
           item.role === "MARK_LEADER"
           item.role === "MARK_LEADER"
@@ -158,10 +158,10 @@ export default {
       const roles = {
       const roles = {
         oneClickLevel: "一键定档",
         oneClickLevel: "一键定档",
         standardVolume: "设立标准卷",
         standardVolume: "设立标准卷",
-        levelCallback: "打回"
+        levelCallback: "打回",
       };
       };
       let roleNames = [];
       let roleNames = [];
-      Object.keys(roles).map(k => {
+      Object.keys(roles).map((k) => {
         if (item[k]) roleNames.push(roles[k]);
         if (item[k]) roleNames.push(roles[k]);
       });
       });
       return roleNames.join(",");
       return roleNames.join(",");
@@ -176,7 +176,7 @@ export default {
     toAdd() {
     toAdd() {
       this.curUser = {
       this.curUser = {
         workId: this.workId,
         workId: this.workId,
-        subject: this.subject
+        subject: this.subject,
       };
       };
       this.$refs.ModifyGradingUser.open();
       this.$refs.ModifyGradingUser.open();
     },
     },
@@ -190,7 +190,7 @@ export default {
         content: "确定要删除当前账号吗?",
         content: "确定要删除当前账号吗?",
         onOk: () => {
         onOk: () => {
           this.toDel(row.id);
           this.toDel(row.id);
-        }
+        },
       });
       });
     },
     },
     async toDel(id) {
     async toDel(id) {
@@ -204,7 +204,7 @@ export default {
           `${this.GLOBAL.domain}/api/export/users?workId=${this.workId}&subject=${this.subject}`
           `${this.GLOBAL.domain}/api/export/users?workId=${this.workId}&subject=${this.subject}`
         )
         )
       );
       );
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 7 - 7
src/modules/grading/components/CleanGradingDataDialog.vue

@@ -42,8 +42,8 @@ export default {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
-    }
+      },
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -51,8 +51,8 @@ export default {
       isSubmit: false,
       isSubmit: false,
       modalForm: { password: "" },
       modalForm: { password: "" },
       rules: {
       rules: {
-        password
-      }
+        password,
+      },
     };
     };
   },
   },
   methods: {
   methods: {
@@ -80,7 +80,7 @@ export default {
         subject: this.curSubject.subject,
         subject: this.curSubject.subject,
         stage: this.curSubject.stage,
         stage: this.curSubject.stage,
         loginName: this.$ls.get("user", { loginName: "" }).loginName,
         loginName: this.$ls.get("user", { loginName: "" }).loginName,
-        password: this.modalForm.password
+        password: this.modalForm.password,
       }).catch(() => {
       }).catch(() => {
         result = false;
         result = false;
       });
       });
@@ -91,7 +91,7 @@ export default {
       this.$Modal.success({ content: "操作成功!" });
       this.$Modal.success({ content: "操作成功!" });
       this.$emit("modified");
       this.$emit("modified");
       this.cancel();
       this.cancel();
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 599 - 598
src/modules/grading/components/GradeAction.vue

@@ -1,598 +1,599 @@
-<template>
-  <div class="grade-action">
-    <div
-      v-if="IS_MARKER && curPaperOrTask.fontFrom === 'history'"
-      :class="['action-history-mark', { 'mark-act': curPaperOrTask.mark }]"
-      @click="toMark"
-    >
-      标记
-    </div>
-    <!-- 头部信息 ------ -->
-    <!-- 试卷状态 -->
-    <!-- 状态:已评,待评,打回,仲裁 -->
-    <div class="action-paper-state" v-if="stepType === 'reject'">
-      <p class="paper-state-cont">
-        {{ curPaperOrTask.isRejectedByLeader ? "科组长打回" : "自动打回" }}
-      </p>
-      <p class="paper-state-intro">
-        <span v-if="curPaperOrTask.rejectedCount"
-          >共打回{{ curPaperOrTask.rejectedCount }}次</span
-        >
-      </p>
-    </div>
-    <div class="action-paper-state" v-else>
-      <p class="paper-state-cont">{{ stepLabel }}</p>
-    </div>
-
-    <!-- 试卷信息 -->
-    <div class="action-paper-info">
-      <p>
-        <span v-if="IS_MARKER">任务密号:</span>
-        <span v-else>试卷密号:</span>
-        <span v-if="curPaperOrTask.sn && !isBatchAction">
-          NO.{{ curPaperOrTask.sn }}
-        </span>
-        <span v-else>--</span>
-      </p>
-    </div>
-
-    <!-- 选择档位 -->
-    <h3
-      class="action-grade-info-title"
-      v-if="IS_MARK_LEADER && markLeaderOnlyRight && rights.gradeList"
-    >
-      当前操作:{{ markLeaderOnlyRight.name }}
-    </h3>
-    <div class="action-grade-list" v-if="rights.gradeList">
-      <div
-        class="action-grade-item"
-        v-for="(level, index) in levels"
-        :key="index"
-      >
-        <div
-          :class="[
-            'action-grade-item-content',
-            {
-              'action-item-content-disabled': btnClicked,
-              'is-active': keyInput == level.name
-            }
-          ]"
-          @click="selectLevel(level)"
-        >
-          <p>{{ level.name | levelNameFilter }}</p>
-          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
-          <p v-if="level.minSubScore || level.maxSubScore">
-            {{ level.minSubScore }}~{{ level.maxSubScore }}
-          </p>
-        </div>
-      </div>
-    </div>
-    <div
-      v-if="ribbonSet.keyboardMark && rights.gradeList"
-      class="action-grade-keyboard"
-    >
-      <div class="keyboard-input">{{ keyInput }}</div>
-      <div class="keyboard-clear" @click="clearKeyInput">
-        <Icon type="md-trash" />
-      </div>
-    </div>
-
-    <!-- 档位信息 -->
-    <!-- 已评(已评档位),打回(建议档位) -->
-    <h3
-      class="action-grade-info-title"
-      v-if="IS_MARKER && stepType === 'reject'"
-    >
-      <span
-        >原分档档位:{{ curPaperOrTask.originLevel | levelNameFilter }}</span
-      >
-      <span
-        v-if="
-          paramsSet.levelConfig &&
-            paramsSet.levelConfig.autoCallbackShowDeviation &&
-            curPaperOrTask.deviationDirection &&
-            curPaperOrTask.deviationDirection !== '0'
-        "
-        :class="[
-          'grade-info-deviation',
-          {
-            'grade-info-deviation-error':
-              curPaperOrTask.deviationDirection * 1 > 0
-          }
-        ]"
-        >{{ curPaperOrTask.deviationDirection * 1 > 0 ? "偏高" : "偏低" }}</span
-      >
-    </h3>
-    <h3
-      class="action-grade-info-title"
-      v-if="curPaperOrTask.rejected && curPaperOrTask.isRejectedByLeader"
-    >
-      建议档位:
-    </h3>
-    <div class="action-grade-info" v-if="rights.gradeInfo && curLevel.name">
-      <h3 class="grade-info-name">{{ curLevel.name | levelNameFilter }}</h3>
-      <div class="grade-info-range">
-        <p>{{ levelRangeName }}范围</p>
-        <p>
-          <span>{{ curLevel.minScore }}</span>
-          <span>~</span>
-          <span>{{ curLevel.maxScore }}</span>
-        </p>
-      </div>
-    </div>
-
-    <!-- 跳过:自测卷不允许跳过 -->
-    <div
-      class="action-grade-pass"
-      v-if="rights.gradePass && IS_MARKER && !curPaperOrTask.selfCheck"
-      @click="toPass"
-    >
-      跳过
-    </div>
-
-    <!-- 评卷记录 -->
-    <div class="action-grade-history" v-if="rights.gradeHis">
-      <h3>评卷记录</h3>
-      <div class="grade-history-list">
-        <div
-          class="grade-history-item"
-          v-for="his in gradingHistory"
-          :key="his.id"
-        >
-          <p>{{ his.loginName }}</p>
-          <p>{{ his.value | levelNameFilter }}</p>
-        </div>
-      </div>
-    </div>
-
-    <!-- 查询 -->
-    <div class="action-search" v-if="rights.search">
-      <Select
-        class="search-select"
-        v-model="filter.codeType"
-        placeholder="密号类型"
-      >
-        <Option
-          v-for="item in codeTypes"
-          :key="item.key"
-          :value="item.key"
-          :label="item.val"
-        ></Option>
-      </Select>
-      <Input
-        class="search-input"
-        v-model.trim="filter.code"
-        placeholder="输入密号"
-        clearable
-      >
-      </Input>
-      <Button size="small" type="primary" class="search-btn" @click="searchCode"
-        >查询</Button
-      >
-    </div>
-  </div>
-</template>
-
-<script>
-import { markHistoryList, markTask } from "@/api";
-import { CODE_TYPE } from "@/constants/enumerate";
-import { mapState, mapMutations } from "vuex";
-import { levelNameTransform } from "@/plugins/utils";
-
-// 三种情况:
-// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
-// 管理员:查询,头部信息,评卷记录
-// 科组长:查询,头部信息,选择档位,评卷记录
-// 评卷员:头部信息,选择档位
-
-// MARK_LEADER / ADMIN: curPaperOrTask => paper
-// MARKER: curPaperOrTask => task
-//
-/*
-[paper template]
-{
-  "id": 165,
-  "sn": "029947536",
-  "examNumber": "1901040084",
-  "level": "A",
-  "score": null,
-  "redoLevel": null,
-  "updatedOn": 1591767742000,
-  "imgSrc": "",
-  "thumbSrc": "",
-  "markByLeader": false,
-  "markedLogic": true,
-  "areaCode": "2",
-  "inspectScore": null,
-  "inspectLevel": null,
-  "inspector": null,
-  "sheetSrc": null,
-  "stage": "LEVEL",
-  "test": 0,
-  "paperTest": 0,
-  "markResults": [],
-  "rejected": false,
-  "arbitrated": false,
-  "sample": false,
-  "tagged": false,
-  "missing": false,
-  "manual": false
-}
-[marktask template]
-{
-  "id": 511,
-  "sn": "4929446110",
-  "redoLevel": null,
-  "level": "A",
-  "score": null,
-  "result": "100",
-  "originLevel": null,
-  "markerId": 49,
-  "marker": "pj061001",
-  "updatedOn": 1594775592000,
-  "imgSrc": "",
-  "thumbSrc": "",
-  "markByLeader": true,
-  "oldRejected": false,
-  "paperId": 168,
-  "randomSeqNew": 9446110,
-  "randomSeq": null,
-  "rejected": false,
-  "sample": true
-}
-*/
-
-const initRights = {
-  search: false,
-  gradeInfo: false,
-  gradeList: false,
-  gradePass: false,
-  gradeHis: false
-};
-
-export default {
-  name: "grade-action",
-  props: {
-    curPaperOrTask: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    levels: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    paramsSet: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    isBatchAction: {
-      type: Boolean,
-      default: false
-    },
-    // 是否处于粗分档
-    isRoughLevel: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      curPaperOrTaskLevel: "",
-      rights: {
-        ...initRights
-      },
-      cacheRights: null,
-      roleRight: {
-        ADMIN: {
-          done: ["search", "gradeHis", "gradeInfo"],
-          reject: ["search", "gradeInfo", "gradeHis"],
-          arbitrate: ["search", "gradeHis"]
-        },
-        MARK_LEADER: {
-          undo: ["gradeList", "gradePass", "gradeInfo"],
-          done: ["gradeList", "gradeHis", "gradeInfo"],
-          reject: ["gradeList", "gradePass", "gradeInfo", "gradeHis"],
-          arbitrate: ["gradeList", "gradePass", "gradeHis"],
-          batch: ["gradeList"]
-        },
-        MARKER: {
-          done: ["gradeList", "gradeInfo"],
-          undo: ["gradeList", "gradePass"],
-          reject: ["gradeList", "gradePass", "gradeInfo"],
-          batch: ["gradeList"]
-        },
-        STANDARD: ["gradeInfo"]
-      },
-      filter: {
-        codeType: "examNumber",
-        code: ""
-      },
-      codeTypes: [],
-      stepDict: {
-        undo: "待评",
-        done: "已评",
-        reject: "打回",
-        arbitrate: "待仲裁",
-        sample: "标准卷",
-        batch: "批量操作"
-      },
-      stepType: "",
-      stepLabel: "",
-      gradingHistory: [],
-      curLevel: {},
-      setT: null,
-      btnClicked: false,
-      keyInput: null,
-      // 科组长权限
-      markLeaderOnlyRight: null,
-      leaderConfirm: true,
-      // 标记
-      loading: false
-    };
-  },
-  computed: {
-    ...mapState("marker", ["ribbonSet", "shortcutKeyStatus", "curSubject"]),
-    IS_ADMIN() {
-      return this.curUserRoleType === "ADMIN";
-    },
-    IS_MARKER() {
-      return this.curUserRoleType === "MARKER";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    },
-    levelRangeName() {
-      return this.curSubject.stage === "LEVEL" ? "分数" : "档位";
-    }
-  },
-  watch: {
-    curPaperOrTask() {
-      this.rebuildRight();
-    },
-    isBatchAction(val) {
-      if (val) {
-        this.stepType = "batch";
-        this.stepLabel = this.stepDict[this.stepType];
-        const roleRights =
-          this.roleRight[this.curUserRoleType][this.stepType] || [];
-        this.rights = { ...initRights };
-        roleRights.map(key => {
-          this.rights[key] = true;
-        });
-      } else {
-        this.rebuildRight();
-      }
-      this.keyInput = null;
-    },
-    "ribbonSet.keyboardMark": {
-      immediate: true,
-      handler(val) {
-        this.setShortcutStatus({ action: val });
-      }
-    },
-    "shortcutKeyStatus.action": {
-      immediate: true,
-      handler(val, oldval) {
-        // console.log(val, oldval);
-        if (val === oldval) return;
-        if (val) {
-          document.addEventListener("keydown", this.keyEvent);
-        } else {
-          document.removeEventListener("keydown", this.keyEvent);
-        }
-      }
-    }
-  },
-  mounted() {
-    const userRight = this.$ls.get("user", {
-      markLeaderOnlyRight: null
-    });
-    this.markLeaderOnlyRight = userRight.markLeaderOnlyRight;
-    this.leaderConfirm = userRight.leaderConfirm;
-
-    this.codeTypes = Object.entries(CODE_TYPE)
-      .map(([key, val]) => {
-        return {
-          key,
-          val
-        };
-      })
-      .filter(item => item.key !== "examNumber");
-    // .filter(item => this.IS_ADMIN || item.key !== "examNumber");
-    this.rebuildRight();
-  },
-  methods: {
-    ...mapMutations("marker", ["setShortcutStatus"]),
-    getStepType() {
-      const info = this.curPaperOrTask;
-      if (
-        (this.curSubject.stage === "LEVEL" && info.sample) ||
-        (this.curSubject.stage === "ROUGH_LEVEL" && info.roughSample)
-      )
-        return "sample";
-      if (this.curPaperOrTaskLevel) return "done";
-      if (info.arbitrated) return "arbitrate";
-      if (info.rejected) return "reject";
-      if (!info.rejected && !info.arbitrated && !info.level) return "undo";
-      return;
-    },
-    rebuildRight() {
-      if (this.setT) clearTimeout(this.setT);
-      this.curPaperOrTaskLevel =
-        this.curSubject.stage === "LEVEL"
-          ? this.curPaperOrTask.level
-          : this.curPaperOrTask.roughLevel || this.curPaperOrTask.level;
-
-      let roleRights = [];
-      this.stepType = this.getStepType();
-      this.stepLabel = this.stepDict[this.stepType];
-      if (this.stepType === "sample") {
-        roleRights = this.roleRight.STANDARD;
-      } else {
-        roleRights = this.roleRight[this.curUserRoleType][this.stepType] || [];
-      }
-      this.rights = { ...initRights };
-      roleRights.map(key => {
-        this.rights[key] = true;
-      });
-      this.getCurLevel();
-      if (this.rights.gradeHis) {
-        this.getMarkHistory();
-      }
-      this.btnClicked = false;
-      this.keyInput = null;
-    },
-    getCurLevel() {
-      const levelName = this.curPaperOrTask.rejected
-        ? this.curPaperOrTask.redoLevel
-        : this.curPaperOrTaskLevel;
-      if (levelName) {
-        this.curLevel = this.levels.find(item => item.name === levelName) || {};
-      } else {
-        this.curLevel = {};
-      }
-    },
-    async getMarkHistory() {
-      // 只有科组长和超管才会展示评卷记录
-      const data = await markHistoryList(
-        this.curPaperOrTask.id,
-        this.curSubject.stage
-      );
-      this.gradingHistory = data.map(item => {
-        let level = item.result || "未评";
-        if (this.stepType === "reject" && !item.result) {
-          level = `${levelNameTransform(level)}(${levelNameTransform(
-            item.originLevel
-          )})`;
-        }
-        return {
-          id: item.id,
-          markerId: item.markerId,
-          name: item.marker,
-          loginName: item.loginName,
-          value: level
-        };
-      });
-    },
-    selectLevel(level) {
-      if (this.isBatchAction) {
-        if (this.btnClicked) return;
-        this.btnClicked = true;
-        this.setT = setTimeout(() => {
-          this.btnClicked = false;
-        }, 500);
-        this.$emit("on-batch-level", level);
-        return;
-      }
-
-      if (this.IS_MARKER && this.curPaperOrTaskLevel === level.name) return;
-      if (this.btnClicked) return;
-      this.btnClicked = true;
-
-      if (this.IS_MARK_LEADER) {
-        this.setT = setTimeout(() => {
-          this.btnClicked = false;
-        }, 500);
-
-        this.$emit(
-          "on-leader-level",
-          {
-            paperIds: this.curPaperOrTask.id + "",
-            curLevel: this.curPaperOrTaskLevel,
-            selectedLevel: level.name,
-            markLeaderOnlyRight: this.markLeaderOnlyRight,
-            leaderConfirm: this.leaderConfirm
-          },
-          this.gradingHistory.map(item => {
-            return {
-              id: item.markerId,
-              name: item.loginName
-            };
-          })
-        );
-        return;
-      }
-
-      this.$emit("on-select-level", level);
-    },
-    toPass() {
-      this.$emit("on-pass");
-    },
-    searchCode() {
-      if (!this.filter.code || !this.filter.codeType) {
-        this.$Message.error("请设置密号类型和密号!");
-        return;
-      }
-      this.$emit("on-code-search", this.filter);
-    },
-    async toMark() {
-      if (this.loading) return;
-      this.loading = true;
-      let res = null;
-      res = await markTask({
-        markTaskId: this.curPaperOrTask.id,
-        isMark: !this.curPaperOrTask.mark,
-        stage: this.curSubject.stage
-      }).catch(() => {});
-
-      this.loading = false;
-      if (!res) return;
-      this.curPaperOrTask.mark = !this.curPaperOrTask.mark;
-      this.$emit("on-history-mark", this.curPaperOrTask.mark);
-    },
-    // keyboard submit
-    keyEvent(e) {
-      this.$Message.destroy();
-      if (this.btnClicked) return;
-      // if (!this.ribbonSet.keyboardMark) return;
-      if (!e.altKey && !e.shiftKey && !e.ctrlKey) {
-        if (e.key === "Enter" && this.ribbonSet.needEnterSubmit) {
-          e.preventDefault();
-          this.toKeySubmit();
-          return;
-        }
-        if (!/^[a-zA-Z0-9]$/.test(e.key)) return;
-
-        const keyInput = e.key.toUpperCase();
-        if (this.getKeyInputLevel(keyInput)) {
-          e.preventDefault();
-          this.keyInput = keyInput;
-
-          if (!this.ribbonSet.needEnterSubmit) {
-            this.toKeySubmit();
-          }
-        } else {
-          this.$Message.error("按键无效");
-        }
-      }
-    },
-    getKeyInputLevel(key) {
-      return (
-        this.rights.gradeList && this.levels.find(item => item.name === key)
-      );
-    },
-    toKeySubmit() {
-      if (!this.keyInput) {
-        this.$Message.error("请选择档位");
-        return;
-      }
-      const level = this.getKeyInputLevel(this.keyInput);
-      this.selectLevel(level);
-    },
-    clearKeyInput() {
-      this.keyInput = null;
-    }
-  },
-  beforeDestroy() {
-    if (this.setT) clearTimeout(this.setT);
-    document.removeEventListener("keydown", this.keyEvent);
-  }
-};
-</script>
+<template>
+  <div class="grade-action">
+    <div
+      v-if="IS_MARKER && curPaperOrTask.fontFrom === 'history'"
+      :class="['action-history-mark', { 'mark-act': curPaperOrTask.mark }]"
+      @click="toMark"
+    >
+      标记
+    </div>
+    <!-- 头部信息 ------ -->
+    <!-- 试卷状态 -->
+    <!-- 状态:已评,待评,打回,仲裁 -->
+    <div class="action-paper-state" v-if="stepType === 'reject'">
+      <p class="paper-state-cont">
+        {{ curPaperOrTask.isRejectedByLeader ? "科组长打回" : "自动打回" }}
+      </p>
+      <p class="paper-state-intro">
+        <span v-if="curPaperOrTask.rejectedCount"
+          >共打回{{ curPaperOrTask.rejectedCount }}次</span
+        >
+      </p>
+    </div>
+    <div class="action-paper-state" v-else>
+      <p class="paper-state-cont">{{ stepLabel }}</p>
+    </div>
+
+    <!-- 试卷信息 -->
+    <div class="action-paper-info">
+      <p>
+        <span v-if="IS_MARKER">任务密号:</span>
+        <span v-else>试卷密号:</span>
+        <span v-if="curPaperOrTask.sn && !isBatchAction">
+          NO.{{ curPaperOrTask.sn }}
+        </span>
+        <span v-else>--</span>
+      </p>
+    </div>
+
+    <!-- 选择档位 -->
+    <h3
+      class="action-grade-info-title"
+      v-if="IS_MARK_LEADER && markLeaderOnlyRight && rights.gradeList"
+    >
+      当前操作:{{ markLeaderOnlyRight.name }}
+    </h3>
+    <div class="action-grade-list" v-if="rights.gradeList">
+      <div
+        class="action-grade-item"
+        v-for="(level, index) in levels"
+        :key="index"
+      >
+        <div
+          :class="[
+            'action-grade-item-content',
+            {
+              'action-item-content-disabled': btnClicked,
+              'is-active': keyInput == level.name,
+            },
+          ]"
+          @click="selectLevel(level)"
+        >
+          <p>{{ level.name | levelNameFilter }}</p>
+          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
+          <p v-if="level.minSubScore || level.maxSubScore">
+            {{ level.minSubScore }}~{{ level.maxSubScore }}
+          </p>
+        </div>
+      </div>
+    </div>
+    <div
+      v-if="ribbonSet.keyboardMark && rights.gradeList"
+      class="action-grade-keyboard"
+    >
+      <div class="keyboard-input">{{ keyInput }}</div>
+      <div class="keyboard-clear" @click="clearKeyInput">
+        <Icon type="md-trash" />
+      </div>
+    </div>
+
+    <!-- 档位信息 -->
+    <!-- 已评(已评档位),打回(建议档位) -->
+    <h3
+      class="action-grade-info-title"
+      v-if="IS_MARKER && stepType === 'reject'"
+    >
+      <span
+        >原分档档位:{{ curPaperOrTask.originLevel | levelNameFilter }}</span
+      >
+      <span
+        v-if="
+          paramsSet.levelConfig &&
+          paramsSet.levelConfig.autoCallbackShowDeviation &&
+          curPaperOrTask.deviationDirection &&
+          curPaperOrTask.deviationDirection !== '0'
+        "
+        :class="[
+          'grade-info-deviation',
+          {
+            'grade-info-deviation-error':
+              curPaperOrTask.deviationDirection * 1 > 0,
+          },
+        ]"
+        >{{ curPaperOrTask.deviationDirection * 1 > 0 ? "偏高" : "偏低" }}</span
+      >
+    </h3>
+    <h3
+      class="action-grade-info-title"
+      v-if="curPaperOrTask.rejected && curPaperOrTask.isRejectedByLeader"
+    >
+      建议档位:
+    </h3>
+    <div class="action-grade-info" v-if="rights.gradeInfo && curLevel.name">
+      <h3 class="grade-info-name">{{ curLevel.name | levelNameFilter }}</h3>
+      <div class="grade-info-range">
+        <p>{{ levelRangeName }}范围</p>
+        <p>
+          <span>{{ curLevel.minScore }}</span>
+          <span>~</span>
+          <span>{{ curLevel.maxScore }}</span>
+        </p>
+      </div>
+    </div>
+
+    <!-- 跳过:自测卷不允许跳过 -->
+    <div
+      class="action-grade-pass"
+      v-if="rights.gradePass && IS_MARKER && !curPaperOrTask.selfCheck"
+      @click="toPass"
+    >
+      跳过
+    </div>
+
+    <!-- 评卷记录 -->
+    <div class="action-grade-history" v-if="rights.gradeHis">
+      <h3>评卷记录</h3>
+      <div class="grade-history-list">
+        <div
+          class="grade-history-item"
+          v-for="his in gradingHistory"
+          :key="his.id"
+        >
+          <p>{{ his.loginName }}</p>
+          <p>{{ his.value | levelNameFilter }}</p>
+        </div>
+      </div>
+    </div>
+
+    <!-- 查询 -->
+    <div class="action-search" v-if="rights.search">
+      <Select
+        class="search-select"
+        v-model="filter.codeType"
+        placeholder="密号类型"
+      >
+        <Option
+          v-for="item in codeTypes"
+          :key="item.key"
+          :value="item.key"
+          :label="item.val"
+        ></Option>
+      </Select>
+      <Input
+        class="search-input"
+        v-model.trim="filter.code"
+        placeholder="输入密号"
+        clearable
+      >
+      </Input>
+      <Button size="small" type="primary" class="search-btn" @click="searchCode"
+        >查询</Button
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+import { markHistoryList, markTask } from "@/api";
+import { CODE_TYPE } from "@/constants/enumerate";
+import { mapState, mapMutations } from "vuex";
+import { levelNameTransform } from "@/plugins/utils";
+
+// 三种情况:
+// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
+// 管理员:查询,头部信息,评卷记录
+// 科组长:查询,头部信息,选择档位,评卷记录
+// 评卷员:头部信息,选择档位
+
+// MARK_LEADER / ADMIN: curPaperOrTask => paper
+// MARKER: curPaperOrTask => task
+//
+/*
+[paper template]
+{
+  "id": 165,
+  "sn": "029947536",
+  "examNumber": "1901040084",
+  "level": "A",
+  "score": null,
+  "redoLevel": null,
+  "updatedOn": 1591767742000,
+  "imgSrc": "",
+  "thumbSrc": "",
+  "markByLeader": false,
+  "markedLogic": true,
+  "areaCode": "2",
+  "inspectScore": null,
+  "inspectLevel": null,
+  "inspector": null,
+  "sheetSrc": null,
+  "stage": "LEVEL",
+  "test": 0,
+  "paperTest": 0,
+  "markResults": [],
+  "rejected": false,
+  "arbitrated": false,
+  "sample": false,
+  "tagged": false,
+  "missing": false,
+  "manual": false
+}
+[marktask template]
+{
+  "id": 511,
+  "sn": "4929446110",
+  "redoLevel": null,
+  "level": "A",
+  "score": null,
+  "result": "100",
+  "originLevel": null,
+  "markerId": 49,
+  "marker": "pj061001",
+  "updatedOn": 1594775592000,
+  "imgSrc": "",
+  "thumbSrc": "",
+  "markByLeader": true,
+  "oldRejected": false,
+  "paperId": 168,
+  "randomSeqNew": 9446110,
+  "randomSeq": null,
+  "rejected": false,
+  "sample": true
+}
+*/
+
+const initRights = {
+  search: false,
+  gradeInfo: false,
+  gradeList: false,
+  gradePass: false,
+  gradeHis: false,
+};
+
+export default {
+  name: "grade-action",
+  props: {
+    curPaperOrTask: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    levels: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    paramsSet: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    isBatchAction: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否处于粗分档
+    isRoughLevel: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      curPaperOrTaskLevel: "",
+      rights: {
+        ...initRights,
+      },
+      cacheRights: null,
+      roleRight: {
+        ADMIN: {
+          done: ["search", "gradeHis", "gradeInfo"],
+          reject: ["search", "gradeInfo", "gradeHis"],
+          arbitrate: ["search", "gradeHis"],
+        },
+        MARK_LEADER: {
+          undo: ["gradeList", "gradePass", "gradeInfo"],
+          done: ["gradeList", "gradeHis", "gradeInfo"],
+          reject: ["gradeList", "gradePass", "gradeInfo", "gradeHis"],
+          arbitrate: ["gradeList", "gradePass", "gradeHis"],
+          batch: ["gradeList"],
+        },
+        MARKER: {
+          done: ["gradeList", "gradeInfo"],
+          undo: ["gradeList", "gradePass"],
+          reject: ["gradeList", "gradePass", "gradeInfo"],
+          batch: ["gradeList"],
+        },
+        STANDARD: ["gradeInfo"],
+      },
+      filter: {
+        codeType: "examNumber",
+        code: "",
+      },
+      codeTypes: [],
+      stepDict: {
+        undo: "待评",
+        done: "已评",
+        reject: "打回",
+        arbitrate: "待仲裁",
+        sample: "标准卷",
+        batch: "批量操作",
+      },
+      stepType: "",
+      stepLabel: "",
+      gradingHistory: [],
+      curLevel: {},
+      setT: null,
+      btnClicked: false,
+      keyInput: null,
+      // 科组长权限
+      markLeaderOnlyRight: null,
+      leaderConfirm: true,
+      // 标记
+      loading: false,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["ribbonSet", "shortcutKeyStatus", "curSubject"]),
+    IS_ADMIN() {
+      return this.curUserRoleType === "ADMIN";
+    },
+    IS_MARKER() {
+      return this.curUserRoleType === "MARKER";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    },
+    levelRangeName() {
+      return this.curSubject.stage === "LEVEL" ? "分数" : "档位";
+    },
+  },
+  watch: {
+    curPaperOrTask() {
+      this.rebuildRight();
+    },
+    isBatchAction(val) {
+      if (val) {
+        this.stepType = "batch";
+        this.stepLabel = this.stepDict[this.stepType];
+        const roleRights =
+          this.roleRight[this.curUserRoleType][this.stepType] || [];
+        this.rights = { ...initRights };
+        roleRights.map((key) => {
+          this.rights[key] = true;
+        });
+      } else {
+        this.rebuildRight();
+      }
+      this.keyInput = null;
+    },
+    "ribbonSet.keyboardMark": {
+      immediate: true,
+      handler(val) {
+        this.setShortcutStatus({ action: val });
+      },
+    },
+    "shortcutKeyStatus.action": {
+      immediate: true,
+      handler(val, oldval) {
+        // console.log(val, oldval);
+        if (val === oldval) return;
+        if (val) {
+          document.addEventListener("keydown", this.keyEvent);
+        } else {
+          document.removeEventListener("keydown", this.keyEvent);
+        }
+      },
+    },
+  },
+  mounted() {
+    const userRight = this.$ls.get("user", {
+      markLeaderOnlyRight: null,
+    });
+    this.markLeaderOnlyRight = userRight.markLeaderOnlyRight;
+    this.leaderConfirm = userRight.leaderConfirm;
+
+    this.codeTypes = Object.entries(CODE_TYPE)
+      .map(([key, val]) => {
+        return {
+          key,
+          val,
+        };
+      })
+      .filter((item) => item.key !== "examNumber");
+    // .filter(item => this.IS_ADMIN || item.key !== "examNumber");
+    this.rebuildRight();
+  },
+  methods: {
+    ...mapMutations("marker", ["setShortcutStatus"]),
+    getStepType() {
+      const info = this.curPaperOrTask;
+      if (
+        (this.curSubject.stage === "LEVEL" && info.sample) ||
+        (this.curSubject.stage === "ROUGH_LEVEL" && info.roughSample)
+      )
+        return "sample";
+      if (this.curPaperOrTaskLevel) return "done";
+      if (info.arbitrated) return "arbitrate";
+      if (info.rejected) return "reject";
+      if (!info.rejected && !info.arbitrated && !info.level) return "undo";
+      return;
+    },
+    rebuildRight() {
+      if (this.setT) clearTimeout(this.setT);
+      this.curPaperOrTaskLevel =
+        this.curSubject.stage === "LEVEL"
+          ? this.curPaperOrTask.level
+          : this.curPaperOrTask.roughLevel || this.curPaperOrTask.level;
+
+      let roleRights = [];
+      this.stepType = this.getStepType();
+      this.stepLabel = this.stepDict[this.stepType];
+      if (this.stepType === "sample") {
+        roleRights = this.roleRight.STANDARD;
+      } else {
+        roleRights = this.roleRight[this.curUserRoleType][this.stepType] || [];
+      }
+      this.rights = { ...initRights };
+      roleRights.map((key) => {
+        this.rights[key] = true;
+      });
+      this.getCurLevel();
+      if (this.rights.gradeHis) {
+        this.getMarkHistory();
+      }
+      this.btnClicked = false;
+      this.keyInput = null;
+    },
+    getCurLevel() {
+      const levelName = this.curPaperOrTask.rejected
+        ? this.curPaperOrTask.redoLevel
+        : this.curPaperOrTaskLevel;
+      if (levelName) {
+        this.curLevel =
+          this.levels.find((item) => item.name === levelName) || {};
+      } else {
+        this.curLevel = {};
+      }
+    },
+    async getMarkHistory() {
+      // 只有科组长和超管才会展示评卷记录
+      const data = await markHistoryList(
+        this.curPaperOrTask.id,
+        this.curSubject.stage
+      );
+      this.gradingHistory = data.map((item) => {
+        let level = item.result || "未评";
+        if (this.stepType === "reject" && !item.result) {
+          level = `${levelNameTransform(level)}(${levelNameTransform(
+            item.originLevel
+          )})`;
+        }
+        return {
+          id: item.id,
+          markerId: item.markerId,
+          name: item.marker,
+          loginName: item.loginName,
+          value: level,
+        };
+      });
+    },
+    selectLevel(level) {
+      if (this.isBatchAction) {
+        if (this.btnClicked) return;
+        this.btnClicked = true;
+        this.setT = setTimeout(() => {
+          this.btnClicked = false;
+        }, 500);
+        this.$emit("on-batch-level", level);
+        return;
+      }
+
+      if (this.IS_MARKER && this.curPaperOrTaskLevel === level.name) return;
+      if (this.btnClicked) return;
+      this.btnClicked = true;
+
+      if (this.IS_MARK_LEADER) {
+        this.setT = setTimeout(() => {
+          this.btnClicked = false;
+        }, 500);
+
+        this.$emit(
+          "on-leader-level",
+          {
+            paperIds: this.curPaperOrTask.id + "",
+            curLevel: this.curPaperOrTaskLevel,
+            selectedLevel: level.name,
+            markLeaderOnlyRight: this.markLeaderOnlyRight,
+            leaderConfirm: this.leaderConfirm,
+          },
+          this.gradingHistory.map((item) => {
+            return {
+              id: item.markerId,
+              name: item.loginName,
+            };
+          })
+        );
+        return;
+      }
+
+      this.$emit("on-select-level", level);
+    },
+    toPass() {
+      this.$emit("on-pass");
+    },
+    searchCode() {
+      if (!this.filter.code || !this.filter.codeType) {
+        this.$Message.error("请设置密号类型和密号!");
+        return;
+      }
+      this.$emit("on-code-search", this.filter);
+    },
+    async toMark() {
+      if (this.loading) return;
+      this.loading = true;
+      let res = null;
+      res = await markTask({
+        markTaskId: this.curPaperOrTask.id,
+        isMark: !this.curPaperOrTask.mark,
+        stage: this.curSubject.stage,
+      }).catch(() => {});
+
+      this.loading = false;
+      if (!res) return;
+      this.curPaperOrTask.mark = !this.curPaperOrTask.mark;
+      this.$emit("on-history-mark", this.curPaperOrTask.mark);
+    },
+    // keyboard submit
+    keyEvent(e) {
+      this.$Message.destroy();
+      if (this.btnClicked) return;
+      // if (!this.ribbonSet.keyboardMark) return;
+      if (!e.altKey && !e.shiftKey && !e.ctrlKey) {
+        if (e.key === "Enter" && this.ribbonSet.needEnterSubmit) {
+          e.preventDefault();
+          this.toKeySubmit();
+          return;
+        }
+        if (!/^[a-zA-Z0-9]$/.test(e.key)) return;
+
+        const keyInput = e.key.toUpperCase();
+        if (this.getKeyInputLevel(keyInput)) {
+          e.preventDefault();
+          this.keyInput = keyInput;
+
+          if (!this.ribbonSet.needEnterSubmit) {
+            this.toKeySubmit();
+          }
+        } else {
+          this.$Message.error("按键无效");
+        }
+      }
+    },
+    getKeyInputLevel(key) {
+      return (
+        this.rights.gradeList && this.levels.find((item) => item.name === key)
+      );
+    },
+    toKeySubmit() {
+      if (!this.keyInput) {
+        this.$Message.error("请选择档位");
+        return;
+      }
+      const level = this.getKeyInputLevel(this.keyInput);
+      this.selectLevel(level);
+    },
+    clearKeyInput() {
+      this.keyInput = null;
+    },
+  },
+  beforeDestroy() {
+    if (this.setT) clearTimeout(this.setT);
+    document.removeEventListener("keydown", this.keyEvent);
+  },
+};
+</script>

+ 777 - 775
src/modules/grading/components/GradeActionRough.vue

@@ -1,775 +1,777 @@
-<template>
-  <div class="grade-action">
-    <div
-      v-if="IS_MARKER && curPaperOrTask.fontFrom === 'history'"
-      :class="['action-history-mark', { 'mark-act': curPaperOrTask.mark }]"
-      @click="toMark"
-    >
-      标记
-    </div>
-    <!-- 头部信息 ------ -->
-    <!-- 试卷状态 -->
-    <!-- 状态:已评,待评,打回,仲裁,改大裆,改大裆打小档 -->
-    <div class="action-paper-state" v-if="stepType === 'reject'">
-      <p class="paper-state-cont">
-        {{ curPaperOrTask.isRejectedByLeader ? "科组长打回" : "自动打回" }}
-      </p>
-      <p class="paper-state-intro">
-        <span v-if="curPaperOrTask.rejectedCount"
-          >共打回{{ curPaperOrTask.rejectedCount }}次</span
-        >
-      </p>
-    </div>
-    <div class="action-paper-state" v-else>
-      <p class="paper-state-cont">{{ stepLabel }}</p>
-    </div>
-    <!-- 试卷信息 -->
-    <div class="action-paper-info">
-      <p>
-        <span v-if="IS_MARKER">任务密号:</span>
-        <span v-else>试卷密号:</span>
-        <span v-if="curPaperOrTask.sn && !isBatchAction">
-          NO.{{ curPaperOrTask.sn }}
-        </span>
-        <span v-else>--</span>
-      </p>
-    </div>
-    <!-- 改档信息 -->
-    <div class="action-grade-change" v-if="rights.gradeChange">
-      <p>
-        <span>原始粗档位:</span
-        ><span>{{ curPaperOrTask.originLevel | levelNameFilter }}</span>
-      </p>
-      <p>
-        <span v-if="IS_MARKER">建议粗档位:</span>
-        <span v-else>申请粗档位:</span>
-        <span>{{ curPaperOrTask.redoLevel | levelNameFilter }}</span>
-      </p>
-    </div>
-    <div
-      :class="[
-        'action-grade-change-status',
-        { 'action-grade-change-status-error': curPaperOrTask.auditStatus === 0 }
-      ]"
-      v-if="rights.gradeChange && IS_ADMIN"
-    >
-      <p>{{ curPaperOrTask.auditStatus === 1 ? "同意改档" : "不同意改档" }}</p>
-    </div>
-
-    <!-- 大档位信息 -->
-    <!-- 已评/待评(已评档位),改大裆打小档(已评档位) -->
-    <div
-      class="action-grade-info"
-      v-if="rights.roughGradeInfo && curRoughLevel.name"
-    >
-      <h3 class="grade-info-name">
-        {{ curRoughLevel.name | levelNameFilter }}
-      </h3>
-      <div class="grade-info-range">
-        <p>档位范围</p>
-        <p>
-          <span>{{ curRoughLevel.minScore }}</span>
-          <span>~</span>
-          <span>{{ curRoughLevel.maxScore }}</span>
-        </p>
-      </div>
-    </div>
-
-    <!-- 小档位信息 -->
-    <!-- 已评(已评档位),打回(建议档位) -->
-    <h3
-      class="action-grade-info-title"
-      v-if="IS_MARKER && stepType === 'reject'"
-    >
-      <span>原细分档档位:{{ curPaperOrTask.originLevel || "" }}</span>
-      <span
-        v-if="
-          paramsSet.levelConfig &&
-            paramsSet.levelConfig.autoCallbackShowDeviation &&
-            curPaperOrTask.deviationDirection &&
-            curPaperOrTask.deviationDirection !== '0'
-        "
-        :class="[
-          'grade-info-deviation',
-          {
-            'grade-info-deviation-error':
-              curPaperOrTask.deviationDirection * 1 > 0
-          }
-        ]"
-        >{{ curPaperOrTask.deviationDirection * 1 > 0 ? "偏高" : "偏低" }}</span
-      >
-    </h3>
-    <h3
-      class="action-grade-info-title"
-      v-if="curPaperOrTask.rejected && curPaperOrTask.isRejectedByLeader"
-    >
-      建议细分档位:
-    </h3>
-    <div class="action-grade-info" v-if="rights.gradeInfo && curLevel.name">
-      <h3 class="grade-info-name">{{ curLevel.name }}</h3>
-      <div class="grade-info-range">
-        <p>分数范围</p>
-        <p>
-          <span>{{ curLevel.minScore }}</span>
-          <span>~</span>
-          <span>{{ curLevel.maxScore }}</span>
-        </p>
-      </div>
-    </div>
-    <!-- 小档位信息 -->
-    <div
-      class="action-grade-info action-mark-info"
-      v-if="rights.gradeInfo && !curLevel.name"
-    >
-      <p class="grade-info-name grade-info-none">未分档</p>
-    </div>
-
-    <!-- 选择小档位  -->
-    <div class="action-grade-list" v-if="rights.levelList">
-      <div
-        class="action-grade-item"
-        v-for="(level, index) in levelList"
-        :key="index"
-      >
-        <div
-          :class="[
-            'action-grade-item-content',
-            {
-              'action-item-content-disabled': btnClicked,
-              'is-active': keyInput == level.name
-            }
-          ]"
-          @click="selectLevel(level)"
-        >
-          <p>{{ level.name }}</p>
-          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
-        </div>
-      </div>
-    </div>
-    <!-- 选择大档位 -->
-    <h3
-      class="action-grade-info-title"
-      v-if="IS_MARK_LEADER && markLeaderOnlyRight && rights.roughLevelList"
-    >
-      当前操作:{{ markLeaderOnlyRight.name }}
-    </h3>
-    <div class="action-grade-list" v-if="rights.roughLevelList">
-      <div
-        class="action-grade-item"
-        v-for="(level, index) in roughLevelList"
-        :key="index"
-      >
-        <div
-          :class="[
-            'action-grade-item-content',
-            {
-              'action-item-content-disabled': btnClicked,
-              'is-active': keyInput == level.name
-            }
-          ]"
-          @click="selectRoughLevel(level)"
-        >
-          <p>{{ level.name | levelNameFilter }}</p>
-          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
-          <p v-if="level.minSubScore || level.maxSubScore">
-            {{ level.minSubScore }}~{{ level.maxSubScore }}
-          </p>
-        </div>
-      </div>
-    </div>
-    <div
-      v-if="
-        ribbonSet.keyboardMark && (rights.roughLevelList || rights.levelList)
-      "
-      class="action-grade-keyboard"
-    >
-      <div class="keyboard-input">{{ keyInput }}</div>
-      <div class="keyboard-clear" @click="clearKeyInput">
-        <Icon type="md-trash" />
-      </div>
-    </div>
-    <!-- 跳过:自测卷不允许跳过 -->
-    <div
-      class="action-grade-pass"
-      v-if="rights.gradePass && IS_MARKER && !curPaperOrTask.selfCheck"
-      @click="toPass"
-    >
-      跳过
-    </div>
-
-    <!-- marker confirm grade change -->
-    <div
-      class="action-grade-change-confirm"
-      v-if="IS_MARKER && rights.gradeChange"
-    >
-      <Button type="primary" @click="gradeChangeConfirm">确认改档</Button>
-    </div>
-
-    <!-- 评卷记录 -->
-    <div class="action-grade-history" v-if="rights.gradeHis">
-      <h3>评卷记录</h3>
-      <div class="grade-history-list">
-        <div
-          class="grade-history-item"
-          v-for="his in gradingHistory"
-          :key="his.id"
-        >
-          <p>{{ his.loginName }}</p>
-          <p>{{ his.value }}</p>
-        </div>
-      </div>
-    </div>
-
-    <!-- 查询 -->
-    <div class="action-search" v-if="rights.search">
-      <Select
-        class="search-select"
-        v-model="filter.codeType"
-        placeholder="密号类型"
-      >
-        <Option
-          v-for="item in codeTypes"
-          :key="item.key"
-          :value="item.key"
-          :label="item.val"
-        ></Option>
-      </Select>
-      <Input
-        class="search-input"
-        v-model.trim="filter.code"
-        placeholder="输入密号"
-        clearable
-      >
-      </Input>
-      <Button size="small" type="primary" class="search-btn" @click="searchCode"
-        >查询</Button
-      >
-    </div>
-  </div>
-</template>
-
-<script>
-import { markHistoryList, markTask } from "@/api";
-import { CODE_TYPE } from "@/constants/enumerate";
-import { mapState, mapMutations } from "vuex";
-import { levelNameTransform } from "@/plugins/utils";
-
-// 三种情况:
-// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
-
-// MARK_LEADER / ADMIN: curPaperOrTask => paper
-// MARKER: curPaperOrTask => task
-//
-/*
-[paper template]
-{
-  "id": 165,
-  "sn": "029947536",
-  "examNumber": "1901040084",
-  "level": "A",
-  "score": null,
-  "redoLevel": null,
-  "updatedOn": 1591767742000,
-  "imgSrc": "",
-  "thumbSrc": "",
-  "markByLeader": false,
-  "markedLogic": true,
-  "areaCode": "2",
-  "inspectScore": null,
-  "inspectLevel": null,
-  "inspector": null,
-  "sheetSrc": null,
-  "stage": "LEVEL",
-  "test": 0,
-  "paperTest": 0,
-  "markResults": [],
-  "rejected": false,
-  "arbitrated": false,
-  "sample": false,
-  "tagged": false,
-  "missing": false,
-  "manual": false
-}
-[marktask template]
-{
-  id: 58,
-  sn: "18111595446",
-  redoLevel: null,
-  level: null,
-  roughLevel: "5",
-  score: null,
-  result: null,
-  originLevel: "",
-  markerId: 16,
-  loginName: "sm1",
-  marker: "sm1",
-  updatedOn: null,
-  imgSrc: "",
-  thumbSrc: "",
-  markByLeader: false,
-  oldRejected: false,
-  paperId: 107,
-  randomSeqNew: 11595446,
-  randomSeq: null,
-  serialNumber: null,
-  displayNumber: false,
-  shift: false,
-  shiftScore: false,
-  isRejectedByLeader: false,
-  rejectedCount: 0,
-  dateMineResult: null,
-  deviationDirection: null,
-  sample: false,
-  rejected: false,
-  mark: false,
-  key: "i9k7nqr8s2kb60uo",
-  title: "NO.18111595446",
-  selected: false
-};
-*/
-
-const initRights = {
-  roughGradeInfo: false,
-  gradeInfo: false,
-  levelList: false,
-  roughLevelList: false,
-  gradePass: false,
-  gradeHis: false,
-  search: false
-};
-
-export default {
-  name: "grade-action-rough",
-  props: {
-    curPaperOrTask: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    levels: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    paramsSet: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    isBatchAction: {
-      type: Boolean,
-      default: false
-    },
-    // 是否处于粗分档
-    isRoughLevel: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      curPaperOrTaskLevel: "",
-      rights: {
-        ...initRights
-      },
-      cacheRights: null,
-      roleRight: {
-        ADMIN: {
-          done: ["roughGradeInfo", "gradeInfo", "gradeHis", "search"],
-          reject: ["roughGradeInfo", "gradeInfo", "gradeHis", "search"],
-          arbitrate: ["gradeHis", "search"],
-          shift: [
-            "roughGradeInfo",
-            "gradeInfo",
-            "search",
-            "gradeChangeSearch",
-            "gradeChange"
-          ]
-        },
-        MARK_LEADER: {
-          undo: ["roughGradeInfo", "gradeInfo", "levelList", "roughLevelList"],
-          done: [
-            "roughGradeInfo",
-            "gradeInfo",
-            "levelList",
-            "roughLevelList",
-            "gradeHis"
-          ],
-          reject: [
-            "roughGradeInfo",
-            "gradeInfo",
-            "levelList",
-            "roughLevelList",
-            "gradeHis"
-          ],
-          arbitrate: ["roughGradeInfo", "gradeInfo", "levelList", "gradeHis"],
-          shift: ["gradeChange", "roughLevelList"],
-          batch: ["levelList"]
-        },
-        MARKER: {
-          done: ["roughGradeInfo", "gradeInfo", "levelList"],
-          undo: ["roughGradeInfo", "gradeInfo", "levelList", "gradePass"],
-          reject: ["gradeInfo", "levelList", "gradePass"],
-          shift: ["gradeChange"],
-          shiftScore: ["roughGradeInfo", "gradeInfo", "levelList", "levelPass"],
-          batch: ["levelList"]
-        },
-        STANDARD: ["gradeInfo"]
-      },
-      filter: {
-        codeType: "examNumber",
-        code: ""
-      },
-      codeTypes: [],
-      stepDict: {
-        undo: "待评",
-        done: "已评",
-        reject: "打回",
-        arbitrate: "待仲裁",
-        shift: "改大档",
-        shiftScore: "改大档打小档",
-        sample: "标准卷",
-        batch: "批量操作"
-      },
-      stepType: "",
-      stepLabel: "",
-      gradingHistory: [],
-      levelList: [],
-      curLevel: {},
-      roughLevelList: [],
-      curRoughLevel: {},
-      setT: null,
-      btnClicked: false,
-      keyInput: null,
-      // 科组长权限
-      markLeaderOnlyRight: null,
-      // 标记
-      loading: false
-    };
-  },
-  computed: {
-    ...mapState("marker", ["ribbonSet", "shortcutKeyStatus", "curSubject"]),
-    IS_ADMIN() {
-      return this.curUserRoleType === "ADMIN";
-    },
-    IS_MARKER() {
-      return this.curUserRoleType === "MARKER";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    }
-  },
-  watch: {
-    curPaperOrTask() {
-      this.rebuildRight();
-    },
-    isBatchAction(val) {
-      if (val) {
-        this.stepType = "batch";
-        this.stepLabel = this.stepDict[this.stepType];
-        const roleRights =
-          this.roleRight[this.curUserRoleType][this.stepType] || [];
-        this.rights = { ...initRights };
-        roleRights.map(key => {
-          this.rights[key] = true;
-        });
-      } else {
-        this.rebuildRight();
-      }
-      this.keyInput = null;
-    },
-    "ribbonSet.keyboardMark": {
-      immediate: true,
-      handler(val) {
-        this.setShortcutStatus({ action: val });
-      }
-    },
-    "shortcutKeyStatus.action": {
-      immediate: true,
-      handler(val, oldval) {
-        // console.log(val, oldval);
-        if (val === oldval) return;
-        if (val) {
-          document.addEventListener("keydown", this.keyEvent);
-        } else {
-          document.removeEventListener("keydown", this.keyEvent);
-        }
-      }
-    }
-  },
-  mounted() {
-    this.markLeaderOnlyRight = this.$ls.get("user", {
-      markLeaderOnlyRight: null
-    }).markLeaderOnlyRight;
-
-    this.codeTypes = Object.entries(CODE_TYPE)
-      .map(([key, val]) => {
-        return {
-          key,
-          val
-        };
-      })
-      .filter(item => item.key !== "examNumber");
-    // .filter(item => this.IS_ADMIN || item.key !== "examNumber");
-    this.rebuildRight();
-  },
-  methods: {
-    ...mapMutations("marker", ["setShortcutStatus"]),
-    getStepType() {
-      const info = this.curPaperOrTask;
-      if (info.sample) return "sample";
-      if (info.shift && info.shiftScore && !info.level && !info.result)
-        return "shift";
-      if (!info.shift && info.shiftScore && !info.result) return "shiftScore";
-      if (this.curPaperOrTaskLevel) return "done";
-      if (info.arbitrated) return "arbitrate";
-      if (info.rejected) return "reject";
-      if (!info.rejected && !info.arbitrated && !info.level) return "undo";
-      return;
-    },
-    rebuildRight() {
-      if (this.setT) clearTimeout(this.setT);
-      this.curPaperOrTaskLevel =
-        this.curSubject.stage === "LEVEL"
-          ? this.curPaperOrTask.level
-          : this.curPaperOrTask.roughLevel || this.curPaperOrTask.level;
-
-      let roleRights = [];
-      this.stepType = this.getStepType();
-      this.stepLabel = this.stepDict[this.stepType];
-      if (this.stepType === "sample") {
-        roleRights = this.roleRight.STANDARD;
-      } else {
-        roleRights = this.roleRight[this.curUserRoleType][this.stepType] || [];
-      }
-      this.rights = { ...initRights };
-      roleRights.map(key => {
-        this.rights[key] = true;
-      });
-      this.initLevels();
-      if (this.rights.gradeHis) {
-        this.getMarkHistory();
-      }
-      this.btnClicked = false;
-      this.keyInput = null;
-    },
-    initLevels() {
-      this.levelList = this.levels.filter(
-        item => item.roughCode === this.curPaperOrTask.roughLevel
-      );
-      this.roughLevelList = this.parseRoughLevels(this.levels);
-      const curRoughLevel = this.roughLevelList.find(
-        item => item.name === this.curPaperOrTask.roughLevel
-      );
-      this.curRoughLevel = curRoughLevel || {};
-
-      const levelName = this.curPaperOrTask.rejected
-        ? this.curPaperOrTask.redoLevel
-        : this.curPaperOrTaskLevel;
-      if (levelName) {
-        this.curLevel =
-          this.levelList.find(item => item.name === levelName) || {};
-      } else {
-        this.curLevel = {};
-      }
-    },
-    parseRoughLevels(levelList) {
-      const levelMap = {};
-      levelList.forEach(item => {
-        const ind = item.roughCode;
-        if (!levelMap[ind]) levelMap[ind] = [];
-        levelMap[ind].push(item);
-      });
-      let roughLevelList = Object.keys(levelMap).map((roughCode, ind) => {
-        const group = levelMap[roughCode];
-        const levels = group.map(item => item.code);
-        const minSs = group.map(item => item.minScore);
-        const maxSs = group.map(item => item.maxScore);
-
-        return {
-          id: ind + 1,
-          name: roughCode,
-          minScore: levels[0],
-          maxScore: levels.slice(-1)[0],
-          minSubScore: Math.min.apply(null, minSs),
-          maxSubScore: Math.max.apply(null, maxSs)
-        };
-      });
-      roughLevelList.sort((a, b) => (a.name < b.name ? -1 : 1));
-      return roughLevelList;
-    },
-    async getMarkHistory() {
-      // 只有科组长和超管才会展示评卷记录
-      const data = await markHistoryList(
-        this.curPaperOrTask.id,
-        this.curSubject.stage
-      );
-      this.gradingHistory = data.map(item => {
-        let level = item.result || "未评";
-        if (this.stepType === "reject" && !item.result) {
-          level = `${levelNameTransform(level)}(${levelNameTransform(
-            item.originLevel
-          )})`;
-        }
-        return {
-          id: item.id,
-          markerId: item.markerId,
-          name: item.marker,
-          loginName: item.loginName,
-          value: level
-        };
-      });
-    },
-    selectLevel(level) {
-      if (this.isBatchAction) {
-        if (this.btnClicked) return;
-        this.btnClicked = true;
-        this.setT = setTimeout(() => {
-          this.btnClicked = false;
-        }, 500);
-        this.$emit("on-batch-level", level);
-        return;
-      }
-
-      if (this.IS_MARKER && this.curPaperOrTaskLevel === level.name) return;
-      if (this.btnClicked) return;
-      this.btnClicked = true;
-
-      if (this.IS_MARK_LEADER) {
-        this.setT = setTimeout(() => {
-          this.btnClicked = false;
-        }, 500);
-
-        this.$emit(
-          "on-leader-level",
-          {
-            paperIds: this.curPaperOrTask.id + "",
-            curLevel: this.curPaperOrTaskLevel,
-            selectedLevel: level.name,
-            markLeaderOnlyRight: this.markLeaderOnlyRight
-          },
-          this.gradingHistory.map(item => {
-            return {
-              id: item.markerId,
-              name: item.loginName
-            };
-          })
-        );
-        return;
-      }
-
-      this.$emit("on-select-level", level);
-    },
-    selectRoughLevel(level, actionType = null) {
-      if (this.curPaperOrTask.roughLevel === level.name && !actionType) return;
-
-      if (this.btnClicked) return;
-      this.btnClicked = true;
-
-      this.setT = setTimeout(() => {
-        this.btnClicked = false;
-      }, 500);
-      // 科组长改档 / 评卷同意改档:只使用selectedLevel
-      const curLevel =
-        this.stepType === "shift"
-          ? this.curPaperOrTask.redoLevel
-          : this.curPaperOrTask.roughLevel;
-      this.$emit("on-leader-change-level", {
-        paperId: this.curPaperOrTask.paperId,
-        curLevel,
-        selectedLevel: level.name
-      });
-    },
-    gradeChangeConfirm() {
-      this.selectRoughLevel(
-        {
-          name: this.curPaperOrTask.redoLevel
-        },
-        "gradeChangeConfirm"
-      );
-    },
-    toPass() {
-      this.$emit("on-pass");
-    },
-    searchCode() {
-      if (!this.filter.code || !this.filter.codeType) {
-        this.$Message.error("请设置密号类型和密号!");
-        return;
-      }
-      this.$emit("on-code-search", this.filter);
-    },
-    async toMark() {
-      if (this.loading) return;
-      this.loading = true;
-      let res = null;
-      res = await markTask({
-        markTaskId: this.curPaperOrTask.id,
-        isMark: !this.curPaperOrTask.mark,
-        stage: this.curSubject.stage
-      }).catch(() => {});
-
-      this.loading = false;
-      if (!res) return;
-      this.curPaperOrTask.mark = !this.curPaperOrTask.mark;
-      this.$emit("on-history-mark", this.curPaperOrTask.mark);
-    },
-    // keyboard submit
-    keyEvent(e) {
-      this.$Message.destroy();
-      if (this.btnClicked) return;
-      // if (!this.ribbonSet.keyboardMark) return;
-      if (!e.altKey && !e.shiftKey && !e.ctrlKey) {
-        if (e.key === "Enter" && this.ribbonSet.needEnterSubmit) {
-          e.preventDefault();
-          this.toKeySubmit();
-          return;
-        }
-        if (!/^[a-zA-Z0-9]$/.test(e.key)) return;
-
-        const keyInput = e.key.toUpperCase();
-        if (this.getKeyInputLevel(keyInput)) {
-          e.preventDefault();
-          this.keyInput = keyInput;
-
-          if (!this.ribbonSet.needEnterSubmit) {
-            this.toKeySubmit();
-          }
-        } else {
-          this.$Message.error("按键无效");
-        }
-      }
-    },
-    getKeyInputLevel(key) {
-      return (
-        (this.rights.levelList &&
-          this.levelList.find(item => item.name === key)) ||
-        (this.rights.roughLevelList &&
-          this.roughLevelList.find(item => item.name === key))
-      );
-    },
-    toKeySubmit() {
-      if (!this.keyInput) {
-        this.$Message.error("请选择档位");
-        return;
-      }
-      const level = this.getKeyInputLevel(this.keyInput);
-      if (/^[a-zA-Z]$/.test(level.name)) {
-        this.selectLevel(level);
-      } else {
-        this.selectRoughLevel(level);
-      }
-    },
-    clearKeyInput() {
-      this.keyInput = null;
-    }
-  },
-  beforeDestroy() {
-    if (this.setT) clearTimeout(this.setT);
-    document.removeEventListener("keydown", this.keyEvent);
-  }
-};
-</script>
+<template>
+  <div class="grade-action">
+    <div
+      v-if="IS_MARKER && curPaperOrTask.fontFrom === 'history'"
+      :class="['action-history-mark', { 'mark-act': curPaperOrTask.mark }]"
+      @click="toMark"
+    >
+      标记
+    </div>
+    <!-- 头部信息 ------ -->
+    <!-- 试卷状态 -->
+    <!-- 状态:已评,待评,打回,仲裁,改大裆,改大裆打小档 -->
+    <div class="action-paper-state" v-if="stepType === 'reject'">
+      <p class="paper-state-cont">
+        {{ curPaperOrTask.isRejectedByLeader ? "科组长打回" : "自动打回" }}
+      </p>
+      <p class="paper-state-intro">
+        <span v-if="curPaperOrTask.rejectedCount"
+          >共打回{{ curPaperOrTask.rejectedCount }}次</span
+        >
+      </p>
+    </div>
+    <div class="action-paper-state" v-else>
+      <p class="paper-state-cont">{{ stepLabel }}</p>
+    </div>
+    <!-- 试卷信息 -->
+    <div class="action-paper-info">
+      <p>
+        <span v-if="IS_MARKER">任务密号:</span>
+        <span v-else>试卷密号:</span>
+        <span v-if="curPaperOrTask.sn && !isBatchAction">
+          NO.{{ curPaperOrTask.sn }}
+        </span>
+        <span v-else>--</span>
+      </p>
+    </div>
+    <!-- 改档信息 -->
+    <div class="action-grade-change" v-if="rights.gradeChange">
+      <p>
+        <span>原始粗档位:</span
+        ><span>{{ curPaperOrTask.originLevel | levelNameFilter }}</span>
+      </p>
+      <p>
+        <span v-if="IS_MARKER">建议粗档位:</span>
+        <span v-else>申请粗档位:</span>
+        <span>{{ curPaperOrTask.redoLevel | levelNameFilter }}</span>
+      </p>
+    </div>
+    <div
+      :class="[
+        'action-grade-change-status',
+        {
+          'action-grade-change-status-error': curPaperOrTask.auditStatus === 0,
+        },
+      ]"
+      v-if="rights.gradeChange && IS_ADMIN"
+    >
+      <p>{{ curPaperOrTask.auditStatus === 1 ? "同意改档" : "不同意改档" }}</p>
+    </div>
+
+    <!-- 大档位信息 -->
+    <!-- 已评/待评(已评档位),改大裆打小档(已评档位) -->
+    <div
+      class="action-grade-info"
+      v-if="rights.roughGradeInfo && curRoughLevel.name"
+    >
+      <h3 class="grade-info-name">
+        {{ curRoughLevel.name | levelNameFilter }}
+      </h3>
+      <div class="grade-info-range">
+        <p>档位范围</p>
+        <p>
+          <span>{{ curRoughLevel.minScore }}</span>
+          <span>~</span>
+          <span>{{ curRoughLevel.maxScore }}</span>
+        </p>
+      </div>
+    </div>
+
+    <!-- 小档位信息 -->
+    <!-- 已评(已评档位),打回(建议档位) -->
+    <h3
+      class="action-grade-info-title"
+      v-if="IS_MARKER && stepType === 'reject'"
+    >
+      <span>原细分档档位:{{ curPaperOrTask.originLevel || "" }}</span>
+      <span
+        v-if="
+          paramsSet.levelConfig &&
+          paramsSet.levelConfig.autoCallbackShowDeviation &&
+          curPaperOrTask.deviationDirection &&
+          curPaperOrTask.deviationDirection !== '0'
+        "
+        :class="[
+          'grade-info-deviation',
+          {
+            'grade-info-deviation-error':
+              curPaperOrTask.deviationDirection * 1 > 0,
+          },
+        ]"
+        >{{ curPaperOrTask.deviationDirection * 1 > 0 ? "偏高" : "偏低" }}</span
+      >
+    </h3>
+    <h3
+      class="action-grade-info-title"
+      v-if="curPaperOrTask.rejected && curPaperOrTask.isRejectedByLeader"
+    >
+      建议细分档位:
+    </h3>
+    <div class="action-grade-info" v-if="rights.gradeInfo && curLevel.name">
+      <h3 class="grade-info-name">{{ curLevel.name }}</h3>
+      <div class="grade-info-range">
+        <p>分数范围</p>
+        <p>
+          <span>{{ curLevel.minScore }}</span>
+          <span>~</span>
+          <span>{{ curLevel.maxScore }}</span>
+        </p>
+      </div>
+    </div>
+    <!-- 小档位信息 -->
+    <div
+      class="action-grade-info action-mark-info"
+      v-if="rights.gradeInfo && !curLevel.name"
+    >
+      <p class="grade-info-name grade-info-none">未分档</p>
+    </div>
+
+    <!-- 选择小档位  -->
+    <div class="action-grade-list" v-if="rights.levelList">
+      <div
+        class="action-grade-item"
+        v-for="(level, index) in levelList"
+        :key="index"
+      >
+        <div
+          :class="[
+            'action-grade-item-content',
+            {
+              'action-item-content-disabled': btnClicked,
+              'is-active': keyInput == level.name,
+            },
+          ]"
+          @click="selectLevel(level)"
+        >
+          <p>{{ level.name }}</p>
+          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
+        </div>
+      </div>
+    </div>
+    <!-- 选择大档位 -->
+    <h3
+      class="action-grade-info-title"
+      v-if="IS_MARK_LEADER && markLeaderOnlyRight && rights.roughLevelList"
+    >
+      当前操作:{{ markLeaderOnlyRight.name }}
+    </h3>
+    <div class="action-grade-list" v-if="rights.roughLevelList">
+      <div
+        class="action-grade-item"
+        v-for="(level, index) in roughLevelList"
+        :key="index"
+      >
+        <div
+          :class="[
+            'action-grade-item-content',
+            {
+              'action-item-content-disabled': btnClicked,
+              'is-active': keyInput == level.name,
+            },
+          ]"
+          @click="selectRoughLevel(level)"
+        >
+          <p>{{ level.name | levelNameFilter }}</p>
+          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
+          <p v-if="level.minSubScore || level.maxSubScore">
+            {{ level.minSubScore }}~{{ level.maxSubScore }}
+          </p>
+        </div>
+      </div>
+    </div>
+    <div
+      v-if="
+        ribbonSet.keyboardMark && (rights.roughLevelList || rights.levelList)
+      "
+      class="action-grade-keyboard"
+    >
+      <div class="keyboard-input">{{ keyInput }}</div>
+      <div class="keyboard-clear" @click="clearKeyInput">
+        <Icon type="md-trash" />
+      </div>
+    </div>
+    <!-- 跳过:自测卷不允许跳过 -->
+    <div
+      class="action-grade-pass"
+      v-if="rights.gradePass && IS_MARKER && !curPaperOrTask.selfCheck"
+      @click="toPass"
+    >
+      跳过
+    </div>
+
+    <!-- marker confirm grade change -->
+    <div
+      class="action-grade-change-confirm"
+      v-if="IS_MARKER && rights.gradeChange"
+    >
+      <Button type="primary" @click="gradeChangeConfirm">确认改档</Button>
+    </div>
+
+    <!-- 评卷记录 -->
+    <div class="action-grade-history" v-if="rights.gradeHis">
+      <h3>评卷记录</h3>
+      <div class="grade-history-list">
+        <div
+          class="grade-history-item"
+          v-for="his in gradingHistory"
+          :key="his.id"
+        >
+          <p>{{ his.loginName }}</p>
+          <p>{{ his.value }}</p>
+        </div>
+      </div>
+    </div>
+
+    <!-- 查询 -->
+    <div class="action-search" v-if="rights.search">
+      <Select
+        class="search-select"
+        v-model="filter.codeType"
+        placeholder="密号类型"
+      >
+        <Option
+          v-for="item in codeTypes"
+          :key="item.key"
+          :value="item.key"
+          :label="item.val"
+        ></Option>
+      </Select>
+      <Input
+        class="search-input"
+        v-model.trim="filter.code"
+        placeholder="输入密号"
+        clearable
+      >
+      </Input>
+      <Button size="small" type="primary" class="search-btn" @click="searchCode"
+        >查询</Button
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+import { markHistoryList, markTask } from "@/api";
+import { CODE_TYPE } from "@/constants/enumerate";
+import { mapState, mapMutations } from "vuex";
+import { levelNameTransform } from "@/plugins/utils";
+
+// 三种情况:
+// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
+
+// MARK_LEADER / ADMIN: curPaperOrTask => paper
+// MARKER: curPaperOrTask => task
+//
+/*
+[paper template]
+{
+  "id": 165,
+  "sn": "029947536",
+  "examNumber": "1901040084",
+  "level": "A",
+  "score": null,
+  "redoLevel": null,
+  "updatedOn": 1591767742000,
+  "imgSrc": "",
+  "thumbSrc": "",
+  "markByLeader": false,
+  "markedLogic": true,
+  "areaCode": "2",
+  "inspectScore": null,
+  "inspectLevel": null,
+  "inspector": null,
+  "sheetSrc": null,
+  "stage": "LEVEL",
+  "test": 0,
+  "paperTest": 0,
+  "markResults": [],
+  "rejected": false,
+  "arbitrated": false,
+  "sample": false,
+  "tagged": false,
+  "missing": false,
+  "manual": false
+}
+[marktask template]
+{
+  id: 58,
+  sn: "18111595446",
+  redoLevel: null,
+  level: null,
+  roughLevel: "5",
+  score: null,
+  result: null,
+  originLevel: "",
+  markerId: 16,
+  loginName: "sm1",
+  marker: "sm1",
+  updatedOn: null,
+  imgSrc: "",
+  thumbSrc: "",
+  markByLeader: false,
+  oldRejected: false,
+  paperId: 107,
+  randomSeqNew: 11595446,
+  randomSeq: null,
+  serialNumber: null,
+  displayNumber: false,
+  shift: false,
+  shiftScore: false,
+  isRejectedByLeader: false,
+  rejectedCount: 0,
+  dateMineResult: null,
+  deviationDirection: null,
+  sample: false,
+  rejected: false,
+  mark: false,
+  key: "i9k7nqr8s2kb60uo",
+  title: "NO.18111595446",
+  selected: false
+};
+*/
+
+const initRights = {
+  roughGradeInfo: false,
+  gradeInfo: false,
+  levelList: false,
+  roughLevelList: false,
+  gradePass: false,
+  gradeHis: false,
+  search: false,
+};
+
+export default {
+  name: "grade-action-rough",
+  props: {
+    curPaperOrTask: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    levels: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    paramsSet: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    isBatchAction: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否处于粗分档
+    isRoughLevel: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      curPaperOrTaskLevel: "",
+      rights: {
+        ...initRights,
+      },
+      cacheRights: null,
+      roleRight: {
+        ADMIN: {
+          done: ["roughGradeInfo", "gradeInfo", "gradeHis", "search"],
+          reject: ["roughGradeInfo", "gradeInfo", "gradeHis", "search"],
+          arbitrate: ["gradeHis", "search"],
+          shift: [
+            "roughGradeInfo",
+            "gradeInfo",
+            "search",
+            "gradeChangeSearch",
+            "gradeChange",
+          ],
+        },
+        MARK_LEADER: {
+          undo: ["roughGradeInfo", "gradeInfo", "levelList", "roughLevelList"],
+          done: [
+            "roughGradeInfo",
+            "gradeInfo",
+            "levelList",
+            "roughLevelList",
+            "gradeHis",
+          ],
+          reject: [
+            "roughGradeInfo",
+            "gradeInfo",
+            "levelList",
+            "roughLevelList",
+            "gradeHis",
+          ],
+          arbitrate: ["roughGradeInfo", "gradeInfo", "levelList", "gradeHis"],
+          shift: ["gradeChange", "roughLevelList"],
+          batch: ["levelList"],
+        },
+        MARKER: {
+          done: ["roughGradeInfo", "gradeInfo", "levelList"],
+          undo: ["roughGradeInfo", "gradeInfo", "levelList", "gradePass"],
+          reject: ["gradeInfo", "levelList", "gradePass"],
+          shift: ["gradeChange"],
+          shiftScore: ["roughGradeInfo", "gradeInfo", "levelList", "levelPass"],
+          batch: ["levelList"],
+        },
+        STANDARD: ["gradeInfo"],
+      },
+      filter: {
+        codeType: "examNumber",
+        code: "",
+      },
+      codeTypes: [],
+      stepDict: {
+        undo: "待评",
+        done: "已评",
+        reject: "打回",
+        arbitrate: "待仲裁",
+        shift: "改大档",
+        shiftScore: "改大档打小档",
+        sample: "标准卷",
+        batch: "批量操作",
+      },
+      stepType: "",
+      stepLabel: "",
+      gradingHistory: [],
+      levelList: [],
+      curLevel: {},
+      roughLevelList: [],
+      curRoughLevel: {},
+      setT: null,
+      btnClicked: false,
+      keyInput: null,
+      // 科组长权限
+      markLeaderOnlyRight: null,
+      // 标记
+      loading: false,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["ribbonSet", "shortcutKeyStatus", "curSubject"]),
+    IS_ADMIN() {
+      return this.curUserRoleType === "ADMIN";
+    },
+    IS_MARKER() {
+      return this.curUserRoleType === "MARKER";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    },
+  },
+  watch: {
+    curPaperOrTask() {
+      this.rebuildRight();
+    },
+    isBatchAction(val) {
+      if (val) {
+        this.stepType = "batch";
+        this.stepLabel = this.stepDict[this.stepType];
+        const roleRights =
+          this.roleRight[this.curUserRoleType][this.stepType] || [];
+        this.rights = { ...initRights };
+        roleRights.map((key) => {
+          this.rights[key] = true;
+        });
+      } else {
+        this.rebuildRight();
+      }
+      this.keyInput = null;
+    },
+    "ribbonSet.keyboardMark": {
+      immediate: true,
+      handler(val) {
+        this.setShortcutStatus({ action: val });
+      },
+    },
+    "shortcutKeyStatus.action": {
+      immediate: true,
+      handler(val, oldval) {
+        // console.log(val, oldval);
+        if (val === oldval) return;
+        if (val) {
+          document.addEventListener("keydown", this.keyEvent);
+        } else {
+          document.removeEventListener("keydown", this.keyEvent);
+        }
+      },
+    },
+  },
+  mounted() {
+    this.markLeaderOnlyRight = this.$ls.get("user", {
+      markLeaderOnlyRight: null,
+    }).markLeaderOnlyRight;
+
+    this.codeTypes = Object.entries(CODE_TYPE)
+      .map(([key, val]) => {
+        return {
+          key,
+          val,
+        };
+      })
+      .filter((item) => item.key !== "examNumber");
+    // .filter(item => this.IS_ADMIN || item.key !== "examNumber");
+    this.rebuildRight();
+  },
+  methods: {
+    ...mapMutations("marker", ["setShortcutStatus"]),
+    getStepType() {
+      const info = this.curPaperOrTask;
+      if (info.sample) return "sample";
+      if (info.shift && info.shiftScore && !info.level && !info.result)
+        return "shift";
+      if (!info.shift && info.shiftScore && !info.result) return "shiftScore";
+      if (this.curPaperOrTaskLevel) return "done";
+      if (info.arbitrated) return "arbitrate";
+      if (info.rejected) return "reject";
+      if (!info.rejected && !info.arbitrated && !info.level) return "undo";
+      return;
+    },
+    rebuildRight() {
+      if (this.setT) clearTimeout(this.setT);
+      this.curPaperOrTaskLevel =
+        this.curSubject.stage === "LEVEL"
+          ? this.curPaperOrTask.level
+          : this.curPaperOrTask.roughLevel || this.curPaperOrTask.level;
+
+      let roleRights = [];
+      this.stepType = this.getStepType();
+      this.stepLabel = this.stepDict[this.stepType];
+      if (this.stepType === "sample") {
+        roleRights = this.roleRight.STANDARD;
+      } else {
+        roleRights = this.roleRight[this.curUserRoleType][this.stepType] || [];
+      }
+      this.rights = { ...initRights };
+      roleRights.map((key) => {
+        this.rights[key] = true;
+      });
+      this.initLevels();
+      if (this.rights.gradeHis) {
+        this.getMarkHistory();
+      }
+      this.btnClicked = false;
+      this.keyInput = null;
+    },
+    initLevels() {
+      this.levelList = this.levels.filter(
+        (item) => item.roughCode === this.curPaperOrTask.roughLevel
+      );
+      this.roughLevelList = this.parseRoughLevels(this.levels);
+      const curRoughLevel = this.roughLevelList.find(
+        (item) => item.name === this.curPaperOrTask.roughLevel
+      );
+      this.curRoughLevel = curRoughLevel || {};
+
+      const levelName = this.curPaperOrTask.rejected
+        ? this.curPaperOrTask.redoLevel
+        : this.curPaperOrTaskLevel;
+      if (levelName) {
+        this.curLevel =
+          this.levelList.find((item) => item.name === levelName) || {};
+      } else {
+        this.curLevel = {};
+      }
+    },
+    parseRoughLevels(levelList) {
+      const levelMap = {};
+      levelList.forEach((item) => {
+        const ind = item.roughCode;
+        if (!levelMap[ind]) levelMap[ind] = [];
+        levelMap[ind].push(item);
+      });
+      let roughLevelList = Object.keys(levelMap).map((roughCode, ind) => {
+        const group = levelMap[roughCode];
+        const levels = group.map((item) => item.code);
+        const minSs = group.map((item) => item.minScore);
+        const maxSs = group.map((item) => item.maxScore);
+
+        return {
+          id: ind + 1,
+          name: roughCode,
+          minScore: levels[0],
+          maxScore: levels.slice(-1)[0],
+          minSubScore: Math.min.apply(null, minSs),
+          maxSubScore: Math.max.apply(null, maxSs),
+        };
+      });
+      roughLevelList.sort((a, b) => (a.name < b.name ? -1 : 1));
+      return roughLevelList;
+    },
+    async getMarkHistory() {
+      // 只有科组长和超管才会展示评卷记录
+      const data = await markHistoryList(
+        this.curPaperOrTask.id,
+        this.curSubject.stage
+      );
+      this.gradingHistory = data.map((item) => {
+        let level = item.result || "未评";
+        if (this.stepType === "reject" && !item.result) {
+          level = `${levelNameTransform(level)}(${levelNameTransform(
+            item.originLevel
+          )})`;
+        }
+        return {
+          id: item.id,
+          markerId: item.markerId,
+          name: item.marker,
+          loginName: item.loginName,
+          value: level,
+        };
+      });
+    },
+    selectLevel(level) {
+      if (this.isBatchAction) {
+        if (this.btnClicked) return;
+        this.btnClicked = true;
+        this.setT = setTimeout(() => {
+          this.btnClicked = false;
+        }, 500);
+        this.$emit("on-batch-level", level);
+        return;
+      }
+
+      if (this.IS_MARKER && this.curPaperOrTaskLevel === level.name) return;
+      if (this.btnClicked) return;
+      this.btnClicked = true;
+
+      if (this.IS_MARK_LEADER) {
+        this.setT = setTimeout(() => {
+          this.btnClicked = false;
+        }, 500);
+
+        this.$emit(
+          "on-leader-level",
+          {
+            paperIds: this.curPaperOrTask.id + "",
+            curLevel: this.curPaperOrTaskLevel,
+            selectedLevel: level.name,
+            markLeaderOnlyRight: this.markLeaderOnlyRight,
+          },
+          this.gradingHistory.map((item) => {
+            return {
+              id: item.markerId,
+              name: item.loginName,
+            };
+          })
+        );
+        return;
+      }
+
+      this.$emit("on-select-level", level);
+    },
+    selectRoughLevel(level, actionType = null) {
+      if (this.curPaperOrTask.roughLevel === level.name && !actionType) return;
+
+      if (this.btnClicked) return;
+      this.btnClicked = true;
+
+      this.setT = setTimeout(() => {
+        this.btnClicked = false;
+      }, 500);
+      // 科组长改档 / 评卷同意改档:只使用selectedLevel
+      const curLevel =
+        this.stepType === "shift"
+          ? this.curPaperOrTask.redoLevel
+          : this.curPaperOrTask.roughLevel;
+      this.$emit("on-leader-change-level", {
+        paperId: this.curPaperOrTask.paperId,
+        curLevel,
+        selectedLevel: level.name,
+      });
+    },
+    gradeChangeConfirm() {
+      this.selectRoughLevel(
+        {
+          name: this.curPaperOrTask.redoLevel,
+        },
+        "gradeChangeConfirm"
+      );
+    },
+    toPass() {
+      this.$emit("on-pass");
+    },
+    searchCode() {
+      if (!this.filter.code || !this.filter.codeType) {
+        this.$Message.error("请设置密号类型和密号!");
+        return;
+      }
+      this.$emit("on-code-search", this.filter);
+    },
+    async toMark() {
+      if (this.loading) return;
+      this.loading = true;
+      let res = null;
+      res = await markTask({
+        markTaskId: this.curPaperOrTask.id,
+        isMark: !this.curPaperOrTask.mark,
+        stage: this.curSubject.stage,
+      }).catch(() => {});
+
+      this.loading = false;
+      if (!res) return;
+      this.curPaperOrTask.mark = !this.curPaperOrTask.mark;
+      this.$emit("on-history-mark", this.curPaperOrTask.mark);
+    },
+    // keyboard submit
+    keyEvent(e) {
+      this.$Message.destroy();
+      if (this.btnClicked) return;
+      // if (!this.ribbonSet.keyboardMark) return;
+      if (!e.altKey && !e.shiftKey && !e.ctrlKey) {
+        if (e.key === "Enter" && this.ribbonSet.needEnterSubmit) {
+          e.preventDefault();
+          this.toKeySubmit();
+          return;
+        }
+        if (!/^[a-zA-Z0-9]$/.test(e.key)) return;
+
+        const keyInput = e.key.toUpperCase();
+        if (this.getKeyInputLevel(keyInput)) {
+          e.preventDefault();
+          this.keyInput = keyInput;
+
+          if (!this.ribbonSet.needEnterSubmit) {
+            this.toKeySubmit();
+          }
+        } else {
+          this.$Message.error("按键无效");
+        }
+      }
+    },
+    getKeyInputLevel(key) {
+      return (
+        (this.rights.levelList &&
+          this.levelList.find((item) => item.name === key)) ||
+        (this.rights.roughLevelList &&
+          this.roughLevelList.find((item) => item.name === key))
+      );
+    },
+    toKeySubmit() {
+      if (!this.keyInput) {
+        this.$Message.error("请选择档位");
+        return;
+      }
+      const level = this.getKeyInputLevel(this.keyInput);
+      if (/^[a-zA-Z]$/.test(level.name)) {
+        this.selectLevel(level);
+      } else {
+        this.selectRoughLevel(level);
+      }
+    },
+    clearKeyInput() {
+      this.keyInput = null;
+    },
+  },
+  beforeDestroy() {
+    if (this.setT) clearTimeout(this.setT);
+    document.removeEventListener("keydown", this.keyEvent);
+  },
+};
+</script>

+ 20 - 20
src/modules/grading/components/GradeAnalysis.vue

@@ -28,12 +28,12 @@ export default {
   props: {
   props: {
     questionId: {
     questionId: {
       type: Number,
       type: Number,
-      required: true
+      required: true,
     },
     },
     subjectId: {
     subjectId: {
       type: String,
       type: String,
-      required: true
-    }
+      required: true,
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -42,59 +42,59 @@ export default {
       columns: [
       columns: [
         {
         {
           title: "科目",
           title: "科目",
-          key: "subjectName"
+          key: "subjectName",
         },
         },
         {
         {
           title: "档位",
           title: "档位",
-          key: "code"
+          key: "code",
         },
         },
         {
         {
           title: "范围",
           title: "范围",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", `${param.row.minScore}~${param.row.maxScore}`);
             return h("div", `${param.row.minScore}~${param.row.maxScore}`);
-          }
+          },
         },
         },
         {
         {
           title: "数量",
           title: "数量",
-          key: "levelCount"
+          key: "levelCount",
         },
         },
         {
         {
           title: "占比",
           title: "占比",
           key: "levelProp",
           key: "levelProp",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", `${param.row.levelProp}%`);
             return h("div", `${param.row.levelProp}%`);
-          }
+          },
         },
         },
         {
         {
           title: "预设占比",
           title: "预设占比",
           key: "examLevelProp",
           key: "examLevelProp",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", `${param.row.examLevelProp}%`);
             return h("div", `${param.row.examLevelProp}%`);
-          }
+          },
         },
         },
         {
         {
           title: "差值",
           title: "差值",
           key: "diffProp",
           key: "diffProp",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", `${param.row.diffProp}%`);
             return h("div", `${param.row.diffProp}%`);
-          }
+          },
         },
         },
         {
         {
           title: "累计数量",
           title: "累计数量",
-          key: "cumulateCount"
+          key: "cumulateCount",
         },
         },
         {
         {
           title: "累计占比",
           title: "累计占比",
           key: "cumulateProp",
           key: "cumulateProp",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", `${param.row.cumulateProp}%`);
             return h("div", `${param.row.cumulateProp}%`);
-          }
+          },
         },
         },
         {
         {
           title: "调整",
           title: "调整",
-          key: "adjustmentCount"
-        }
-      ]
+          key: "adjustmentCount",
+        },
+      ],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -107,13 +107,13 @@ export default {
       this.levelData = await gradingStatData({
       this.levelData = await gradingStatData({
         questionId: this.questionId,
         questionId: this.questionId,
         workId: subs[0],
         workId: subs[0],
-        subject: subs[1]
+        subject: subs[1],
       });
       });
 
 
-      this.lineChartData = this.levelData.map(item => {
+      this.lineChartData = this.levelData.map((item) => {
         return {
         return {
           name: item.code,
           name: item.code,
-          value: item.levelProp
+          value: item.levelProp,
         };
         };
       });
       });
     },
     },
@@ -124,7 +124,7 @@ export default {
         return { rowspan: 0, colspan: 0 };
         return { rowspan: 0, colspan: 0 };
       }
       }
     },
     },
-    toExport() {}
-  }
+    toExport() {},
+  },
 };
 };
 </script>
 </script>

+ 11 - 13
src/modules/grading/components/GradeAnalysisExport.vue

@@ -1,9 +1,7 @@
 <template>
 <template>
   <div class="grade-analysis-export analysis-export-modal">
   <div class="grade-analysis-export analysis-export-modal">
     <div class="print-box">
     <div class="print-box">
-      <h1>
-        分档详情数据
-      </h1>
+      <h1>分档详情数据</h1>
       <div class="quality-info">
       <div class="quality-info">
         <p>科目:{{ pageInfo.subjectName }}</p>
         <p>科目:{{ pageInfo.subjectName }}</p>
         <p>考区:{{ pageInfo.areaName }}</p>
         <p>考区:{{ pageInfo.areaName }}</p>
@@ -68,25 +66,25 @@ export default {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
+      },
     },
     },
     pageInfo: {
     pageInfo: {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
-    }
+      },
+    },
   },
   },
   data() {
   data() {
     return {
     return {
       currentTime: formatDate(),
       currentTime: formatDate(),
-      showImg: false
+      showImg: false,
     };
     };
   },
   },
   mounted() {
   mounted() {
     this.$nextTick(() => {
     this.$nextTick(() => {
       this.$refs.lineChartImg.src = this.$refs.lineChart.getDataURL({
       this.$refs.lineChartImg.src = this.$refs.lineChart.getDataURL({
-        backgroundColor: "#fff"
+        backgroundColor: "#fff",
       });
       });
 
 
       this.showImg = true;
       this.showImg = true;
@@ -98,7 +96,7 @@ export default {
   methods: {
   methods: {
     async toExport() {
     async toExport() {
       const canvas = await html2canvas(this.$el.childNodes[0], {
       const canvas = await html2canvas(this.$el.childNodes[0], {
-        allowTaint: true
+        allowTaint: true,
       }).catch(() => {});
       }).catch(() => {});
 
 
       if (!canvas) {
       if (!canvas) {
@@ -113,15 +111,15 @@ export default {
         url: `${this.GLOBAL.domain}/api/exportPdf`,
         url: `${this.GLOBAL.domain}/api/exportPdf`,
         header: { Authorization: user.token, userId: user.id },
         header: { Authorization: user.token, userId: user.id },
         data: {
         data: {
-          content: [canvas.toDataURL().split(",")[1]]
+          content: [canvas.toDataURL().split(",")[1]],
         },
         },
-        fileName: `${this.pageInfo.subjectName}-${this.pageInfo.areaName}-分档详情分析.pdf`
+        fileName: `${this.pageInfo.subjectName}-${this.pageInfo.areaName}-分档详情分析.pdf`,
       }).catch(() => {
       }).catch(() => {
         result = false;
         result = false;
       });
       });
 
 
       this.$emit("on-exported", result);
       this.$emit("on-exported", result);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 10 - 10
src/modules/grading/components/GradeFilter.vue

@@ -44,17 +44,17 @@ export default {
       default() {
       default() {
         return {
         return {
           workId: "",
           workId: "",
-          subject: ""
+          subject: "",
         };
         };
-      }
-    }
+      },
+    },
   },
   },
   data() {
   data() {
     return {
     return {
       questionId: "",
       questionId: "",
       areas: [],
       areas: [],
       curArea: {},
       curArea: {},
-      selectIsShow: false
+      selectIsShow: false,
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -64,13 +64,13 @@ export default {
     async getAreaList() {
     async getAreaList() {
       const data = await areaList({
       const data = await areaList({
         workId: this.data.workId,
         workId: this.data.workId,
-        subject: this.data.subject
+        subject: this.data.subject,
       });
       });
-      this.areas = data.map(item => {
+      this.areas = data.map((item) => {
         return {
         return {
           id: item.id,
           id: item.id,
           areaName: item.areaName,
           areaName: item.areaName,
-          areaCode: item.areaCode
+          areaCode: item.areaCode,
         };
         };
       });
       });
 
 
@@ -81,14 +81,14 @@ export default {
       }
       }
     },
     },
     confrim() {
     confrim() {
-      const curArea = this.areas.find(item => item.id === this.questionId);
+      const curArea = this.areas.find((item) => item.id === this.questionId);
       this.curArea = curArea;
       this.curArea = curArea;
       this.selectIsShow = false;
       this.selectIsShow = false;
       this.$emit("change", this.curArea);
       this.$emit("change", this.curArea);
     },
     },
     cancel() {
     cancel() {
       this.selectIsShow = false;
       this.selectIsShow = false;
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 12 - 12
src/modules/grading/components/GradeHistoryPaper.vue

@@ -30,12 +30,12 @@ export default {
   components: { PaperCarousel },
   components: { PaperCarousel },
   props: {
   props: {
     questionId: {
     questionId: {
-      type: Number
+      type: Number,
     },
     },
     stage: {
     stage: {
       type: String,
       type: String,
-      default: "LEVEL"
-    }
+      default: "LEVEL",
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -45,7 +45,7 @@ export default {
       userId: "",
       userId: "",
       curPaper: {},
       curPaper: {},
       papers: [],
       papers: [],
-      IS_MARK_LEADER: false
+      IS_MARK_LEADER: false,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -54,13 +54,13 @@ export default {
         return this.curPaper.level ? `一键定档  ${this.curPaper.level}` : "";
         return this.curPaper.level ? `一键定档  ${this.curPaper.level}` : "";
       return this.curPaper.result ? `已评  ${this.curPaper.result}` : "";
       return this.curPaper.result ? `已评  ${this.curPaper.result}` : "";
       // return this.curPaper.sn ? `NO.${this.curPaper.sn}` : "";
       // return this.curPaper.sn ? `NO.${this.curPaper.sn}` : "";
-    }
+    },
   },
   },
   watch: {
   watch: {
     questionId(val) {
     questionId(val) {
       this.papers = [];
       this.papers = [];
       this.updatePapers();
       this.updatePapers();
-    }
+    },
   },
   },
   mounted() {
   mounted() {
     this.userId = this.$ls.get("user", { id: "" }).id;
     this.userId = this.$ls.get("user", { id: "" }).id;
@@ -78,7 +78,7 @@ export default {
         const datas = {
         const datas = {
           workId: this.workId,
           workId: this.workId,
           subject: this.subject,
           subject: this.subject,
-          questionId: this.questionId
+          questionId: this.questionId,
         };
         };
 
 
         data = await actionLeaderHistory(datas);
         data = await actionLeaderHistory(datas);
@@ -86,7 +86,7 @@ export default {
         const datas = {
         const datas = {
           markerId: this.userId,
           markerId: this.userId,
           stage: this.stage,
           stage: this.stage,
-          questionId: this.questionId
+          questionId: this.questionId,
         };
         };
 
 
         data = await actionHistory(datas);
         data = await actionHistory(datas);
@@ -98,9 +98,9 @@ export default {
       });
       });
     },
     },
     updateCachePapers(papers) {
     updateCachePapers(papers) {
-      papers.forEach(paper => {
+      papers.forEach((paper) => {
         const paperIndex = this.papers.findIndex(
         const paperIndex = this.papers.findIndex(
-          item => item.paperId === paper.paperId
+          (item) => item.paperId === paper.paperId
         );
         );
         if (paperIndex !== -1) {
         if (paperIndex !== -1) {
           this.papers.splice(paperIndex, 1);
           this.papers.splice(paperIndex, 1);
@@ -118,7 +118,7 @@ export default {
     },
     },
     paperClick(paperIndex, papers) {
     paperClick(paperIndex, papers) {
       this.$emit("on-paper-click", paperIndex, papers);
       this.$emit("on-paper-click", paperIndex, papers);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 4 - 6
src/modules/grading/components/GradeImageList.vue

@@ -1,7 +1,5 @@
 <template>
 <template>
-  <div class="grade-image-list">
-    grade-image-list
-  </div>
+  <div class="grade-image-list">grade-image-list</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -11,13 +9,13 @@ export default {
     return {
     return {
       filter: {
       filter: {
         workId: this.$route.params.workId,
         workId: this.$route.params.workId,
-        subjectId: this.$route.params.subjectId
+        subjectId: this.$route.params.subjectId,
       },
       },
       current: 1,
       current: 1,
       size: 6,
       size: 6,
-      total: 0
+      total: 0,
     };
     };
   },
   },
-  methods: {}
+  methods: {},
 };
 };
 </script>
 </script>

+ 47 - 47
src/modules/grading/components/GradeRibbon.vue

@@ -1,47 +1,47 @@
-<template>
-  <div class="grade-ribbon">
-    <div class="ribbon-list">
-      <div class="ribbon-item" title="刷新" @click="toFresh">
-        <Icon type="md-refresh" />
-      </div>
-      <div class="ribbon-item" title="消息" @click="toNotice">
-        <Icon type="md-notifications" />
-      </div>
-      <div class="ribbon-item" title="设置" @click="toSet">
-        <Icon type="md-settings" />
-      </div>
-    </div>
-
-    <!-- RibbonSetDialog -->
-    <ribbon-set-dialog ref="RibbonSetDialog"></ribbon-set-dialog>
-    <!-- NoticeDialog -->
-    <notice-dialog ref="NoticeDialog"></notice-dialog>
-  </div>
-</template>
-
-<script>
-import RibbonSetDialog from "./RibbonSetDialog";
-import NoticeDialog from "./NoticeDialog";
-
-export default {
-  name: "grade-ribbon",
-  components: {
-    RibbonSetDialog,
-    NoticeDialog
-  },
-  data() {
-    return {};
-  },
-  methods: {
-    toNotice() {
-      this.$refs.NoticeDialog.open();
-    },
-    toSet() {
-      this.$refs.RibbonSetDialog.open();
-    },
-    toFresh() {
-      location.reload();
-    }
-  }
-};
-</script>
+<template>
+  <div class="grade-ribbon">
+    <div class="ribbon-list">
+      <div class="ribbon-item" title="刷新" @click="toFresh">
+        <Icon type="md-refresh" />
+      </div>
+      <div class="ribbon-item" title="消息" @click="toNotice">
+        <Icon type="md-notifications" />
+      </div>
+      <div class="ribbon-item" title="设置" @click="toSet">
+        <Icon type="md-settings" />
+      </div>
+    </div>
+
+    <!-- RibbonSetDialog -->
+    <ribbon-set-dialog ref="RibbonSetDialog"></ribbon-set-dialog>
+    <!-- NoticeDialog -->
+    <notice-dialog ref="NoticeDialog"></notice-dialog>
+  </div>
+</template>
+
+<script>
+import RibbonSetDialog from "./RibbonSetDialog";
+import NoticeDialog from "./NoticeDialog";
+
+export default {
+  name: "grade-ribbon",
+  components: {
+    RibbonSetDialog,
+    NoticeDialog,
+  },
+  data() {
+    return {};
+  },
+  methods: {
+    toNotice() {
+      this.$refs.NoticeDialog.open();
+    },
+    toSet() {
+      this.$refs.RibbonSetDialog.open();
+    },
+    toFresh() {
+      location.reload();
+    },
+  },
+};
+</script>

+ 11 - 11
src/modules/grading/components/GradeStandardPaper.vue

@@ -34,14 +34,14 @@ export default {
   components: { PaperCarousel },
   components: { PaperCarousel },
   props: {
   props: {
     questionId: {
     questionId: {
-      type: Number
+      type: Number,
     },
     },
     levels: {
     levels: {
       type: Array,
       type: Array,
       default() {
       default() {
         return [];
         return [];
-      }
-    }
+      },
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -49,7 +49,7 @@ export default {
       curLevelIndex: 0,
       curLevelIndex: 0,
       papers: [],
       papers: [],
       paperMap: {},
       paperMap: {},
-      isLoading: false
+      isLoading: false,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -61,14 +61,14 @@ export default {
     },
     },
     lastLevelIndex() {
     lastLevelIndex() {
       return this.levels.length ? this.levels.length - 1 : 0;
       return this.levels.length ? this.levels.length - 1 : 0;
-    }
+    },
   },
   },
   watch: {
   watch: {
     questionId(val) {
     questionId(val) {
       this.paperMap = {};
       this.paperMap = {};
       this.papers = [];
       this.papers = [];
       this.updatePapers();
       this.updatePapers();
-    }
+    },
   },
   },
   mounted() {
   mounted() {
     this.setCurLevel(this.curLevelIndex);
     this.setCurLevel(this.curLevelIndex);
@@ -80,7 +80,7 @@ export default {
     },
     },
     curLevelChange() {
     curLevelChange() {
       this.curLevelIndex = this.levels.findIndex(
       this.curLevelIndex = this.levels.findIndex(
-        item => item.name === this.curLevel
+        (item) => item.name === this.curLevel
       );
       );
       this.updatePapers();
       this.updatePapers();
     },
     },
@@ -100,7 +100,7 @@ export default {
         sort: "secretNumber",
         sort: "secretNumber",
         isSample: true,
         isSample: true,
         page: 0,
         page: 0,
-        size: 100
+        size: 100,
       };
       };
       const data = await paperList(datas).catch(() => {});
       const data = await paperList(datas).catch(() => {});
       this.isLoading = false;
       this.isLoading = false;
@@ -115,7 +115,7 @@ export default {
         sort: "secretNumber",
         sort: "secretNumber",
         isSample: true,
         isSample: true,
         page: 0,
         page: 0,
-        size: 100
+        size: 100,
       };
       };
       const data = await paperList(datas).catch(() => {});
       const data = await paperList(datas).catch(() => {});
       this.isLoading = false;
       this.isLoading = false;
@@ -144,7 +144,7 @@ export default {
     },
     },
     paperChange(curPaper) {
     paperChange(curPaper) {
       this.$emit("on-paper-change", curPaper);
       this.$emit("on-paper-change", curPaper);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 84 - 84
src/modules/grading/components/GradeStep.vue

@@ -1,84 +1,84 @@
-<template>
-  <div class="grade-step">
-    <div
-      class="grade-step-other"
-      v-if="steps.otherStep && steps.otherStep.length"
-    >
-      <div
-        v-for="(step, sindex) in steps.otherStep"
-        :key="sindex"
-        :class="[
-          'step-item',
-          {
-            'step-act': curStep.name === step.name,
-            'step-other': step.type !== 'done'
-          }
-        ]"
-        @click="selectStep(step)"
-      >
-        <p>{{ step.count }}</p>
-        <p class="step-name">{{ step.name }}</p>
-        <p>{{ step.count }}</p>
-      </div>
-    </div>
-    <div class="grade-step-level">
-      <div
-        v-for="(step, sindex) in steps.levelStep"
-        :key="sindex"
-        :class="[
-          'step-item',
-          {
-            'step-act': curStep.name === step.name,
-            'step-other': step.type !== 'done'
-          }
-        ]"
-        @click="selectStep(step)"
-      >
-        <p>
-          <span>{{ step.gcount }}/</span><span>{{ step.gpercent }}%</span
-          ><span>({{ step.pt }}%)</span>
-        </p>
-        <p class="step-name">{{ step.name | levelNameFilter }}</p>
-        <p>
-          <span>{{ step.count }}/</span><span>{{ step.percent }}%</span
-          ><span v-if="step.kdpt !== null">({{ step.kdpt }}%)</span>
-        </p>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-export default {
-  name: "grade-step",
-  props: {
-    steps: {
-      type: Object,
-      default() {
-        return { levelStep: [], otherStep: [] };
-      }
-    },
-    initStep: {
-      type: Object,
-      default() {
-        return { type: "analysis", name: "analysis" };
-      }
-    }
-  },
-  data() {
-    return {
-      curStep: {}
-    };
-  },
-  mounted() {
-    // this.selectStep(this.initStep);
-    this.curStep = { ...this.initStep };
-  },
-  methods: {
-    selectStep(step) {
-      this.curStep = { ...step };
-      this.$emit("on-change", this.curStep);
-    }
-  }
-};
-</script>
+<template>
+  <div class="grade-step">
+    <div
+      class="grade-step-other"
+      v-if="steps.otherStep && steps.otherStep.length"
+    >
+      <div
+        v-for="(step, sindex) in steps.otherStep"
+        :key="sindex"
+        :class="[
+          'step-item',
+          {
+            'step-act': curStep.name === step.name,
+            'step-other': step.type !== 'done',
+          },
+        ]"
+        @click="selectStep(step)"
+      >
+        <p>{{ step.count }}</p>
+        <p class="step-name">{{ step.name }}</p>
+        <p>{{ step.count }}</p>
+      </div>
+    </div>
+    <div class="grade-step-level">
+      <div
+        v-for="(step, sindex) in steps.levelStep"
+        :key="sindex"
+        :class="[
+          'step-item',
+          {
+            'step-act': curStep.name === step.name,
+            'step-other': step.type !== 'done',
+          },
+        ]"
+        @click="selectStep(step)"
+      >
+        <p>
+          <span>{{ step.gcount }}/</span><span>{{ step.gpercent }}%</span
+          ><span>({{ step.pt }}%)</span>
+        </p>
+        <p class="step-name">{{ step.name | levelNameFilter }}</p>
+        <p>
+          <span>{{ step.count }}/</span><span>{{ step.percent }}%</span
+          ><span v-if="step.kdpt !== null">({{ step.kdpt }}%)</span>
+        </p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "grade-step",
+  props: {
+    steps: {
+      type: Object,
+      default() {
+        return { levelStep: [], otherStep: [] };
+      },
+    },
+    initStep: {
+      type: Object,
+      default() {
+        return { type: "analysis", name: "analysis" };
+      },
+    },
+  },
+  data() {
+    return {
+      curStep: {},
+    };
+  },
+  mounted() {
+    // this.selectStep(this.initStep);
+    this.curStep = { ...this.initStep };
+  },
+  methods: {
+    selectStep(step) {
+      this.curStep = { ...step };
+      this.$emit("on-change", this.curStep);
+    },
+  },
+};
+</script>

+ 235 - 231
src/modules/grading/components/ModifyFormalGradingTask.vue

@@ -1,231 +1,235 @@
-<template>
-  <Modal
-    class="modify-formal-grading-task"
-    v-model="modalIsShow"
-    title="创建正评任务"
-    :mask-closable="false"
-    @on-visible-change="visibleChange"
-  >
-    <p class="tips-info tips-error" v-if="!canPublish">
-      警告:当前批次还有未完成的任务,无法发布新任务!
-    </p>
-    <Form
-      ref="modalFormComp"
-      class="modal-form"
-      :model="modalForm"
-      :rules="rules"
-      :key="modalForm.id"
-      :label-width="130"
-    >
-      <FormItem prop="questionId" label="考区">
-        <Select
-          size="large"
-          v-model="modalForm.questionId"
-          placeholder="请选择考区"
-          multiple
-          @on-change="areaChange"
-        >
-          <Option
-            v-for="(item, index) in areas"
-            :key="index"
-            :value="item.questionId"
-            :label="item.areaName"
-            :disabled="!!item.initCount"
-          ></Option>
-        </Select>
-      </FormItem>
-      <FormItem label="已评数量">
-        <Input
-          size="large"
-          v-model.trim="modalForm.successCount"
-          readonly
-        ></Input>
-      </FormItem>
-      <FormItem size="large" label="待评数量">
-        <Input v-model.trim="modalForm.waitCount" readonly></Input>
-      </FormItem>
-      <FormItem size="large" label="整体进度">
-        <Input v-model.trim="modalForm.progress" readonly></Input>
-      </FormItem>
-      <FormItem prop="taskCount" label="分配任务数量">
-        <InputNumber
-          size="large"
-          :min="minTaskCount"
-          :max="maxTaskCount"
-          :precision="0"
-          :active-change="false"
-          v-model.trim="modalForm.taskCount"
-          :disabled="!modalForm.waitCount || !canPublish"
-          style="width: 120px"
-          clearable
-        ></InputNumber>
-      </FormItem>
-    </Form>
-    <div slot="footer">
-      <Button
-        shape="circle"
-        type="primary"
-        :disabled="isSubmit || !canPublish || !modalForm.waitCount"
-        @click="submit"
-        >发布</Button
-      >
-      <Button shape="circle" @click="cancel">取消</Button>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import {
-  checkMissionStatus,
-  checkCanPublishTask,
-  createGradingTask,
-  areaStatProgress
-} from "@/api";
-import { calcSum } from "@/plugins/utils";
-
-const initModalForm = {
-  questionId: [],
-  totalCount: 0,
-  successCount: 0,
-  waitCount: 0,
-  progress: 0,
-  taskCount: null
-};
-
-export default {
-  name: "modify-formal-grading-task",
-  props: {
-    subjectId: {
-      type: String,
-      required: true
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      isSubmit: false,
-      canPublish: true,
-      modalForm: { ...initModalForm },
-      areas: [],
-      defaultQuestionIds: [],
-      minTaskCount: 0,
-      maxTaskCount: 0,
-      rules: {
-        questionId: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (value && value.length) {
-                callback();
-              } else {
-                callback(new Error("请选择考区"));
-              }
-            },
-            trigger: "change"
-          }
-        ],
-        taskCount: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (value) {
-                callback();
-              } else {
-                callback(new Error("请输入分配任务数量"));
-              }
-            },
-            trigger: "change"
-          }
-        ]
-      }
-    };
-  },
-  methods: {
-    visibleChange(visible) {
-      if (visible) {
-        this.$refs.modalFormComp.resetFields();
-        this.getArea();
-        this.checkStatus();
-      }
-    },
-    async checkStatus() {
-      this.canPublish = await checkCanPublishTask(this.subjectId);
-    },
-    async getArea() {
-      const data = await areaStatProgress(this.subjectId);
-      this.areas = data;
-      this.defaultQuestionIds = data
-        .filter(item => item.initCount)
-        .map(item => item.questionId);
-      this.modalForm.questionId = this.defaultQuestionIds.length
-        ? [...this.defaultQuestionIds]
-        : [data[data.length - 1].questionId];
-
-      this.areaChange();
-    },
-    areaChange() {
-      this.modalForm.questionId = this.modalForm.questionId.filter(
-        item => !this.defaultQuestionIds.includes(item)
-      );
-      this.modalForm.questionId = [
-        ...this.modalForm.questionId,
-        ...this.defaultQuestionIds
-      ];
-      const curAreas = this.areas.filter(item =>
-        this.modalForm.questionId.includes(item.questionId)
-      );
-      this.modalForm.successCount = calcSum(
-        curAreas.map(item => item.successCount)
-      );
-      this.modalForm.waitCount = calcSum(curAreas.map(item => item.waitCount));
-
-      this.modalForm.progress = !(
-        this.modalForm.successCount + this.modalForm.waitCount
-      )
-        ? "0%"
-        : (
-            (100 * this.modalForm.successCount) /
-            (this.modalForm.successCount + this.modalForm.waitCount)
-          ).toFixed(2) + "%";
-
-      this.modalForm.taskCount = calcSum(curAreas.map(item => item.initCount));
-      this.minTaskCount = this.modalForm.taskCount || 1;
-      this.maxTaskCount = this.modalForm.waitCount;
-
-      console.log(curAreas);
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
-      if (!valid) return;
-
-      if (this.isSubmit) return;
-
-      const ids = this.subjectId.split("-");
-      await checkMissionStatus({ workId: ids[0], subject: ids[1] });
-
-      this.isSubmit = true;
-      let result = true;
-      await createGradingTask({
-        subjectId: this.subjectId,
-        taskCount: this.modalForm.taskCount,
-        questionId: this.modalForm.questionId
-      }).catch(() => {
-        result = false;
-      });
-
-      this.isSubmit = false;
-      if (!result) return;
-
-      this.$Modal.success({ content: "评卷任务创建成功" });
-      this.$emit("modified");
-      this.cancel();
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    class="modify-formal-grading-task"
+    v-model="modalIsShow"
+    title="创建正评任务"
+    :mask-closable="false"
+    @on-visible-change="visibleChange"
+  >
+    <p class="tips-info tips-error" v-if="!canPublish">
+      警告:当前批次还有未完成的任务,无法发布新任务!
+    </p>
+    <Form
+      ref="modalFormComp"
+      class="modal-form"
+      :model="modalForm"
+      :rules="rules"
+      :key="modalForm.id"
+      :label-width="130"
+    >
+      <FormItem prop="questionId" label="考区">
+        <Select
+          size="large"
+          v-model="modalForm.questionId"
+          placeholder="请选择考区"
+          multiple
+          @on-change="areaChange"
+        >
+          <Option
+            v-for="(item, index) in areas"
+            :key="index"
+            :value="item.questionId"
+            :label="item.areaName"
+            :disabled="!!item.initCount"
+          ></Option>
+        </Select>
+      </FormItem>
+      <FormItem label="已评数量">
+        <Input
+          size="large"
+          v-model.trim="modalForm.successCount"
+          readonly
+        ></Input>
+      </FormItem>
+      <FormItem size="large" label="待评数量">
+        <Input v-model.trim="modalForm.waitCount" readonly></Input>
+      </FormItem>
+      <FormItem size="large" label="整体进度">
+        <Input v-model.trim="modalForm.progress" readonly></Input>
+      </FormItem>
+      <FormItem prop="taskCount" label="分配任务数量">
+        <InputNumber
+          size="large"
+          :min="minTaskCount"
+          :max="maxTaskCount"
+          :precision="0"
+          :active-change="false"
+          v-model.trim="modalForm.taskCount"
+          :disabled="!modalForm.waitCount || !canPublish"
+          style="width: 120px"
+          clearable
+        ></InputNumber>
+      </FormItem>
+    </Form>
+    <div slot="footer">
+      <Button
+        shape="circle"
+        type="primary"
+        :disabled="isSubmit || !canPublish || !modalForm.waitCount"
+        @click="submit"
+        >发布</Button
+      >
+      <Button shape="circle" @click="cancel">取消</Button>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import {
+  checkMissionStatus,
+  checkCanPublishTask,
+  createGradingTask,
+  areaStatProgress,
+} from "@/api";
+import { calcSum } from "@/plugins/utils";
+
+const initModalForm = {
+  questionId: [],
+  totalCount: 0,
+  successCount: 0,
+  waitCount: 0,
+  progress: 0,
+  taskCount: null,
+};
+
+export default {
+  name: "modify-formal-grading-task",
+  props: {
+    subjectId: {
+      type: String,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      canPublish: true,
+      modalForm: { ...initModalForm },
+      areas: [],
+      defaultQuestionIds: [],
+      minTaskCount: 0,
+      maxTaskCount: 0,
+      rules: {
+        questionId: [
+          {
+            required: true,
+            validator: (rule, value, callback) => {
+              if (value && value.length) {
+                callback();
+              } else {
+                callback(new Error("请选择考区"));
+              }
+            },
+            trigger: "change",
+          },
+        ],
+        taskCount: [
+          {
+            required: true,
+            validator: (rule, value, callback) => {
+              if (value) {
+                callback();
+              } else {
+                callback(new Error("请输入分配任务数量"));
+              }
+            },
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.$refs.modalFormComp.resetFields();
+        this.getArea();
+        this.checkStatus();
+      }
+    },
+    async checkStatus() {
+      this.canPublish = await checkCanPublishTask(this.subjectId);
+    },
+    async getArea() {
+      const data = await areaStatProgress(this.subjectId);
+      this.areas = data;
+      this.defaultQuestionIds = data
+        .filter((item) => item.initCount)
+        .map((item) => item.questionId);
+      this.modalForm.questionId = this.defaultQuestionIds.length
+        ? [...this.defaultQuestionIds]
+        : [data[data.length - 1].questionId];
+
+      this.areaChange();
+    },
+    areaChange() {
+      this.modalForm.questionId = this.modalForm.questionId.filter(
+        (item) => !this.defaultQuestionIds.includes(item)
+      );
+      this.modalForm.questionId = [
+        ...this.modalForm.questionId,
+        ...this.defaultQuestionIds,
+      ];
+      const curAreas = this.areas.filter((item) =>
+        this.modalForm.questionId.includes(item.questionId)
+      );
+      this.modalForm.successCount = calcSum(
+        curAreas.map((item) => item.successCount)
+      );
+      this.modalForm.waitCount = calcSum(
+        curAreas.map((item) => item.waitCount)
+      );
+
+      this.modalForm.progress = !(
+        this.modalForm.successCount + this.modalForm.waitCount
+      )
+        ? "0%"
+        : (
+            (100 * this.modalForm.successCount) /
+            (this.modalForm.successCount + this.modalForm.waitCount)
+          ).toFixed(2) + "%";
+
+      this.modalForm.taskCount = calcSum(
+        curAreas.map((item) => item.initCount)
+      );
+      this.minTaskCount = this.modalForm.taskCount || 1;
+      this.maxTaskCount = this.modalForm.waitCount;
+
+      console.log(curAreas);
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async submit() {
+      const valid = await this.$refs.modalFormComp.validate();
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+
+      const ids = this.subjectId.split("-");
+      await checkMissionStatus({ workId: ids[0], subject: ids[1] });
+
+      this.isSubmit = true;
+      let result = true;
+      await createGradingTask({
+        subjectId: this.subjectId,
+        taskCount: this.modalForm.taskCount,
+        questionId: this.modalForm.questionId,
+      }).catch(() => {
+        result = false;
+      });
+
+      this.isSubmit = false;
+      if (!result) return;
+
+      this.$Modal.success({ content: "评卷任务创建成功" });
+      this.$emit("modified");
+      this.cancel();
+    },
+  },
+};
+</script>

+ 27 - 27
src/modules/grading/components/ModifyGradingUser.vue

@@ -81,8 +81,8 @@
         label="权重"
         label="权重"
         v-if="
         v-if="
           modalForm.role === 'MARKER' &&
           modalForm.role === 'MARKER' &&
-            modalForm.markRight &&
-            modalForm.markRight !== 'ALLOW_SCORING'
+          modalForm.markRight &&
+          modalForm.markRight !== 'ALLOW_SCORING'
         "
         "
       >
       >
         <InputNumber
         <InputNumber
@@ -124,7 +124,7 @@
             v-for="(val, key) in MARK_LEADER_RIGHTS"
             v-for="(val, key) in MARK_LEADER_RIGHTS"
             :key="key"
             :key="key"
             :label="key"
             :label="key"
-            style="line-height: 40px;"
+            style="line-height: 40px"
           >
           >
             {{ val.name }}
             {{ val.name }}
           </Checkbox>
           </Checkbox>
@@ -134,7 +134,7 @@
             v-for="(val, key) in MARK_LEADER_RIGHTS"
             v-for="(val, key) in MARK_LEADER_RIGHTS"
             :key="key"
             :key="key"
             :label="key"
             :label="key"
-            style="line-height: 40px;"
+            style="line-height: 40px"
             >{{ val.name }}</Radio
             >{{ val.name }}</Radio
           >
           >
         </RadioGroup>
         </RadioGroup>
@@ -156,7 +156,7 @@ import {
   BOOLEAN_TYPE,
   BOOLEAN_TYPE,
   ROLE_TYPE,
   ROLE_TYPE,
   MARKER_RIGHT_TYPE,
   MARKER_RIGHT_TYPE,
-  MARK_LEADER_RIGHTS
+  MARK_LEADER_RIGHTS,
 } from "@/constants/enumerate";
 } from "@/constants/enumerate";
 
 
 const initModalForm = {
 const initModalForm = {
@@ -172,7 +172,7 @@ const initModalForm = {
   oneClickLevel: false,
   oneClickLevel: false,
   standardVolume: false,
   standardVolume: false,
   levelCallback: false,
   levelCallback: false,
-  leaderConfirm: 1
+  leaderConfirm: 1,
 };
 };
 
 
 export default {
 export default {
@@ -182,14 +182,14 @@ export default {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
+      },
     },
     },
     subject: {
     subject: {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
-    }
+      },
+    },
   },
   },
   computed: {
   computed: {
     isEdit() {
     isEdit() {
@@ -197,7 +197,7 @@ export default {
     },
     },
     title() {
     title() {
       return (this.isEdit ? "编辑" : "新增") + "账号";
       return (this.isEdit ? "编辑" : "新增") + "账号";
-    }
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -218,22 +218,22 @@ export default {
             min: 2,
             min: 2,
             max: 20,
             max: 20,
             message: "请输入姓名,长度2-20个字符",
             message: "请输入姓名,长度2-20个字符",
-            trigger: "change"
-          }
+            trigger: "change",
+          },
         ],
         ],
         role: [
         role: [
           {
           {
             required: true,
             required: true,
             message: "请选择角色",
             message: "请选择角色",
-            trigger: "change"
-          }
+            trigger: "change",
+          },
         ],
         ],
         markRight: [
         markRight: [
           {
           {
             required: true,
             required: true,
             message: "请选择权限",
             message: "请选择权限",
-            trigger: "change"
-          }
+            trigger: "change",
+          },
         ],
         ],
         weight: numberValidator("请输入权重"),
         weight: numberValidator("请输入权重"),
         leaderConfirm: numberValidator("请选择操作是否需要确认"),
         leaderConfirm: numberValidator("请选择操作是否需要确认"),
@@ -250,30 +250,30 @@ export default {
                 return callback();
                 return callback();
               }
               }
             },
             },
-            trigger: "change"
-          }
-        ]
-      }
+            trigger: "change",
+          },
+        ],
+      },
     };
     };
   },
   },
   methods: {
   methods: {
     initData(val) {
     initData(val) {
       this.$refs.modalFormComp.resetFields();
       this.$refs.modalFormComp.resetFields();
-      this.roleTypes = Object.keys(ROLE_TYPE).map(key => {
+      this.roleTypes = Object.keys(ROLE_TYPE).map((key) => {
         return {
         return {
           key,
           key,
-          val: ROLE_TYPE[key]
+          val: ROLE_TYPE[key],
         };
         };
       });
       });
       if (!this.isEdit) {
       if (!this.isEdit) {
         this.roleTypes.filter(
         this.roleTypes.filter(
-          item => this.subject.stage === "INIT" || item.key === "MARK_LEADER"
+          (item) => this.subject.stage === "INIT" || item.key === "MARK_LEADER"
         );
         );
       }
       }
       this.modalForm = this.$objAssign(initModalForm, val);
       this.modalForm = this.$objAssign(initModalForm, val);
       this.modalForm.leaderConfirm = this.modalForm.leaderConfirm ? 1 : 0;
       this.modalForm.leaderConfirm = this.modalForm.leaderConfirm ? 1 : 0;
       this.leaderRights = Object.keys(MARK_LEADER_RIGHTS).filter(
       this.leaderRights = Object.keys(MARK_LEADER_RIGHTS).filter(
-        right => this.modalForm[right]
+        (right) => this.modalForm[right]
       );
       );
       if (!this.modalForm.leaderConfirm)
       if (!this.modalForm.leaderConfirm)
         this.leaderRights = this.leaderRights[0];
         this.leaderRights = this.leaderRights[0];
@@ -308,7 +308,7 @@ export default {
       const rights = datas.leaderConfirm
       const rights = datas.leaderConfirm
         ? this.leaderRights
         ? this.leaderRights
         : [this.leaderRights];
         : [this.leaderRights];
-      Object.keys(MARK_LEADER_RIGHTS).forEach(right => {
+      Object.keys(MARK_LEADER_RIGHTS).forEach((right) => {
         datas[right] = rights.includes(right);
         datas[right] = rights.includes(right);
       });
       });
       await updateGradingUser(datas).catch(() => {
       await updateGradingUser(datas).catch(() => {
@@ -321,7 +321,7 @@ export default {
       this.$Message.success(this.title + "成功!");
       this.$Message.success(this.title + "成功!");
       this.$emit("modified");
       this.$emit("modified");
       this.cancel();
       this.cancel();
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 158 - 158
src/modules/grading/components/ModifyLeaderGrading.vue

@@ -1,158 +1,158 @@
-<template>
-  <Modal
-    class="modify-leader-grading"
-    v-model="modalIsShow"
-    title="科组长评档"
-    :mask-closable="false"
-    @on-cancel="cancelHandle"
-    @on-visible-change="visibleChange"
-  >
-    <div class="leader-grading">
-      <div class="leader-level">
-        <p>已选档位</p>
-        <h3>{{ levelInfo.selectedLevel | levelNameFilter }}</h3>
-      </div>
-      <RadioGroup v-model="actionType">
-        <div class="leader-aciton" v-if="standardVolume">
-          <Radio size="large" label="sampling">设为标准卷</Radio>
-        </div>
-        <div class="leader-aciton" v-if="oneClickLevel">
-          <Radio size="large" label="leveling" :disabled="noneedLevelOrReject"
-            >一键定档</Radio
-          >
-        </div>
-        <div class="leader-aciton" v-if="levelCallback">
-          <Radio size="large" label="reject" :disabled="noneedLevelOrReject"
-            >建议档位打回</Radio
-          >
-        </div>
-      </RadioGroup>
-      <div
-        class="leader-markers"
-        v-if="actionType === 'reject' && !noneedLevelOrReject"
-      >
-        <CheckboxGroup v-model="selectedMarkers">
-          <Checkbox
-            v-for="marker in markers"
-            :key="marker.id"
-            :label="marker.id"
-            >{{ marker.name }}</Checkbox
-          >
-        </CheckboxGroup>
-      </div>
-    </div>
-
-    <div slot="footer">
-      <Button shape="circle" type="primary" :disabled="isSubmit" @click="submit"
-        >确认</Button
-      >
-      <Button shape="circle" @click="cancel">取消</Button>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { leaderGradingPaper } from "@/api";
-
-export default {
-  name: "modify-leader-grading",
-  props: {
-    levelInfo: {
-      type: Object,
-      default() {
-        return {
-          paperIds: "",
-          curLevel: "",
-          selectedLevel: ""
-        };
-      }
-    },
-    markers: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    stage: {
-      type: String,
-      default: "LEVEL"
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      isSubmit: false,
-      standardVolume: false,
-      oneClickLevel: false,
-      levelCallback: false,
-      noneedLevelOrReject: false,
-      actionType: null,
-      selectedMarkers: []
-    };
-  },
-  methods: {
-    initData() {
-      const isMuliple = this.levelInfo.paperIds.includes(",");
-      this.noneedLevelOrReject =
-        this.levelInfo.curLevel === this.levelInfo.selectedLevel;
-      const user = this.$ls.get("user");
-      this.standardVolume = user.standardVolume && !isMuliple;
-      this.levelCallback = user.levelCallback;
-      this.oneClickLevel = user.oneClickLevel;
-      this.selectedMarkers = [];
-      // this.selectedMarkers = this.markers.map(item => item.id);
-    },
-    visibleChange(visible) {
-      if (visible) {
-        this.initData();
-      } else {
-        this.isSubmit = false;
-        this.actionType = null;
-      }
-    },
-    cancel() {
-      this.modalIsShow = false;
-      this.cancelHandle();
-    },
-    cancelHandle() {
-      this.$emit("canceled");
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    async submit() {
-      if (!this.actionType) {
-        this.$Message.error("请选择操作类型!");
-        return;
-      }
-      if (this.actionType === "reject" && !this.selectedMarkers.length) {
-        this.$Message.error("请指定评卷员!");
-        return;
-      }
-      const datas = {
-        action: this.actionType,
-        level: this.levelInfo.selectedLevel,
-        originLevel: this.levelInfo.curLevel,
-        paperIds: this.levelInfo.paperIds,
-        stage: this.stage
-      };
-      if (this.actionType === "reject")
-        datas.range = this.selectedMarkers.join();
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      let result = true;
-      const paper = await leaderGradingPaper(datas).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-
-      if (!result) return;
-
-      this.$Message.success("操作成功!");
-      this.$emit("modified", datas, paper);
-      this.cancel();
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    class="modify-leader-grading"
+    v-model="modalIsShow"
+    title="科组长评档"
+    :mask-closable="false"
+    @on-cancel="cancelHandle"
+    @on-visible-change="visibleChange"
+  >
+    <div class="leader-grading">
+      <div class="leader-level">
+        <p>已选档位</p>
+        <h3>{{ levelInfo.selectedLevel | levelNameFilter }}</h3>
+      </div>
+      <RadioGroup v-model="actionType">
+        <div class="leader-aciton" v-if="standardVolume">
+          <Radio size="large" label="sampling">设为标准卷</Radio>
+        </div>
+        <div class="leader-aciton" v-if="oneClickLevel">
+          <Radio size="large" label="leveling" :disabled="noneedLevelOrReject"
+            >一键定档</Radio
+          >
+        </div>
+        <div class="leader-aciton" v-if="levelCallback">
+          <Radio size="large" label="reject" :disabled="noneedLevelOrReject"
+            >建议档位打回</Radio
+          >
+        </div>
+      </RadioGroup>
+      <div
+        class="leader-markers"
+        v-if="actionType === 'reject' && !noneedLevelOrReject"
+      >
+        <CheckboxGroup v-model="selectedMarkers">
+          <Checkbox
+            v-for="marker in markers"
+            :key="marker.id"
+            :label="marker.id"
+            >{{ marker.name }}</Checkbox
+          >
+        </CheckboxGroup>
+      </div>
+    </div>
+
+    <div slot="footer">
+      <Button shape="circle" type="primary" :disabled="isSubmit" @click="submit"
+        >确认</Button
+      >
+      <Button shape="circle" @click="cancel">取消</Button>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { leaderGradingPaper } from "@/api";
+
+export default {
+  name: "modify-leader-grading",
+  props: {
+    levelInfo: {
+      type: Object,
+      default() {
+        return {
+          paperIds: "",
+          curLevel: "",
+          selectedLevel: "",
+        };
+      },
+    },
+    markers: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    stage: {
+      type: String,
+      default: "LEVEL",
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      standardVolume: false,
+      oneClickLevel: false,
+      levelCallback: false,
+      noneedLevelOrReject: false,
+      actionType: null,
+      selectedMarkers: [],
+    };
+  },
+  methods: {
+    initData() {
+      const isMuliple = this.levelInfo.paperIds.includes(",");
+      this.noneedLevelOrReject =
+        this.levelInfo.curLevel === this.levelInfo.selectedLevel;
+      const user = this.$ls.get("user");
+      this.standardVolume = user.standardVolume && !isMuliple;
+      this.levelCallback = user.levelCallback;
+      this.oneClickLevel = user.oneClickLevel;
+      this.selectedMarkers = [];
+      // this.selectedMarkers = this.markers.map(item => item.id);
+    },
+    visibleChange(visible) {
+      if (visible) {
+        this.initData();
+      } else {
+        this.isSubmit = false;
+        this.actionType = null;
+      }
+    },
+    cancel() {
+      this.modalIsShow = false;
+      this.cancelHandle();
+    },
+    cancelHandle() {
+      this.$emit("canceled");
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async submit() {
+      if (!this.actionType) {
+        this.$Message.error("请选择操作类型!");
+        return;
+      }
+      if (this.actionType === "reject" && !this.selectedMarkers.length) {
+        this.$Message.error("请指定评卷员!");
+        return;
+      }
+      const datas = {
+        action: this.actionType,
+        level: this.levelInfo.selectedLevel,
+        originLevel: this.levelInfo.curLevel,
+        paperIds: this.levelInfo.paperIds,
+        stage: this.stage,
+      };
+      if (this.actionType === "reject")
+        datas.range = this.selectedMarkers.join();
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      let result = true;
+      const paper = await leaderGradingPaper(datas).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+
+      if (!result) return;
+
+      this.$Message.success("操作成功!");
+      this.$emit("modified", datas, paper);
+      this.cancel();
+    },
+  },
+};
+</script>

+ 160 - 160
src/modules/grading/components/ModifyUnformalGradingTask.vue

@@ -1,160 +1,160 @@
-<template>
-  <Modal
-    class="modify-unformal-grading-task"
-    v-model="modalIsShow"
-    title="创建试评任务"
-    :mask-closable="false"
-    @on-visible-change="visibleChange"
-  >
-    <div class="task-body" v-if="!unformalGradingIsRunning">
-      <upload-button
-        btn-icon="md-cloud-upload"
-        :btn-content="uploadBtnName"
-        :upload-url="uploadUrl"
-        :upload-data="uploadData"
-        :headers="headers"
-        :format="['xls', 'xlsx']"
-        :auto-upload="false"
-        @upload-success="uploadSuccess"
-        @file-change="selectedFile"
-        ref="UploadButton"
-      >
-        <Button
-          type="primary"
-          shape="circle"
-          :disabled="$refs.UploadButton && $refs.UploadButton.loading"
-          @click="startUpload"
-          style="margin-left: 10px"
-          slot="extra"
-          >开始上传</Button
-        >
-      </upload-button>
-    </div>
-    <div class="task-body" v-else>
-      <p class="task-tips">当前已经开始试评</p>
-    </div>
-    <div class="task-action" slot="footer">
-      <Button
-        shape="circle"
-        type="error"
-        :disabled="isSubmit"
-        @click="toOverTask"
-        v-if="unformalGradingIsRunning"
-        >结束并清空数据</Button
-      >
-      <Button shape="circle" @click="cancel">取消</Button>
-      <Button
-        shape="circle"
-        type="primary"
-        :disabled="isSubmit || !uploadFileIsSuccess"
-        v-if="!unformalGradingIsRunning"
-        @click="toStartTask"
-        >开始试评</Button
-      >
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { createTryGradingTask, finishTryGradingTask } from "@/api";
-import UploadButton from "@/components/UploadButton";
-
-export default {
-  name: "modify-unformal-grading-task",
-  components: { UploadButton },
-  props: {
-    curSubject: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      isSubmit: false,
-      uploadData: {},
-      headers: {
-        Authorization: this.$ls.get("user", { token: "" }).token,
-        workId: this.$route.params.workId,
-        userId: this.$ls.get("user", { id: "" }).id
-      },
-      uploadBtnName: "导入考生数据",
-      uploadUrl: this.GLOBAL.domain + "/api/import/students/batchAllForTrial",
-      uploadFileIsSuccess: false,
-      unformalGradingIsRunning: false
-    };
-  },
-  created() {
-    this.uploadData = {
-      workId: this.curSubject.workId,
-      subject: this.curSubject.subject
-    };
-  },
-  methods: {
-    visibleChange(visible) {
-      if (visible) {
-        this.uploadFileIsSuccess = false;
-        this.isSubmit = false;
-        this.unformalGradingIsRunning =
-          (this.curSubject.stage === "LEVEL" ||
-            this.curSubject.stage === "ROUGH_LEVEL") &&
-          this.curSubject.test === 2;
-      }
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    startUpload() {
-      this.$refs.UploadButton.startUpload();
-    },
-    selectedFile(file) {
-      this.uploadBtnName = file.name;
-    },
-    uploadSuccess(response) {
-      this.uploadBtnName = "导入考生数据";
-      this.uploadFileIsSuccess = true;
-    },
-    async toStartTask() {
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      let result = true;
-      await createTryGradingTask(this.uploadData).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-      if (!result) return;
-
-      this.$Message.success("发布任务成功!");
-      this.$emit("modified");
-      this.cancel();
-    },
-    async toOverTask() {
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-
-      this.$Modal.confirm({
-        content: "确定要结束试评任务并清空所有试评数据吗?",
-        onOk: async () => {
-          const data = await finishTryGradingTask(
-            this.uploadData
-          ).catch(() => {});
-          this.isSubmit = false;
-          if (!data) return;
-
-          this.$Message.success("操作成功!");
-          this.$emit("modified");
-          this.cancel();
-        },
-        onCancel: () => {
-          this.isSubmit = false;
-        }
-      });
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    class="modify-unformal-grading-task"
+    v-model="modalIsShow"
+    title="创建试评任务"
+    :mask-closable="false"
+    @on-visible-change="visibleChange"
+  >
+    <div class="task-body" v-if="!unformalGradingIsRunning">
+      <upload-button
+        btn-icon="md-cloud-upload"
+        :btn-content="uploadBtnName"
+        :upload-url="uploadUrl"
+        :upload-data="uploadData"
+        :headers="headers"
+        :format="['xls', 'xlsx']"
+        :auto-upload="false"
+        @upload-success="uploadSuccess"
+        @file-change="selectedFile"
+        ref="UploadButton"
+      >
+        <Button
+          type="primary"
+          shape="circle"
+          :disabled="$refs.UploadButton && $refs.UploadButton.loading"
+          @click="startUpload"
+          style="margin-left: 10px"
+          slot="extra"
+          >开始上传</Button
+        >
+      </upload-button>
+    </div>
+    <div class="task-body" v-else>
+      <p class="task-tips">当前已经开始试评</p>
+    </div>
+    <div class="task-action" slot="footer">
+      <Button
+        shape="circle"
+        type="error"
+        :disabled="isSubmit"
+        @click="toOverTask"
+        v-if="unformalGradingIsRunning"
+        >结束并清空数据</Button
+      >
+      <Button shape="circle" @click="cancel">取消</Button>
+      <Button
+        shape="circle"
+        type="primary"
+        :disabled="isSubmit || !uploadFileIsSuccess"
+        v-if="!unformalGradingIsRunning"
+        @click="toStartTask"
+        >开始试评</Button
+      >
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { createTryGradingTask, finishTryGradingTask } from "@/api";
+import UploadButton from "@/components/UploadButton";
+
+export default {
+  name: "modify-unformal-grading-task",
+  components: { UploadButton },
+  props: {
+    curSubject: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      uploadData: {},
+      headers: {
+        Authorization: this.$ls.get("user", { token: "" }).token,
+        workId: this.$route.params.workId,
+        userId: this.$ls.get("user", { id: "" }).id,
+      },
+      uploadBtnName: "导入考生数据",
+      uploadUrl: this.GLOBAL.domain + "/api/import/students/batchAllForTrial",
+      uploadFileIsSuccess: false,
+      unformalGradingIsRunning: false,
+    };
+  },
+  created() {
+    this.uploadData = {
+      workId: this.curSubject.workId,
+      subject: this.curSubject.subject,
+    };
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.uploadFileIsSuccess = false;
+        this.isSubmit = false;
+        this.unformalGradingIsRunning =
+          (this.curSubject.stage === "LEVEL" ||
+            this.curSubject.stage === "ROUGH_LEVEL") &&
+          this.curSubject.test === 2;
+      }
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    startUpload() {
+      this.$refs.UploadButton.startUpload();
+    },
+    selectedFile(file) {
+      this.uploadBtnName = file.name;
+    },
+    uploadSuccess(response) {
+      this.uploadBtnName = "导入考生数据";
+      this.uploadFileIsSuccess = true;
+    },
+    async toStartTask() {
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      let result = true;
+      await createTryGradingTask(this.uploadData).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+      if (!result) return;
+
+      this.$Message.success("发布任务成功!");
+      this.$emit("modified");
+      this.cancel();
+    },
+    async toOverTask() {
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+
+      this.$Modal.confirm({
+        content: "确定要结束试评任务并清空所有试评数据吗?",
+        onOk: async () => {
+          const data = await finishTryGradingTask(this.uploadData).catch(
+            () => {}
+          );
+          this.isSubmit = false;
+          if (!data) return;
+
+          this.$Message.success("操作成功!");
+          this.$emit("modified");
+          this.cancel();
+        },
+        onCancel: () => {
+          this.isSubmit = false;
+        },
+      });
+    },
+  },
+};
+</script>

+ 328 - 327
src/modules/grading/components/NoticeDialog.vue

@@ -1,327 +1,328 @@
-<template>
-  <Modal
-    class="notice-dialog marker-modal"
-    v-model="modalIsShow"
-    title="消息"
-    :mask-closable="false"
-    footer-hide
-    fullscreen
-    :z-index="2999"
-    @on-visible-change="visibleChange"
-  >
-    <div class="notice-container">
-      <div v-if="IS_MARK_LEADER" class="notice-users">
-        <div class="user-item user-all">
-          <div>小组成员</div>
-          <div
-            :class="['user-selection', { 'is-active': userSelectAll }]"
-            @click="selectAll"
-          >
-            <Icon v-if="userSelectAll" type="ios-checkmark-circle" />
-            <Icon v-else type="md-radio-button-off" />
-          </div>
-        </div>
-        <div
-          v-for="user in markers"
-          :key="user.id"
-          class="user-item"
-          @click="selectUser(user)"
-        >
-          <div class="user-avatar"><Icon type="md-contact" /></div>
-          <div class="user-name" :title="user.name">{{ user.name }}</div>
-          <div :class="['user-selection', { 'is-active': user.selected }]">
-            <Icon v-if="user.selected" type="ios-checkmark-circle" />
-            <Icon v-else type="md-radio-button-off" />
-          </div>
-        </div>
-      </div>
-      <div class="notice-body">
-        <div ref="NoticeContent" class="notice-content">
-          <div v-if="hasMore" class="notice-item notice-more" @click="nextPage">
-            获取更多
-          </div>
-          <div v-for="notice in notices" :key="notice.id" class="notice-item">
-            <div class="notice-item-head">
-              <span class="notice-head-users">
-                {{ notice.relateUsers }}
-              </span>
-              <span class="notice-head-time">
-                {{ notice.createTime }}
-              </span>
-            </div>
-            <div class="notice-item-content" v-html="notice.content"></div>
-          </div>
-        </div>
-        <div v-if="IS_MARK_LEADER" class="notice-send">
-          <textarea
-            placeholder="请输入"
-            v-model="content"
-            maxlength="300"
-          ></textarea>
-          <div class="notice-send-footer">
-            <Button type="primary" :loading="loading" @click="toSend"
-              >发送</Button
-            >
-          </div>
-        </div>
-      </div>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-import {
-  userSendNoticeList,
-  userReceiveNoticeList,
-  fetchReleaseUnreadNotice,
-  readNotice,
-  sendNotice,
-  leaderMarkUserList
-} from "@/api";
-import timeMixin from "@/plugins/timeMixin";
-
-export default {
-  name: "ribbon-set-dialog",
-  mixins: [timeMixin],
-  data() {
-    return {
-      workId: "",
-      subject: "",
-      modalIsShow: false,
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      userSelectAll: false,
-      markers: [],
-      notices: [],
-      current: 0,
-      size: 10,
-      content: "",
-      hasMore: false,
-      fetching: false,
-      loading: false
-    };
-  },
-  computed: {
-    ...mapState("marker", ["curSubject"]),
-    IS_MARKER() {
-      return this.curUserRoleType === "MARKER";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    }
-  },
-  mounted() {
-    const [workId, subject] = this.$route.params.subjectId.split("-");
-    this.workId = workId;
-    this.subject = subject;
-
-    this.initData();
-  },
-  beforeDestroy() {
-    this.clearSetTs();
-  },
-  methods: {
-    ...mapMutations("marker", ["setShortcut", "recoverShortcut"]),
-    async initData() {
-      if (this.IS_MARK_LEADER) {
-        this.getLeaderMarkerList();
-        this.getLeaderMarkerNoticeList();
-        return;
-      }
-
-      if (this.IS_MARKER) {
-        await this.getMarkerNoticeList();
-        await this.getNewNotice();
-      }
-    },
-    visibleChange(visible) {
-      if (visible) {
-        if (this.IS_MARKER) {
-          this.setNoticeRead();
-        }
-        this.goToBottom();
-        this.setShortcut([]);
-      } else {
-        this.recoverShortcut();
-      }
-    },
-    goToBottom() {
-      this.$nextTick(() => {
-        this.$refs.NoticeContent.scrollTop = this.$refs.NoticeContent.offsetHeight;
-      });
-    },
-    async getLeaderMarkerList() {
-      const markerId = this.$ls.get("user", { id: "" }).id;
-      const data = await leaderMarkUserList({
-        workId: this.workId,
-        subject: this.subject,
-        stage: this.curSubject.stage,
-        markerId
-      });
-      const markers = data || [];
-      this.markers = markers.map(item => {
-        item.selected = false;
-        return item;
-      });
-    },
-    async nextPage() {
-      if (this.fetching) return;
-      this.fetching = true;
-
-      this.current++;
-      if (this.IS_MARKER) {
-        await this.getMarkerNoticeList().catch(() => {});
-      } else {
-        await this.getLeaderMarkerNoticeList().catch(() => {});
-      }
-      this.fetching = false;
-    },
-    async getLeaderMarkerNoticeList() {
-      const sendUserId = this.$ls.get("user", { id: "" }).id;
-      const lastId = this.notices.length ? this.notices.slice(-1)[0].id : null;
-      const data = await userSendNoticeList({
-        subject: this.subject,
-        stage: this.curSubject.stage,
-        sendUserId,
-        lastId,
-        page: this.current,
-        size: this.size
-      });
-      const notices = data.content.map(item => {
-        item.receiveUser = JSON.parse(item.receiveUser);
-        item.relateUsers = item.receiveUser.map(user => user.name).join(",");
-        return item;
-      });
-      notices.reverse();
-      this.hasMore = this.current + 1 < data.totalPages;
-      this.notices = [...notices, ...this.notices];
-    },
-    parseMarkerNotice(info) {
-      return {
-        ...info.message,
-        id: info.id,
-        read: info.read,
-        relateUsers: info.message.sendUserName
-      };
-    },
-    async getMarkerNoticeList() {
-      const receiveUserId = this.$ls.get("user", { id: "" }).id;
-      const lastId = this.notices.length ? this.notices.slice(-1)[0].id : null;
-      const data = await userReceiveNoticeList({
-        subject: this.subject,
-        stage: this.curSubject.stage,
-        receiveUserId,
-        lastId,
-        page: this.current,
-        size: this.size
-      });
-      const notices = data.content.map(item => {
-        return this.parseMarkerNotice(item);
-      });
-      notices.reverse();
-      this.hasMore = this.current + 1 < data.totalPages;
-      this.notices = [...notices, ...this.notices];
-    },
-    async getNewNotice() {
-      this.clearSetTs();
-
-      const receiveUserId = this.$ls.get("user", { id: "" }).id;
-      const resData = await fetchReleaseUnreadNotice({
-        subject: this.subject,
-        stage: this.curSubject.stage,
-        receiveUserId
-      }).catch(() => {});
-      const data = resData || [];
-      const noticeIds = this.notices.map(item => item.id);
-      const validNotices = data
-        .filter(item => !noticeIds.includes(item.id))
-        .map(item => this.parseMarkerNotice(item));
-      if (validNotices.length) {
-        this.notices.push(...validNotices);
-        this.open();
-        this.goToBottom();
-
-        this.$nextTick(() => {
-          this.setNoticeRead();
-        });
-      }
-
-      this.addSetTime(() => {
-        this.getNewNotice();
-      }, 10 * 1000);
-    },
-    setNoticeRead() {
-      const noticeIds = this.notices
-        .filter(item => !item.read)
-        .map(item => item.id);
-      if (!noticeIds.length) return;
-      readNotice(noticeIds);
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    selectChange() {
-      this.userSelectAll = !this.markers.some(item => !item.selected);
-    },
-    selectUser(user) {
-      user.selected = !user.selected;
-      this.selectChange();
-    },
-    selectAll() {
-      this.userSelectAll = !this.userSelectAll;
-      this.markers.forEach(user => {
-        user.selected = this.userSelectAll;
-      });
-    },
-    async toSend() {
-      if (!this.content) {
-        this.$Message.error("请输入内容");
-        return;
-      }
-      if (this.content.length > 300) {
-        this.$Message.error("内容最多300个字符");
-        return;
-      }
-
-      const user = this.$ls.get("user", { id: "", name: "" });
-      const markers = this.markers
-        .filter(item => item.selected)
-        .map(item => {
-          return {
-            id: item.id,
-            name: item.name
-          };
-        });
-
-      if (!markers.length) {
-        this.$Message.error("请选择评卷员");
-        return;
-      }
-
-      if (this.loading) return;
-      this.loading = true;
-
-      const data = {
-        subject: this.subject,
-        stage: this.curSubject.stage,
-        sendUserId: user.id,
-        sendUserName: user.name,
-        content: this.content,
-        markers
-      };
-      const res = await sendNotice(data).catch(() => {});
-      this.loading = false;
-      if (!res) return;
-
-      this.content = "";
-      res.receiveUser = JSON.parse(res.receiveUser);
-      res.relateUsers = res.receiveUser.map(item => item.name).join(",");
-      this.notices.push({ ...res });
-      this.goToBottom();
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    class="notice-dialog marker-modal"
+    v-model="modalIsShow"
+    title="消息"
+    :mask-closable="false"
+    footer-hide
+    fullscreen
+    :z-index="2999"
+    @on-visible-change="visibleChange"
+  >
+    <div class="notice-container">
+      <div v-if="IS_MARK_LEADER" class="notice-users">
+        <div class="user-item user-all">
+          <div>小组成员</div>
+          <div
+            :class="['user-selection', { 'is-active': userSelectAll }]"
+            @click="selectAll"
+          >
+            <Icon v-if="userSelectAll" type="ios-checkmark-circle" />
+            <Icon v-else type="md-radio-button-off" />
+          </div>
+        </div>
+        <div
+          v-for="user in markers"
+          :key="user.id"
+          class="user-item"
+          @click="selectUser(user)"
+        >
+          <div class="user-avatar"><Icon type="md-contact" /></div>
+          <div class="user-name" :title="user.name">{{ user.name }}</div>
+          <div :class="['user-selection', { 'is-active': user.selected }]">
+            <Icon v-if="user.selected" type="ios-checkmark-circle" />
+            <Icon v-else type="md-radio-button-off" />
+          </div>
+        </div>
+      </div>
+      <div class="notice-body">
+        <div ref="NoticeContent" class="notice-content">
+          <div v-if="hasMore" class="notice-item notice-more" @click="nextPage">
+            获取更多
+          </div>
+          <div v-for="notice in notices" :key="notice.id" class="notice-item">
+            <div class="notice-item-head">
+              <span class="notice-head-users">
+                {{ notice.relateUsers }}
+              </span>
+              <span class="notice-head-time">
+                {{ notice.createTime }}
+              </span>
+            </div>
+            <div class="notice-item-content" v-html="notice.content"></div>
+          </div>
+        </div>
+        <div v-if="IS_MARK_LEADER" class="notice-send">
+          <textarea
+            placeholder="请输入"
+            v-model="content"
+            maxlength="300"
+          ></textarea>
+          <div class="notice-send-footer">
+            <Button type="primary" :loading="loading" @click="toSend"
+              >发送</Button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import {
+  userSendNoticeList,
+  userReceiveNoticeList,
+  fetchReleaseUnreadNotice,
+  readNotice,
+  sendNotice,
+  leaderMarkUserList,
+} from "@/api";
+import timeMixin from "@/plugins/timeMixin";
+
+export default {
+  name: "ribbon-set-dialog",
+  mixins: [timeMixin],
+  data() {
+    return {
+      workId: "",
+      subject: "",
+      modalIsShow: false,
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      userSelectAll: false,
+      markers: [],
+      notices: [],
+      current: 0,
+      size: 10,
+      content: "",
+      hasMore: false,
+      fetching: false,
+      loading: false,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["curSubject"]),
+    IS_MARKER() {
+      return this.curUserRoleType === "MARKER";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    },
+  },
+  mounted() {
+    const [workId, subject] = this.$route.params.subjectId.split("-");
+    this.workId = workId;
+    this.subject = subject;
+
+    this.initData();
+  },
+  beforeDestroy() {
+    this.clearSetTs();
+  },
+  methods: {
+    ...mapMutations("marker", ["setShortcut", "recoverShortcut"]),
+    async initData() {
+      if (this.IS_MARK_LEADER) {
+        this.getLeaderMarkerList();
+        this.getLeaderMarkerNoticeList();
+        return;
+      }
+
+      if (this.IS_MARKER) {
+        await this.getMarkerNoticeList();
+        await this.getNewNotice();
+      }
+    },
+    visibleChange(visible) {
+      if (visible) {
+        if (this.IS_MARKER) {
+          this.setNoticeRead();
+        }
+        this.goToBottom();
+        this.setShortcut([]);
+      } else {
+        this.recoverShortcut();
+      }
+    },
+    goToBottom() {
+      this.$nextTick(() => {
+        this.$refs.NoticeContent.scrollTop =
+          this.$refs.NoticeContent.offsetHeight;
+      });
+    },
+    async getLeaderMarkerList() {
+      const markerId = this.$ls.get("user", { id: "" }).id;
+      const data = await leaderMarkUserList({
+        workId: this.workId,
+        subject: this.subject,
+        stage: this.curSubject.stage,
+        markerId,
+      });
+      const markers = data || [];
+      this.markers = markers.map((item) => {
+        item.selected = false;
+        return item;
+      });
+    },
+    async nextPage() {
+      if (this.fetching) return;
+      this.fetching = true;
+
+      this.current++;
+      if (this.IS_MARKER) {
+        await this.getMarkerNoticeList().catch(() => {});
+      } else {
+        await this.getLeaderMarkerNoticeList().catch(() => {});
+      }
+      this.fetching = false;
+    },
+    async getLeaderMarkerNoticeList() {
+      const sendUserId = this.$ls.get("user", { id: "" }).id;
+      const lastId = this.notices.length ? this.notices.slice(-1)[0].id : null;
+      const data = await userSendNoticeList({
+        subject: this.subject,
+        stage: this.curSubject.stage,
+        sendUserId,
+        lastId,
+        page: this.current,
+        size: this.size,
+      });
+      const notices = data.content.map((item) => {
+        item.receiveUser = JSON.parse(item.receiveUser);
+        item.relateUsers = item.receiveUser.map((user) => user.name).join(",");
+        return item;
+      });
+      notices.reverse();
+      this.hasMore = this.current + 1 < data.totalPages;
+      this.notices = [...notices, ...this.notices];
+    },
+    parseMarkerNotice(info) {
+      return {
+        ...info.message,
+        id: info.id,
+        read: info.read,
+        relateUsers: info.message.sendUserName,
+      };
+    },
+    async getMarkerNoticeList() {
+      const receiveUserId = this.$ls.get("user", { id: "" }).id;
+      const lastId = this.notices.length ? this.notices.slice(-1)[0].id : null;
+      const data = await userReceiveNoticeList({
+        subject: this.subject,
+        stage: this.curSubject.stage,
+        receiveUserId,
+        lastId,
+        page: this.current,
+        size: this.size,
+      });
+      const notices = data.content.map((item) => {
+        return this.parseMarkerNotice(item);
+      });
+      notices.reverse();
+      this.hasMore = this.current + 1 < data.totalPages;
+      this.notices = [...notices, ...this.notices];
+    },
+    async getNewNotice() {
+      this.clearSetTs();
+
+      const receiveUserId = this.$ls.get("user", { id: "" }).id;
+      const resData = await fetchReleaseUnreadNotice({
+        subject: this.subject,
+        stage: this.curSubject.stage,
+        receiveUserId,
+      }).catch(() => {});
+      const data = resData || [];
+      const noticeIds = this.notices.map((item) => item.id);
+      const validNotices = data
+        .filter((item) => !noticeIds.includes(item.id))
+        .map((item) => this.parseMarkerNotice(item));
+      if (validNotices.length) {
+        this.notices.push(...validNotices);
+        this.open();
+        this.goToBottom();
+
+        this.$nextTick(() => {
+          this.setNoticeRead();
+        });
+      }
+
+      this.addSetTime(() => {
+        this.getNewNotice();
+      }, 10 * 1000);
+    },
+    setNoticeRead() {
+      const noticeIds = this.notices
+        .filter((item) => !item.read)
+        .map((item) => item.id);
+      if (!noticeIds.length) return;
+      readNotice(noticeIds);
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    selectChange() {
+      this.userSelectAll = !this.markers.some((item) => !item.selected);
+    },
+    selectUser(user) {
+      user.selected = !user.selected;
+      this.selectChange();
+    },
+    selectAll() {
+      this.userSelectAll = !this.userSelectAll;
+      this.markers.forEach((user) => {
+        user.selected = this.userSelectAll;
+      });
+    },
+    async toSend() {
+      if (!this.content) {
+        this.$Message.error("请输入内容");
+        return;
+      }
+      if (this.content.length > 300) {
+        this.$Message.error("内容最多300个字符");
+        return;
+      }
+
+      const user = this.$ls.get("user", { id: "", name: "" });
+      const markers = this.markers
+        .filter((item) => item.selected)
+        .map((item) => {
+          return {
+            id: item.id,
+            name: item.name,
+          };
+        });
+
+      if (!markers.length) {
+        this.$Message.error("请选择评卷员");
+        return;
+      }
+
+      if (this.loading) return;
+      this.loading = true;
+
+      const data = {
+        subject: this.subject,
+        stage: this.curSubject.stage,
+        sendUserId: user.id,
+        sendUserName: user.name,
+        content: this.content,
+        markers,
+      };
+      const res = await sendNotice(data).catch(() => {});
+      this.loading = false;
+      if (!res) return;
+
+      this.content = "";
+      res.receiveUser = JSON.parse(res.receiveUser);
+      res.relateUsers = res.receiveUser.map((item) => item.name).join(",");
+      this.notices.push({ ...res });
+      this.goToBottom();
+    },
+  },
+};
+</script>

+ 6 - 6
src/modules/grading/components/ProgressLine.vue

@@ -15,16 +15,16 @@ export default {
   props: {
   props: {
     sum: {
     sum: {
       type: Number,
       type: Number,
-      default: 0
+      default: 0,
     },
     },
     current: {
     current: {
       type: Number,
       type: Number,
-      default: 0
+      default: 0,
     },
     },
     minRate: {
     minRate: {
       type: Number,
       type: Number,
-      default: 1
-    }
+      default: 1,
+    },
   },
   },
   data() {
   data() {
     return {};
     return {};
@@ -34,8 +34,8 @@ export default {
       const rate = this.sum ? (this.current / this.sum).toFixed(4) * 100 : 0;
       const rate = this.sum ? (this.current / this.sum).toFixed(4) * 100 : 0;
 
 
       return rate || this.minRate;
       return rate || this.minRate;
-    }
+    },
   },
   },
-  methods: {}
+  methods: {},
 };
 };
 </script>
 </script>

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

@@ -1,101 +1,101 @@
-<template>
-  <Modal
-    class="ribbon-set-dialog marker-modal"
-    v-model="modalIsShow"
-    title="设置"
-    :mask-closable="false"
-    @on-visible-change="visibleChange"
-  >
-    <Form
-      ref="modalFormComp"
-      class="ribbon-set-form"
-      :model="ribbonSetModal"
-      :label-width="140"
-    >
-      <FormItem label="启用键盘">
-        <i-switch
-          v-model="ribbonSetModal.keyboardMark"
-          @change="keyboardMarkChange"
-        ></i-switch>
-      </FormItem>
-      <FormItem v-if="ribbonSetModal.keyboardMark" label="需要回车提交">
-        <i-switch
-          v-model="ribbonSetModal.needEnterSubmit"
-          :disabled="IS_SCORE"
-        ></i-switch>
-      </FormItem>
-      <FormItem label="显示快捷档位导航">
-        <i-switch v-model="ribbonSetModal.fastLevelNav"></i-switch>
-      </FormItem>
-    </Form>
-
-    <div slot="footer">
-      <Button shape="circle" type="primary" @click="submit">确认</Button>
-      <Button shape="circle" @click="cancel">取消</Button>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-
-export default {
-  name: "ribbon-set-dialog",
-  data() {
-    return {
-      modalIsShow: false,
-      ribbonSetModal: {}
-    };
-  },
-  computed: {
-    ...mapState("marker", ["ribbonSet", "curSubject"]),
-    IS_SCORE() {
-      return this.curSubject.stage === "SCORE";
-    }
-  },
-  mounted() {
-    const userId = this.$ls.get("user", { id: "" }).id;
-    const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
-    const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
-    if (ribbonSet[userId]) this.setRibbonSet(ribbonSet[userId]);
-  },
-  methods: {
-    ...mapMutations("marker", ["setRibbonSet"]),
-    initData() {
-      this.ribbonSetModal = { ...this.ribbonSet };
-    },
-    visibleChange(visible) {
-      if (visible) {
-        this.initData();
-      }
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    keyboardMarkChange() {
-      if (this.ribbonSetModal.keyboardMark && this.IS_SCORE)
-        this.ribbonSetModal.needEnterSubmit = true;
-    },
-    submit() {
-      const lastFastLevelNav = this.ribbonSet.fastLevelNav;
-      const userId = this.$ls.get("user", { id: "" }).id;
-      const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
-      const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
-      ribbonSet[userId] = this.ribbonSetModal;
-      this.setRibbonSet(this.ribbonSetModal);
-      window.localStorage.setItem("ribbonSet", JSON.stringify(ribbonSet));
-      this.cancel();
-
-      if (lastFastLevelNav !== this.ribbonSetModal.fastLevelNav) {
-        setTimeout(() => {
-          const resizeEvent = new Event("resize");
-          window.dispatchEvent(resizeEvent);
-        });
-      }
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    class="ribbon-set-dialog marker-modal"
+    v-model="modalIsShow"
+    title="设置"
+    :mask-closable="false"
+    @on-visible-change="visibleChange"
+  >
+    <Form
+      ref="modalFormComp"
+      class="ribbon-set-form"
+      :model="ribbonSetModal"
+      :label-width="140"
+    >
+      <FormItem label="启用键盘">
+        <i-switch
+          v-model="ribbonSetModal.keyboardMark"
+          @change="keyboardMarkChange"
+        ></i-switch>
+      </FormItem>
+      <FormItem v-if="ribbonSetModal.keyboardMark" label="需要回车提交">
+        <i-switch
+          v-model="ribbonSetModal.needEnterSubmit"
+          :disabled="IS_SCORE"
+        ></i-switch>
+      </FormItem>
+      <FormItem label="显示快捷档位导航">
+        <i-switch v-model="ribbonSetModal.fastLevelNav"></i-switch>
+      </FormItem>
+    </Form>
+
+    <div slot="footer">
+      <Button shape="circle" type="primary" @click="submit">确认</Button>
+      <Button shape="circle" @click="cancel">取消</Button>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+
+export default {
+  name: "ribbon-set-dialog",
+  data() {
+    return {
+      modalIsShow: false,
+      ribbonSetModal: {},
+    };
+  },
+  computed: {
+    ...mapState("marker", ["ribbonSet", "curSubject"]),
+    IS_SCORE() {
+      return this.curSubject.stage === "SCORE";
+    },
+  },
+  mounted() {
+    const userId = this.$ls.get("user", { id: "" }).id;
+    const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
+    const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
+    if (ribbonSet[userId]) this.setRibbonSet(ribbonSet[userId]);
+  },
+  methods: {
+    ...mapMutations("marker", ["setRibbonSet"]),
+    initData() {
+      this.ribbonSetModal = { ...this.ribbonSet };
+    },
+    visibleChange(visible) {
+      if (visible) {
+        this.initData();
+      }
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    keyboardMarkChange() {
+      if (this.ribbonSetModal.keyboardMark && this.IS_SCORE)
+        this.ribbonSetModal.needEnterSubmit = true;
+    },
+    submit() {
+      const lastFastLevelNav = this.ribbonSet.fastLevelNav;
+      const userId = this.$ls.get("user", { id: "" }).id;
+      const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
+      const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
+      ribbonSet[userId] = this.ribbonSetModal;
+      this.setRibbonSet(this.ribbonSetModal);
+      window.localStorage.setItem("ribbonSet", JSON.stringify(ribbonSet));
+      this.cancel();
+
+      if (lastFastLevelNav !== this.ribbonSetModal.fastLevelNav) {
+        setTimeout(() => {
+          const resizeEvent = new Event("resize");
+          window.dispatchEvent(resizeEvent);
+        });
+      }
+    },
+  },
+};
+</script>

+ 127 - 129
src/modules/grading/leader/LeaderAnalysisExport.vue

@@ -1,129 +1,127 @@
-<template>
-  <div class="leader-analysis-export analysis-export-modal">
-    <div class="print-box">
-      <h1>
-        分档详情数据
-      </h1>
-      <div class="quality-info">
-        <p>科目:{{ pageInfo.subjectName }}</p>
-        <p>考区:{{ pageInfo.areaName }}</p>
-        <p>截止时间:{{ currentTime }}</p>
-      </div>
-      <div class="print-chart">
-        <div class="print-chart-title">详细数值表:</div>
-        <table class="export-table">
-          <tr>
-            <th>档位</th>
-            <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, index) in chartData.levelData" :key="index">
-            <td>{{ level.code | levelNameFilter }}</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>
-            <td class="td-bl">{{ level.gcount }}</td>
-            <td>{{ level.gpercent }}%</td>
-            <td>{{ level.pt }}%</td>
-          </tr>
-        </table>
-      </div>
-      <div class="print-chart" v-if="chartData.lineChartData">
-        <div class="print-chart-title">考区试卷数量分布图</div>
-        <div class="print-chart-body">
-          <echart-render
-            :chart-data="chartData.lineChartData"
-            :animation-is-open="false"
-            chart-type="darkLines"
-            ref="lineChart"
-            v-if="!showImg"
-          ></echart-render>
-          <img src="" ref="lineChartImg" v-show="showImg" />
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import EchartRender from "@/components/EchartRender";
-import { download, formatDate } from "@/plugins/utils";
-import html2canvas from "html2canvas";
-
-export default {
-  name: "leader-analysis-export",
-  components: { EchartRender },
-  props: {
-    chartData: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    pageInfo: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      currentTime: formatDate(),
-      showImg: false
-    };
-  },
-  mounted() {
-    this.$nextTick(() => {
-      this.$refs.lineChartImg.src = this.$refs.lineChart.getDataURL({
-        backgroundColor: "#fff"
-      });
-
-      this.showImg = true;
-      this.$nextTick(() => {
-        this.toExport();
-      });
-    });
-  },
-  methods: {
-    async toExport() {
-      const canvas = await html2canvas(this.$el.childNodes[0], {
-        allowTaint: true
-      }).catch(() => {});
-
-      if (!canvas) {
-        this.$emit("on-exported", false);
-        return;
-      }
-
-      let result = true;
-      const user = this.$ls.get("user", { token: "", id: "" });
-      await download({
-        type: "post",
-        url: `${this.GLOBAL.domain}/api/exportPdf`,
-        header: { Authorization: user.token, userId: user.id },
-        data: {
-          content: [canvas.toDataURL().split(",")[1]]
-        },
-        fileName: `${this.pageInfo.subjectName}-${this.pageInfo.areaName}-分档详情分析.pdf`
-      }).catch(() => {
-        result = false;
-      });
-
-      this.$emit("on-exported", result);
-    }
-  }
-};
-</script>
+<template>
+  <div class="leader-analysis-export analysis-export-modal">
+    <div class="print-box">
+      <h1>分档详情数据</h1>
+      <div class="quality-info">
+        <p>科目:{{ pageInfo.subjectName }}</p>
+        <p>考区:{{ pageInfo.areaName }}</p>
+        <p>截止时间:{{ currentTime }}</p>
+      </div>
+      <div class="print-chart">
+        <div class="print-chart-title">详细数值表:</div>
+        <table class="export-table">
+          <tr>
+            <th>档位</th>
+            <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, index) in chartData.levelData" :key="index">
+            <td>{{ level.code | levelNameFilter }}</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>
+            <td class="td-bl">{{ level.gcount }}</td>
+            <td>{{ level.gpercent }}%</td>
+            <td>{{ level.pt }}%</td>
+          </tr>
+        </table>
+      </div>
+      <div class="print-chart" v-if="chartData.lineChartData">
+        <div class="print-chart-title">考区试卷数量分布图</div>
+        <div class="print-chart-body">
+          <echart-render
+            :chart-data="chartData.lineChartData"
+            :animation-is-open="false"
+            chart-type="darkLines"
+            ref="lineChart"
+            v-if="!showImg"
+          ></echart-render>
+          <img src="" ref="lineChartImg" v-show="showImg" />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import EchartRender from "@/components/EchartRender";
+import { download, formatDate } from "@/plugins/utils";
+import html2canvas from "html2canvas";
+
+export default {
+  name: "leader-analysis-export",
+  components: { EchartRender },
+  props: {
+    chartData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    pageInfo: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      currentTime: formatDate(),
+      showImg: false,
+    };
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.$refs.lineChartImg.src = this.$refs.lineChart.getDataURL({
+        backgroundColor: "#fff",
+      });
+
+      this.showImg = true;
+      this.$nextTick(() => {
+        this.toExport();
+      });
+    });
+  },
+  methods: {
+    async toExport() {
+      const canvas = await html2canvas(this.$el.childNodes[0], {
+        allowTaint: true,
+      }).catch(() => {});
+
+      if (!canvas) {
+        this.$emit("on-exported", false);
+        return;
+      }
+
+      let result = true;
+      const user = this.$ls.get("user", { token: "", id: "" });
+      await download({
+        type: "post",
+        url: `${this.GLOBAL.domain}/api/exportPdf`,
+        header: { Authorization: user.token, userId: user.id },
+        data: {
+          content: [canvas.toDataURL().split(",")[1]],
+        },
+        fileName: `${this.pageInfo.subjectName}-${this.pageInfo.areaName}-分档详情分析.pdf`,
+      }).catch(() => {
+        result = false;
+      });
+
+      this.$emit("on-exported", result);
+    },
+  },
+};
+</script>

+ 766 - 764
src/modules/grading/leader/LeaderGrading.vue

@@ -1,764 +1,766 @@
-<template>
-  <div class="marker-grading">
-    <marker-header
-      v-if="dataReady"
-      ref="MarkerHeader"
-      show-select-all
-      @area-change="areaChange"
-      @step-change="stepChange"
-      @page-set-change="pageSetChange"
-      @to-progress="toProgress"
-      @to-select-all="toSelectAll"
-      @to-history="toHistory"
-      @to-standard="toStandard"
-      @to-statistics="toStatistics"
-      @on-code-search="serachPaperByCode"
-      @on-mark-search="serachMarkPaper"
-    ></marker-header>
-
-    <div
-      v-if="dataReady"
-      :class="[
-        'marker-action',
-        'dark-mark',
-        { 'marker-action-fullscreen': isFullscreenMarking }
-      ]"
-    >
-      <template v-if="curPaper && curPaper.id">
-        <grade-action-rough
-          v-if="IS_ROUGH_THIN_LEVEL"
-          ref="GradeAction"
-          :cur-paper-or-task="curPaper"
-          :levels="levels"
-          :params-set="paramsSet"
-          :key="paperKey"
-          :is-batch-action="!!multipleGradingList.length"
-          @on-leader-level="leaderSelectLevel"
-          @on-batch-level="multipleSelectLevel"
-          @on-leader-change-level="leaderChangeLevel"
-        ></grade-action-rough>
-        <grade-action
-          v-else
-          ref="GradeAction"
-          :cur-paper-or-task="curPaper"
-          :levels="levels"
-          :params-set="paramsSet"
-          :key="paperKey"
-          :is-batch-action="!!multipleGradingList.length"
-          @on-leader-level="leaderSelectLevel"
-          @on-batch-level="multipleSelectLevel"
-        ></grade-action>
-      </template>
-      <grade-ribbon ref="GradeRibbon"></grade-ribbon>
-    </div>
-
-    <div
-      :class="['marker-body', { 'marker-body-low': ribbonSet.fastLevelNav }]"
-    >
-      <div :class="markerImageListClasses" v-if="papers.length">
-        <div
-          v-for="(paper, index) in papers"
-          :key="paper.key"
-          :class="[
-            'marker-image-item',
-            {
-              'marker-image-item-act': curPaperIndex === index
-            }
-          ]"
-        >
-          <div class="marker-image-content">
-            <marker-image-view
-              ref="MarkerImageView"
-              :data="paper"
-              :can-select="ACTION_CAN_BATCH"
-              :stage="curSubject.stage"
-              @to-review="toReview"
-              @to-select="selectMultiplePaper"
-            ></marker-image-view>
-          </div>
-        </div>
-      </div>
-      <div v-else class="marker-image-none">暂无数据</div>
-    </div>
-
-    <!-- LeaderStatistics -->
-    <leader-statistics
-      :question-id="filter.questionId"
-      @on-close="statisticsClose"
-      ref="LeaderStatistics"
-    ></leader-statistics>
-    <!-- LeaderProgress -->
-    <leader-progress
-      ref="LeaderProgress"
-      @on-close="progressClose"
-    ></leader-progress>
-    <!-- MarkerHistory -->
-    <marker-history
-      :question-id="filter.questionId"
-      :stage="curSubject.stage"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers, 'history');
-        }
-      "
-      @on-close="historyClose"
-      @on-mark="historyMarkChange"
-      ref="MarkerHistory"
-    ></marker-history>
-    <!-- MarkerStandard -->
-    <marker-standard
-      :question-id="filter.questionId"
-      :levels="levels"
-      :stage="curSubject.stage"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers, 'sample');
-        }
-      "
-      @on-close="standardClose"
-      ref="MarkerStandard"
-      v-if="levels.length && filter.questionId"
-    ></marker-standard>
-    <!-- modify-leader-grading -->
-    <modify-leader-grading
-      class="marker-modal"
-      :level-info="levelInfo"
-      :markers="markers"
-      :stage="curSubject.stage"
-      @modified="leaderGradingSuccess"
-      ref="ModifyLeaderGrading"
-    ></modify-leader-grading>
-    <!-- image-preview -->
-    <simple-image-preview
-      class="grading-operation-image-preview"
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      @on-close="imagePreviewClose"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-    <!-- carousel paper review -->
-    <simple-image-preview
-      class="grading-operation-image-preview"
-      :cur-image="curPaper"
-      @on-prev="toCarousePaper('prev')"
-      @on-next="toCarousePaper('next')"
-      @on-close="carouseImagePreviewClose"
-      ref="CarouselPapersPreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-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 GradeActionRough from "../components/GradeActionRough";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import ModifyLeaderGrading from "../components/ModifyLeaderGrading";
-import GradeRibbon from "../components/GradeRibbon";
-import { levelNameTransform } from "@/plugins/utils";
-
-import {
-  paperList,
-  markTaskPaperList,
-  markLeaderLevelStatData,
-  workLevelList,
-  taskSnSearch,
-  subjectDetail,
-  markHistoryList,
-  getParamsSet,
-  markStepChangeLevel,
-  leaderGradingPaper
-} from "@/api";
-
-export default {
-  name: "leader-grading",
-  components: {
-    MarkerHeader,
-    MarkerImageView,
-    MarkerHistory,
-    MarkerStandard,
-    LeaderProgress,
-    LeaderStatistics,
-    GradeAction,
-    GradeActionRough,
-    GradeRibbon,
-    SimpleImagePreview,
-    ModifyLeaderGrading
-  },
-  data() {
-    return {
-      filter: {
-        questionId: "",
-        sort: "secretNumber"
-      },
-      typeFilter: {
-        done: {
-          level: ""
-        },
-        reject: {
-          reject: true
-        },
-        arbitrate: {
-          arbi: true
-        }
-      },
-      dataReady: false,
-      speFilter: null,
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      levels: [],
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      paperKey: "",
-      // leader-grade
-      levelInfo: {},
-      markers: [],
-      // carousel paper review,
-      carouselType: "",
-      carouselPapers: [],
-      curCarouselPaperIndex: 0,
-      isFullscreenMarking: false,
-      // multiple grading
-      multiplebtnClicked: false,
-      multipleGradingList: [],
-      // 科组长权限
-      markLeaderOnlyRight: null
-    };
-  },
-  computed: {
-    ...mapState("marker", [
-      "paramsSet",
-      "page",
-      "steps",
-      "curStep",
-      "curArea",
-      "curSubject",
-      "ribbonSet"
-    ]),
-    markerImageListClasses() {
-      return ["marker-image-list", `marker-image-list-${this.page.size}`];
-    },
-    IS_TEST() {
-      return this.curSubject.test === 2;
-    },
-    IS_ROUGH_THIN_LEVEL() {
-      return (
-        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
-      );
-    },
-    ACTION_CAN_BATCH() {
-      return (
-        this.curStep.type === "done" && !this.paramsSet.collectConfig.paperStage
-      );
-    }
-  },
-  created() {
-    this.markLeaderOnlyRight = this.$ls.get("user", {
-      markLeaderOnlyRight: null
-    }).markLeaderOnlyRight;
-
-    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.setCurUserRoleType(curUserRoleType);
-    this.initData();
-    this.subject = this.subjectId.split("-")[1];
-  },
-  methods: {
-    ...mapMutations("marker", [
-      "setParamSet",
-      "setPage",
-      "setSteps",
-      "setCurStep",
-      "setCurArea",
-      "setCurSubject",
-      "setCurUserRoleType",
-      "setShortcut",
-      "clearState"
-    ]),
-    async initData() {
-      this.dataReady = false;
-      await this.getSubjectDetail();
-      await this.getParamsSetInfo();
-      await this.getWorkLevels();
-      this.dataReady = true;
-    },
-    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.clearMultiplePaper();
-
-      let data = {
-        data: [],
-        totalCount: 0,
-        pageCount: 0
-      };
-      if (this.speFilter) {
-        const { type, params } = this.speFilter;
-        if (type === "mark") {
-          data = await this.getMarkList(params);
-        }
-      } else {
-        data = await this.getCommonList();
-      }
-
-      this.papers = data.data.map(paper => {
-        paper.key = this.$randomCode();
-        paper.title = `NO.${paper.sn}`;
-        paper.selected = false;
-        return paper;
-      });
-
-      this.setPage({
-        total: data.totalCount,
-        totalPage: data.pageCount
-      });
-    },
-    async getCommonList() {
-      const datas = {
-        ...this.filter,
-        ...this.typeFilter[this.curStep.type],
-        page: this.page.current - 1,
-        size: this.page.size
-      };
-      if (this.curStep.type === "done") datas.level = this.curStep.name;
-
-      const data = await paperList(datas);
-      return data;
-    },
-    async getMarkList(params) {
-      const userId = this.$ls.get("user", { id: "" }).id;
-      const markDisabled = userId !== params.markerId;
-      const datas = {
-        ...params,
-        workId: this.workId,
-        subject: this.subject,
-        stage: this.curSubject.stage,
-        page: this.page.current - 1,
-        size: this.page.size
-      };
-
-      const data = await markTaskPaperList(datas);
-      data.data.forEach(item => {
-        item.markDisabled = markDisabled;
-        item.mark = true;
-      });
-      return data;
-    },
-    async toPage(page) {
-      this.setPage({
-        current: page
-      });
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async getStepLevels() {
-      const data = await markLeaderLevelStatData(
-        this.subjectId,
-        this.filter.questionId,
-        this.curSubject.stage
-      );
-      const undoIndex = data.findIndex(item => item.id === null);
-      let otherStep = [];
-      let undo = {
-        count: 0,
-        rejected: 0,
-        arbitrated: 0
-      };
-      if (undoIndex !== -1) {
-        undo = { ...data[undoIndex] };
-        data.splice(undoIndex, 1);
-      }
-
-      if (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 => {
-        return {
-          ...item,
-          name: item.id,
-          type: "done"
-        };
-      });
-      this.setSteps({ levelStep, otherStep });
-
-      if (!this.curStep.name) {
-        const firstStep = otherStep.find(item => item.count);
-        const curStep = firstStep || levelStep[0];
-        this.setCurStep(curStep);
-      } else {
-        const curStep = [...levelStep, ...otherStep].find(
-          item => item.name === this.curStep.name
-        );
-        this.setCurStep(curStep);
-      }
-    },
-    async getWorkLevels() {
-      const data = await workLevelList(this.workId, this.curSubject.stage);
-      this.levels = data || [];
-    },
-    async pageSetChange() {
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async stepChange(step) {
-      this.speFilter = null;
-      this.setCurStep(step);
-      this.setPage({ current: 1 });
-      this.isFullscreenMarking = false;
-      await this.getList();
-      this.getStepLevels();
-      if (this.papers.length) {
-        this.selectPaper(0);
-      } else {
-        this.curPaper = {};
-      }
-    },
-    async areaChange(curArea) {
-      this.speFilter = null;
-      this.setCurArea(curArea);
-      this.filter.questionId = curArea.id;
-      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;
-      this.multipleGradingList = this.papers.filter(paper => paper.selected);
-    },
-    clearMultiplePaper() {
-      this.multipleGradingList = [];
-      this.papers.forEach(paper => {
-        paper.selected = false;
-      });
-      this.$refs.MarkerHeader.changeAllSelect(false);
-    },
-    checkPapersIsSelectLevel(levelName, papers) {
-      const firstLevel = papers[0].level;
-      const hasOtherLevel = this.papers.some(item => item.level !== firstLevel);
-      return hasOtherLevel ? false : firstLevel === levelName;
-    },
-    async multipleSelectLevel(level) {
-      if (!this.multipleGradingList.length) return;
-
-      if (this.checkPapersIsSelectLevel(level.name, this.multipleGradingList)) {
-        this.$Message.error("已选试卷档位和设置档位一样!");
-        return;
-      }
-
-      if (this.multiplebtnClicked) return;
-      this.multiplebtnClicked = true;
-
-      const data = await markHistoryList(
-        this.multipleGradingList[0].id,
-        this.curSubject.stage
-      ).catch(() => {
-        this.multiplebtnClicked = false;
-      });
-
-      if (!data) return;
-
-      const markers = data.map(item => {
-        return {
-          id: item.markerId,
-          name: item.marker
-        };
-      });
-      const levelInfo = {
-        paperIds: this.multipleGradingList.map(item => item.id).join(),
-        curLevel: this.curStep.name,
-        selectedLevel: level.name,
-        markLeaderOnlyRight: this.markLeaderOnlyRight
-      };
-
-      await this.leaderSelectLevel(levelInfo, markers).catch(() => {});
-      this.multiplebtnClicked = false;
-    },
-    // paper view action
-    toReview(data) {
-      this.setShortcut(["action"]);
-      this.isFullscreenMarking = true;
-      this.clearMultiplePaper();
-      this.curPaperIndex = this.papers.findIndex(item => item.id === data.id);
-      this.curPaper = Object.assign({}, this.papers[this.curPaperIndex], data);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      this.paperKey = this.$randomCode();
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        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("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.page.current === this.page.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.setPage({ current: this.page.current + 1 });
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toActionNextPaper() {
-      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 serachPaperByCode(params) {
-      this.speFilter = null;
-      const data = await taskSnSearch(
-        params.codeType,
-        params.code,
-        this.filter.questionId,
-        this.curSubject.stage
-      );
-      if (!data) {
-        this.$Message.error("没有查找到结果!");
-        return;
-      }
-      data.title = `NO.${data.sn}`;
-      data.key = this.$randomCode();
-      this.papers = [data];
-      this.setPage({ current: 1, total: 1, totalPage: 1 });
-      this.selectPaper(0);
-    },
-    serachMarkPaper(data) {
-      // console.log(data);
-      this.speFilter = { type: data.type, params: data.params };
-      this.toPage(1);
-    },
-    async leaderSelectLevel(levelInfo, markers) {
-      // 唯一权限时,直接操作
-      if (levelInfo.markLeaderOnlyRight && !levelInfo.leaderConfirm) {
-        const datas = {
-          action: levelInfo.markLeaderOnlyRight.action,
-          level: levelInfo.selectedLevel,
-          originLevel: levelInfo.curLevel,
-          paperIds: levelInfo.paperIds,
-          stage: this.curSubject.stage,
-          leaderConfirm: levelInfo.leaderConfirm
-        };
-        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) {
-      this.getStepLevels();
-
-      if (this.carouselType) {
-        this.$refs.CarouselPapersPreview.cancel();
-        this.$refs.MarkerHistory.updatePapers();
-        return;
-      }
-
-      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();
-      }
-    },
-    leaderChangeLevel(levelInfo) {
-      const content = `确定申请由${levelNameTransform(
-        levelInfo.curLevel
-      )}档改为${levelNameTransform(
-        levelInfo.selectedLevel
-      )}档,并打回给所有老师吗?`;
-      this.$Modal.confirm({
-        content,
-        width: 450,
-        onOk: async () => {
-          await markStepChangeLevel({
-            subjectId: this.subjectId,
-            paperId: levelInfo.paperId,
-            level: levelInfo.selectedLevel,
-            userId: this.$ls.get("user", { id: "" }).id
-          });
-          this.$Message.success("申请改档成功!");
-          this.getStepLevels();
-          if (this.carouselType) {
-            this.$refs.CarouselPapersPreview.cancel();
-            this.$refs.MarkerHistory.updatePapers();
-          } else {
-            // this.toActionNextPaper();
-            // 调档之后,试卷还在当前类别中,应该调用下一张
-            this.toNextPaper();
-          }
-        }
-      });
-    },
-    imagePreviewClose() {
-      this.isFullscreenMarking = false;
-      this.setShortcut(["page", "action"]);
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers, type) {
-      this.carouselType = type;
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-        this.setShortcut(["action"]);
-      });
-    },
-    selectCarouselPaper(index) {
-      this.paperKey = this.$randomCode();
-      this.curCarouselPaperIndex = index;
-      this.curPaper = { ...this.carouselPapers[index] };
-    },
-    toCarousePaper(type) {
-      if (type === "prev" && this.curCarouselPaperIndex > 0) {
-        this.curCarouselPaperIndex--;
-      } else if (
-        type === "next" &&
-        this.curCarouselPaperIndex < this.carouselPapers.length - 1
-      ) {
-        this.curCarouselPaperIndex++;
-      } else {
-        return;
-      }
-      this.selectCarouselPaper(this.curCarouselPaperIndex);
-    },
-    carouseImagePreviewClose() {
-      this.setShortcut([]);
-      this.isFullscreenMarking = false;
-      this.carouselType = "";
-    },
-    // header
-    toHistory() {
-      this.setShortcut([]);
-      this.$refs.MarkerHistory.open();
-    },
-    historyClose() {
-      this.selectPaper(this.curPaperIndex);
-      this.setShortcut(["page", "action"]);
-    },
-    historyMarkChange() {
-      this.getStepLevels();
-      this.getList();
-      this.$refs.MarkerHistory.updatePapers();
-    },
-    toStandard() {
-      this.setShortcut([]);
-      this.$refs.MarkerStandard.open();
-    },
-    async standardClose() {
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-      this.getStepLevels();
-      this.setShortcut(["page", "action"]);
-    },
-    toProgress() {
-      this.setShortcut([]);
-      this.$refs.LeaderProgress.open();
-    },
-    progressClose() {
-      this.setShortcut(["page", "action"]);
-    },
-    toSelectAll(allSelected) {
-      this.$refs.MarkerImageView.forEach(item => {
-        item.changeSelect(allSelected);
-      });
-    },
-    toStatistics() {
-      this.setShortcut([]);
-      this.$refs.LeaderStatistics.open();
-    },
-    statisticsClose() {
-      this.setShortcut(["page", "action"]);
-    }
-  },
-  beforeDestroy() {
-    this.clearState();
-  }
-};
-</script>
+<template>
+  <div class="marker-grading">
+    <marker-header
+      v-if="dataReady"
+      ref="MarkerHeader"
+      show-select-all
+      @area-change="areaChange"
+      @step-change="stepChange"
+      @page-set-change="pageSetChange"
+      @to-progress="toProgress"
+      @to-select-all="toSelectAll"
+      @to-history="toHistory"
+      @to-standard="toStandard"
+      @to-statistics="toStatistics"
+      @on-code-search="serachPaperByCode"
+      @on-mark-search="serachMarkPaper"
+    ></marker-header>
+
+    <div
+      v-if="dataReady"
+      :class="[
+        'marker-action',
+        'dark-mark',
+        { 'marker-action-fullscreen': isFullscreenMarking },
+      ]"
+    >
+      <template v-if="curPaper && curPaper.id">
+        <grade-action-rough
+          v-if="IS_ROUGH_THIN_LEVEL"
+          ref="GradeAction"
+          :cur-paper-or-task="curPaper"
+          :levels="levels"
+          :params-set="paramsSet"
+          :key="paperKey"
+          :is-batch-action="!!multipleGradingList.length"
+          @on-leader-level="leaderSelectLevel"
+          @on-batch-level="multipleSelectLevel"
+          @on-leader-change-level="leaderChangeLevel"
+        ></grade-action-rough>
+        <grade-action
+          v-else
+          ref="GradeAction"
+          :cur-paper-or-task="curPaper"
+          :levels="levels"
+          :params-set="paramsSet"
+          :key="paperKey"
+          :is-batch-action="!!multipleGradingList.length"
+          @on-leader-level="leaderSelectLevel"
+          @on-batch-level="multipleSelectLevel"
+        ></grade-action>
+      </template>
+      <grade-ribbon ref="GradeRibbon"></grade-ribbon>
+    </div>
+
+    <div
+      :class="['marker-body', { 'marker-body-low': ribbonSet.fastLevelNav }]"
+    >
+      <div :class="markerImageListClasses" v-if="papers.length">
+        <div
+          v-for="(paper, index) in papers"
+          :key="paper.key"
+          :class="[
+            'marker-image-item',
+            {
+              'marker-image-item-act': curPaperIndex === index,
+            },
+          ]"
+        >
+          <div class="marker-image-content">
+            <marker-image-view
+              ref="MarkerImageView"
+              :data="paper"
+              :can-select="ACTION_CAN_BATCH"
+              :stage="curSubject.stage"
+              @to-review="toReview"
+              @to-select="selectMultiplePaper"
+            ></marker-image-view>
+          </div>
+        </div>
+      </div>
+      <div v-else class="marker-image-none">暂无数据</div>
+    </div>
+
+    <!-- LeaderStatistics -->
+    <leader-statistics
+      :question-id="filter.questionId"
+      @on-close="statisticsClose"
+      ref="LeaderStatistics"
+    ></leader-statistics>
+    <!-- LeaderProgress -->
+    <leader-progress
+      ref="LeaderProgress"
+      @on-close="progressClose"
+    ></leader-progress>
+    <!-- MarkerHistory -->
+    <marker-history
+      :question-id="filter.questionId"
+      :stage="curSubject.stage"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers, 'history');
+        }
+      "
+      @on-close="historyClose"
+      @on-mark="historyMarkChange"
+      ref="MarkerHistory"
+    ></marker-history>
+    <!-- MarkerStandard -->
+    <marker-standard
+      :question-id="filter.questionId"
+      :levels="levels"
+      :stage="curSubject.stage"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers, 'sample');
+        }
+      "
+      @on-close="standardClose"
+      ref="MarkerStandard"
+      v-if="levels.length && filter.questionId"
+    ></marker-standard>
+    <!-- modify-leader-grading -->
+    <modify-leader-grading
+      class="marker-modal"
+      :level-info="levelInfo"
+      :markers="markers"
+      :stage="curSubject.stage"
+      @modified="leaderGradingSuccess"
+      ref="ModifyLeaderGrading"
+    ></modify-leader-grading>
+    <!-- image-preview -->
+    <simple-image-preview
+      class="grading-operation-image-preview"
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      @on-close="imagePreviewClose"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+    <!-- carousel paper review -->
+    <simple-image-preview
+      class="grading-operation-image-preview"
+      :cur-image="curPaper"
+      @on-prev="toCarousePaper('prev')"
+      @on-next="toCarousePaper('next')"
+      @on-close="carouseImagePreviewClose"
+      ref="CarouselPapersPreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+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 GradeActionRough from "../components/GradeActionRough";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import ModifyLeaderGrading from "../components/ModifyLeaderGrading";
+import GradeRibbon from "../components/GradeRibbon";
+import { levelNameTransform } from "@/plugins/utils";
+
+import {
+  paperList,
+  markTaskPaperList,
+  markLeaderLevelStatData,
+  workLevelList,
+  taskSnSearch,
+  subjectDetail,
+  markHistoryList,
+  getParamsSet,
+  markStepChangeLevel,
+  leaderGradingPaper,
+} from "@/api";
+
+export default {
+  name: "leader-grading",
+  components: {
+    MarkerHeader,
+    MarkerImageView,
+    MarkerHistory,
+    MarkerStandard,
+    LeaderProgress,
+    LeaderStatistics,
+    GradeAction,
+    GradeActionRough,
+    GradeRibbon,
+    SimpleImagePreview,
+    ModifyLeaderGrading,
+  },
+  data() {
+    return {
+      filter: {
+        questionId: "",
+        sort: "secretNumber",
+      },
+      typeFilter: {
+        done: {
+          level: "",
+        },
+        reject: {
+          reject: true,
+        },
+        arbitrate: {
+          arbi: true,
+        },
+      },
+      dataReady: false,
+      speFilter: null,
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      levels: [],
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      paperKey: "",
+      // leader-grade
+      levelInfo: {},
+      markers: [],
+      // carousel paper review,
+      carouselType: "",
+      carouselPapers: [],
+      curCarouselPaperIndex: 0,
+      isFullscreenMarking: false,
+      // multiple grading
+      multiplebtnClicked: false,
+      multipleGradingList: [],
+      // 科组长权限
+      markLeaderOnlyRight: null,
+    };
+  },
+  computed: {
+    ...mapState("marker", [
+      "paramsSet",
+      "page",
+      "steps",
+      "curStep",
+      "curArea",
+      "curSubject",
+      "ribbonSet",
+    ]),
+    markerImageListClasses() {
+      return ["marker-image-list", `marker-image-list-${this.page.size}`];
+    },
+    IS_TEST() {
+      return this.curSubject.test === 2;
+    },
+    IS_ROUGH_THIN_LEVEL() {
+      return (
+        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
+      );
+    },
+    ACTION_CAN_BATCH() {
+      return (
+        this.curStep.type === "done" && !this.paramsSet.collectConfig.paperStage
+      );
+    },
+  },
+  created() {
+    this.markLeaderOnlyRight = this.$ls.get("user", {
+      markLeaderOnlyRight: null,
+    }).markLeaderOnlyRight;
+
+    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    this.setCurUserRoleType(curUserRoleType);
+    this.initData();
+    this.subject = this.subjectId.split("-")[1];
+  },
+  methods: {
+    ...mapMutations("marker", [
+      "setParamSet",
+      "setPage",
+      "setSteps",
+      "setCurStep",
+      "setCurArea",
+      "setCurSubject",
+      "setCurUserRoleType",
+      "setShortcut",
+      "clearState",
+    ]),
+    async initData() {
+      this.dataReady = false;
+      await this.getSubjectDetail();
+      await this.getParamsSetInfo();
+      await this.getWorkLevels();
+      this.dataReady = true;
+    },
+    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.clearMultiplePaper();
+
+      let data = {
+        data: [],
+        totalCount: 0,
+        pageCount: 0,
+      };
+      if (this.speFilter) {
+        const { type, params } = this.speFilter;
+        if (type === "mark") {
+          data = await this.getMarkList(params);
+        }
+      } else {
+        data = await this.getCommonList();
+      }
+
+      this.papers = data.data.map((paper) => {
+        paper.key = this.$randomCode();
+        paper.title = `NO.${paper.sn}`;
+        paper.selected = false;
+        return paper;
+      });
+
+      this.setPage({
+        total: data.totalCount,
+        totalPage: data.pageCount,
+      });
+    },
+    async getCommonList() {
+      const datas = {
+        ...this.filter,
+        ...this.typeFilter[this.curStep.type],
+        page: this.page.current - 1,
+        size: this.page.size,
+      };
+      if (this.curStep.type === "done") datas.level = this.curStep.name;
+
+      const data = await paperList(datas);
+      return data;
+    },
+    async getMarkList(params) {
+      const userId = this.$ls.get("user", { id: "" }).id;
+      const markDisabled = userId !== params.markerId;
+      const datas = {
+        ...params,
+        workId: this.workId,
+        subject: this.subject,
+        stage: this.curSubject.stage,
+        page: this.page.current - 1,
+        size: this.page.size,
+      };
+
+      const data = await markTaskPaperList(datas);
+      data.data.forEach((item) => {
+        item.markDisabled = markDisabled;
+        item.mark = true;
+      });
+      return data;
+    },
+    async toPage(page) {
+      this.setPage({
+        current: page,
+      });
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async getStepLevels() {
+      const data = await markLeaderLevelStatData(
+        this.subjectId,
+        this.filter.questionId,
+        this.curSubject.stage
+      );
+      const undoIndex = data.findIndex((item) => item.id === null);
+      let otherStep = [];
+      let undo = {
+        count: 0,
+        rejected: 0,
+        arbitrated: 0,
+      };
+      if (undoIndex !== -1) {
+        undo = { ...data[undoIndex] };
+        data.splice(undoIndex, 1);
+      }
+
+      if (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) => {
+        return {
+          ...item,
+          name: item.id,
+          type: "done",
+        };
+      });
+      this.setSteps({ levelStep, otherStep });
+
+      if (!this.curStep.name) {
+        const firstStep = otherStep.find((item) => item.count);
+        const curStep = firstStep || levelStep[0];
+        this.setCurStep(curStep);
+      } else {
+        const curStep = [...levelStep, ...otherStep].find(
+          (item) => item.name === this.curStep.name
+        );
+        this.setCurStep(curStep);
+      }
+    },
+    async getWorkLevels() {
+      const data = await workLevelList(this.workId, this.curSubject.stage);
+      this.levels = data || [];
+    },
+    async pageSetChange() {
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async stepChange(step) {
+      this.speFilter = null;
+      this.setCurStep(step);
+      this.setPage({ current: 1 });
+      this.isFullscreenMarking = false;
+      await this.getList();
+      this.getStepLevels();
+      if (this.papers.length) {
+        this.selectPaper(0);
+      } else {
+        this.curPaper = {};
+      }
+    },
+    async areaChange(curArea) {
+      this.speFilter = null;
+      this.setCurArea(curArea);
+      this.filter.questionId = curArea.id;
+      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;
+      this.multipleGradingList = this.papers.filter((paper) => paper.selected);
+    },
+    clearMultiplePaper() {
+      this.multipleGradingList = [];
+      this.papers.forEach((paper) => {
+        paper.selected = false;
+      });
+      this.$refs.MarkerHeader.changeAllSelect(false);
+    },
+    checkPapersIsSelectLevel(levelName, papers) {
+      const firstLevel = papers[0].level;
+      const hasOtherLevel = this.papers.some(
+        (item) => item.level !== firstLevel
+      );
+      return hasOtherLevel ? false : firstLevel === levelName;
+    },
+    async multipleSelectLevel(level) {
+      if (!this.multipleGradingList.length) return;
+
+      if (this.checkPapersIsSelectLevel(level.name, this.multipleGradingList)) {
+        this.$Message.error("已选试卷档位和设置档位一样!");
+        return;
+      }
+
+      if (this.multiplebtnClicked) return;
+      this.multiplebtnClicked = true;
+
+      const data = await markHistoryList(
+        this.multipleGradingList[0].id,
+        this.curSubject.stage
+      ).catch(() => {
+        this.multiplebtnClicked = false;
+      });
+
+      if (!data) return;
+
+      const markers = data.map((item) => {
+        return {
+          id: item.markerId,
+          name: item.marker,
+        };
+      });
+      const levelInfo = {
+        paperIds: this.multipleGradingList.map((item) => item.id).join(),
+        curLevel: this.curStep.name,
+        selectedLevel: level.name,
+        markLeaderOnlyRight: this.markLeaderOnlyRight,
+      };
+
+      await this.leaderSelectLevel(levelInfo, markers).catch(() => {});
+      this.multiplebtnClicked = false;
+    },
+    // paper view action
+    toReview(data) {
+      this.setShortcut(["action"]);
+      this.isFullscreenMarking = true;
+      this.clearMultiplePaper();
+      this.curPaperIndex = this.papers.findIndex((item) => item.id === data.id);
+      this.curPaper = Object.assign({}, this.papers[this.curPaperIndex], data);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      this.paperKey = this.$randomCode();
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        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("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.page.current === this.page.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.setPage({ current: this.page.current + 1 });
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toActionNextPaper() {
+      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 serachPaperByCode(params) {
+      this.speFilter = null;
+      const data = await taskSnSearch(
+        params.codeType,
+        params.code,
+        this.filter.questionId,
+        this.curSubject.stage
+      );
+      if (!data) {
+        this.$Message.error("没有查找到结果!");
+        return;
+      }
+      data.title = `NO.${data.sn}`;
+      data.key = this.$randomCode();
+      this.papers = [data];
+      this.setPage({ current: 1, total: 1, totalPage: 1 });
+      this.selectPaper(0);
+    },
+    serachMarkPaper(data) {
+      // console.log(data);
+      this.speFilter = { type: data.type, params: data.params };
+      this.toPage(1);
+    },
+    async leaderSelectLevel(levelInfo, markers) {
+      // 唯一权限时,直接操作
+      if (levelInfo.markLeaderOnlyRight && !levelInfo.leaderConfirm) {
+        const datas = {
+          action: levelInfo.markLeaderOnlyRight.action,
+          level: levelInfo.selectedLevel,
+          originLevel: levelInfo.curLevel,
+          paperIds: levelInfo.paperIds,
+          stage: this.curSubject.stage,
+          leaderConfirm: levelInfo.leaderConfirm,
+        };
+        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) {
+      this.getStepLevels();
+
+      if (this.carouselType) {
+        this.$refs.CarouselPapersPreview.cancel();
+        this.$refs.MarkerHistory.updatePapers();
+        return;
+      }
+
+      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();
+      }
+    },
+    leaderChangeLevel(levelInfo) {
+      const content = `确定申请由${levelNameTransform(
+        levelInfo.curLevel
+      )}档改为${levelNameTransform(
+        levelInfo.selectedLevel
+      )}档,并打回给所有老师吗?`;
+      this.$Modal.confirm({
+        content,
+        width: 450,
+        onOk: async () => {
+          await markStepChangeLevel({
+            subjectId: this.subjectId,
+            paperId: levelInfo.paperId,
+            level: levelInfo.selectedLevel,
+            userId: this.$ls.get("user", { id: "" }).id,
+          });
+          this.$Message.success("申请改档成功!");
+          this.getStepLevels();
+          if (this.carouselType) {
+            this.$refs.CarouselPapersPreview.cancel();
+            this.$refs.MarkerHistory.updatePapers();
+          } else {
+            // this.toActionNextPaper();
+            // 调档之后,试卷还在当前类别中,应该调用下一张
+            this.toNextPaper();
+          }
+        },
+      });
+    },
+    imagePreviewClose() {
+      this.isFullscreenMarking = false;
+      this.setShortcut(["page", "action"]);
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers, type) {
+      this.carouselType = type;
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+        this.setShortcut(["action"]);
+      });
+    },
+    selectCarouselPaper(index) {
+      this.paperKey = this.$randomCode();
+      this.curCarouselPaperIndex = index;
+      this.curPaper = { ...this.carouselPapers[index] };
+    },
+    toCarousePaper(type) {
+      if (type === "prev" && this.curCarouselPaperIndex > 0) {
+        this.curCarouselPaperIndex--;
+      } else if (
+        type === "next" &&
+        this.curCarouselPaperIndex < this.carouselPapers.length - 1
+      ) {
+        this.curCarouselPaperIndex++;
+      } else {
+        return;
+      }
+      this.selectCarouselPaper(this.curCarouselPaperIndex);
+    },
+    carouseImagePreviewClose() {
+      this.setShortcut([]);
+      this.isFullscreenMarking = false;
+      this.carouselType = "";
+    },
+    // header
+    toHistory() {
+      this.setShortcut([]);
+      this.$refs.MarkerHistory.open();
+    },
+    historyClose() {
+      this.selectPaper(this.curPaperIndex);
+      this.setShortcut(["page", "action"]);
+    },
+    historyMarkChange() {
+      this.getStepLevels();
+      this.getList();
+      this.$refs.MarkerHistory.updatePapers();
+    },
+    toStandard() {
+      this.setShortcut([]);
+      this.$refs.MarkerStandard.open();
+    },
+    async standardClose() {
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+      this.getStepLevels();
+      this.setShortcut(["page", "action"]);
+    },
+    toProgress() {
+      this.setShortcut([]);
+      this.$refs.LeaderProgress.open();
+    },
+    progressClose() {
+      this.setShortcut(["page", "action"]);
+    },
+    toSelectAll(allSelected) {
+      this.$refs.MarkerImageView.forEach((item) => {
+        item.changeSelect(allSelected);
+      });
+    },
+    toStatistics() {
+      this.setShortcut([]);
+      this.$refs.LeaderStatistics.open();
+    },
+    statisticsClose() {
+      this.setShortcut(["page", "action"]);
+    },
+  },
+  beforeDestroy() {
+    this.clearState();
+  },
+};
+</script>

+ 216 - 218
src/modules/grading/leader/LeaderProgress.vue

@@ -1,218 +1,216 @@
-<template>
-  <Modal
-    v-model="modalIsShow"
-    class="leader-progress marker-modal"
-    :title="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"
-            ></progress-line>
-          </td>
-          <td class="td-nopad">{{ item.progress }}%</td>
-        </tr>
-      </table>
-    </div>
-
-    <div v-if="kzzInfo.length && IS_LEVEL" class="leader-progress-part">
-      <table class="table table-dark">
-        <tr v-for="(user, uindex) in kzzInfo" :key="uindex">
-          <td>科组长</td>
-          <td>{{ user.loginName }}</td>
-          <td>仲裁</td>
-          <td>{{ user.arbitrated }}</td>
-        </tr>
-      </table>
-    </div>
-
-    <div
-      v-for="(group, index) in groupMarkers"
-      :key="index"
-      class="leader-progress-part"
-    >
-      <div v-if="IS_LEVEL">
-        <div v-for="(kzz, kindex) in group.kzzProgress" :key="kindex">
-          科组长:{{ kzz.loginName }},仲裁:{{ kzz.arbitrated }}
-        </div>
-        <table class="table table-dark">
-          <tr>
-            <th>评卷员</th>
-            <th>进度</th>
-            <th></th>
-            <th>打回</th>
-            <td v-if="IS_ROUGH_THIN_LEVEL">改大档</td>
-            <td v-if="IS_ROUGH_THIN_LEVEL">
-              改大档打小档
-            </td>
-          </tr>
-          <tr v-for="(item, aindex) in group.markerProgress" :key="aindex">
-            <td>{{ item.loginName }}</td>
-            <td>
-              <progress-line
-                :sum="item.totalCount"
-                :current="item.successCount"
-              ></progress-line>
-            </td>
-            <td class="td-nopad">{{ item.progress }}%</td>
-            <td>{{ item.rejectedCount }}</td>
-            <td v-if="IS_ROUGH_THIN_LEVEL">{{ item.shiftCount }}</td>
-            <td v-if="IS_ROUGH_THIN_LEVEL">
-              {{ item.shiftScoreCount }}
-            </td>
-          </tr>
-        </table>
-      </div>
-
-      <div v-if="IS_SCORE">
-        <div v-for="(kzz, kindex) in group.kzzProgress" :key="kindex">
-          科组长:{{ kzz.loginName }}
-        </div>
-        <table class="table table-dark">
-          <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 group.markerProgress" :key="aindex">
-            <td>{{ item.loginName }}</td>
-            <td>
-              <progress-line
-                :sum="item.totalCount"
-                :current="item.successCount"
-              ></progress-line>
-            </td>
-            <td class="td-nopad">{{ item.progress }}%</td>
-            <td>{{ item.shiftCount }}</td>
-            <td>{{ item.shiftScoreCount }}</td>
-          </tr>
-        </table>
-      </div>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { mapState } from "vuex";
-import { markLeaderGradingProgressDetail } from "@/api";
-import ProgressLine from "../components/ProgressLine";
-
-export default {
-  name: "leader-progress",
-  components: { ProgressLine },
-  data() {
-    return {
-      modalIsShow: false,
-      kzzInfo: [],
-      totalProgress: {},
-      areaProgress: [],
-      groupMarkers: []
-    };
-  },
-  computed: {
-    ...mapState("marker", ["paramsSet", "curSubject"]),
-    IS_LEVEL() {
-      return (
-        this.curSubject.stage === "LEVEL" ||
-        this.curSubject.stage === "ROUGH_LEVEL"
-      );
-    },
-    IS_SCORE() {
-      return this.curSubject.stage === "SCORE";
-    },
-    IS_ROUGH_THIN_LEVEL() {
-      return (
-        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
-      );
-    },
-    title() {
-      const infos = {
-        ROUGH_LEVEL: "粗分档",
-        LEVEL: "分档",
-        SCORE: "打分"
-      };
-      const { roughLevelEnable, stage } = this.curSubject;
-      let stageName = infos[stage];
-      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档";
-      return stageName + "进度";
-    }
-  },
-  methods: {
-    visibleChange(visible) {
-      if (visible) {
-        this.initData();
-      } else {
-        this.$emit("on-close");
-      }
-    },
-    async initData() {
-      const subjectId = this.$route.params.subjectId.split("-");
-      const data = await markLeaderGradingProgressDetail({
-        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.groupMarkers = [];
-      } else {
-        this.areaProgress = [totalInfo, ...this.addProgress(data.areaProgress)];
-        this.groupMarkers = data.groupMarkers.map(group => {
-          group.markerProgress = this.addProgress(group.markerProgress);
-          return group;
-        });
-      }
-    },
-    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>
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="leader-progress marker-modal"
+    :title="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"
+            ></progress-line>
+          </td>
+          <td class="td-nopad">{{ item.progress }}%</td>
+        </tr>
+      </table>
+    </div>
+
+    <div v-if="kzzInfo.length && IS_LEVEL" class="leader-progress-part">
+      <table class="table table-dark">
+        <tr v-for="(user, uindex) in kzzInfo" :key="uindex">
+          <td>科组长</td>
+          <td>{{ user.loginName }}</td>
+          <td>仲裁</td>
+          <td>{{ user.arbitrated }}</td>
+        </tr>
+      </table>
+    </div>
+
+    <div
+      v-for="(group, index) in groupMarkers"
+      :key="index"
+      class="leader-progress-part"
+    >
+      <div v-if="IS_LEVEL">
+        <div v-for="(kzz, kindex) in group.kzzProgress" :key="kindex">
+          科组长:{{ kzz.loginName }},仲裁:{{ kzz.arbitrated }}
+        </div>
+        <table class="table table-dark">
+          <tr>
+            <th>评卷员</th>
+            <th>进度</th>
+            <th></th>
+            <th>打回</th>
+            <td v-if="IS_ROUGH_THIN_LEVEL">改大档</td>
+            <td v-if="IS_ROUGH_THIN_LEVEL">改大档打小档</td>
+          </tr>
+          <tr v-for="(item, aindex) in group.markerProgress" :key="aindex">
+            <td>{{ item.loginName }}</td>
+            <td>
+              <progress-line
+                :sum="item.totalCount"
+                :current="item.successCount"
+              ></progress-line>
+            </td>
+            <td class="td-nopad">{{ item.progress }}%</td>
+            <td>{{ item.rejectedCount }}</td>
+            <td v-if="IS_ROUGH_THIN_LEVEL">{{ item.shiftCount }}</td>
+            <td v-if="IS_ROUGH_THIN_LEVEL">
+              {{ item.shiftScoreCount }}
+            </td>
+          </tr>
+        </table>
+      </div>
+
+      <div v-if="IS_SCORE">
+        <div v-for="(kzz, kindex) in group.kzzProgress" :key="kindex">
+          科组长:{{ kzz.loginName }}
+        </div>
+        <table class="table table-dark">
+          <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 group.markerProgress" :key="aindex">
+            <td>{{ item.loginName }}</td>
+            <td>
+              <progress-line
+                :sum="item.totalCount"
+                :current="item.successCount"
+              ></progress-line>
+            </td>
+            <td class="td-nopad">{{ item.progress }}%</td>
+            <td>{{ item.shiftCount }}</td>
+            <td>{{ item.shiftScoreCount }}</td>
+          </tr>
+        </table>
+      </div>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { markLeaderGradingProgressDetail } from "@/api";
+import ProgressLine from "../components/ProgressLine";
+
+export default {
+  name: "leader-progress",
+  components: { ProgressLine },
+  data() {
+    return {
+      modalIsShow: false,
+      kzzInfo: [],
+      totalProgress: {},
+      areaProgress: [],
+      groupMarkers: [],
+    };
+  },
+  computed: {
+    ...mapState("marker", ["paramsSet", "curSubject"]),
+    IS_LEVEL() {
+      return (
+        this.curSubject.stage === "LEVEL" ||
+        this.curSubject.stage === "ROUGH_LEVEL"
+      );
+    },
+    IS_SCORE() {
+      return this.curSubject.stage === "SCORE";
+    },
+    IS_ROUGH_THIN_LEVEL() {
+      return (
+        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
+      );
+    },
+    title() {
+      const infos = {
+        ROUGH_LEVEL: "粗分档",
+        LEVEL: "分档",
+        SCORE: "打分",
+      };
+      const { roughLevelEnable, stage } = this.curSubject;
+      let stageName = infos[stage];
+      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档";
+      return stageName + "进度";
+    },
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.initData();
+      } else {
+        this.$emit("on-close");
+      }
+    },
+    async initData() {
+      const subjectId = this.$route.params.subjectId.split("-");
+      const data = await markLeaderGradingProgressDetail({
+        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.groupMarkers = [];
+      } else {
+        this.areaProgress = [totalInfo, ...this.addProgress(data.areaProgress)];
+        this.groupMarkers = data.groupMarkers.map((group) => {
+          group.markerProgress = this.addProgress(group.markerProgress);
+          return group;
+        });
+      }
+    },
+    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>

+ 175 - 175
src/modules/grading/leader/LeaderStatistics.vue

@@ -1,175 +1,175 @@
-<template>
-  <Modal
-    v-model="modalIsShow"
-    class="leader-statistics marker-modal"
-    title="统计分析"
-    footer-hide
-    fullscreen
-    @on-visible-change="visibleChange"
-  >
-    <div class="box-justify mb-2">
-      <div>
-        <p>{{ curArea.areaName }}:{{ curSubject.name }}</p>
-      </div>
-      <div>
-        <Button
-          class="marker-btn-primary"
-          size="small"
-          type="primary"
-          @click="toExport"
-          :loading="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 class="td-bl">全部试卷数量</th>
-          <th>全部试卷占比</th>
-          <th>占比阈值</th>
-        </tr>
-        <tr v-for="(level, sindex) in levelData" :key="sindex">
-          <td>{{ level.code | levelNameFilter }}</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>
-          <td class="td-bl">{{ level.gcount }}</td>
-          <td>{{ level.gpercent }}%</td>
-          <td>{{ level.pt }}%</td>
-        </tr>
-      </table>
-    </div>
-    <div class="marker-statistics-chart">
-      <h3>考区试卷数量分布图</h3>
-      <echart-render
-        :chart-data="lineChartData"
-        chart-type="darkLines"
-        v-if="lineChartData"
-      ></echart-render>
-    </div>
-
-    <!-- LeaderAnalysisExport -->
-    <leader-analysis-export
-      ref="LeaderAnalysisExport"
-      :chart-data="renderChartData"
-      :page-info="renderPageInfo"
-      @on-exported="exportOver"
-      v-if="renderExportPage"
-    ></leader-analysis-export>
-  </Modal>
-</template>
-
-<script>
-import { mapState } from "vuex";
-import { gradingStatData } from "@/api";
-import EchartRender from "@/components/EchartRender";
-import LeaderAnalysisExport from "./LeaderAnalysisExport";
-import { levelNameTransform } from "@/plugins/utils";
-
-export default {
-  name: "leader-statistics",
-  components: { EchartRender, LeaderAnalysisExport },
-  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", "areas"])
-  },
-  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]
-      });
-
-      const groups = [
-        {
-          key: "levelProp",
-          label: "考区"
-        },
-        {
-          key: "gpercent",
-          label: "全部"
-        }
-      ];
-      const groupList = this.areas.length === 1 ? groups.slice(0, 1) : groups;
-      this.lineChartData = groupList.map(group => {
-        const data = this.levelData.map(item => {
-          return {
-            name: levelNameTransform(item.code),
-            value: item[group.key]
-          };
-        });
-        return {
-          name: group.label,
-          data
-        };
-      });
-    },
-    // export
-    toExport() {
-      if (this.isDownload) return;
-      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>
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="leader-statistics marker-modal"
+    title="统计分析"
+    footer-hide
+    fullscreen
+    @on-visible-change="visibleChange"
+  >
+    <div class="box-justify mb-2">
+      <div>
+        <p>{{ curArea.areaName }}:{{ curSubject.name }}</p>
+      </div>
+      <div>
+        <Button
+          class="marker-btn-primary"
+          size="small"
+          type="primary"
+          @click="toExport"
+          :loading="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 class="td-bl">全部试卷数量</th>
+          <th>全部试卷占比</th>
+          <th>占比阈值</th>
+        </tr>
+        <tr v-for="(level, sindex) in levelData" :key="sindex">
+          <td>{{ level.code | levelNameFilter }}</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>
+          <td class="td-bl">{{ level.gcount }}</td>
+          <td>{{ level.gpercent }}%</td>
+          <td>{{ level.pt }}%</td>
+        </tr>
+      </table>
+    </div>
+    <div class="marker-statistics-chart">
+      <h3>考区试卷数量分布图</h3>
+      <echart-render
+        :chart-data="lineChartData"
+        chart-type="darkLines"
+        v-if="lineChartData"
+      ></echart-render>
+    </div>
+
+    <!-- LeaderAnalysisExport -->
+    <leader-analysis-export
+      ref="LeaderAnalysisExport"
+      :chart-data="renderChartData"
+      :page-info="renderPageInfo"
+      @on-exported="exportOver"
+      v-if="renderExportPage"
+    ></leader-analysis-export>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { gradingStatData } from "@/api";
+import EchartRender from "@/components/EchartRender";
+import LeaderAnalysisExport from "./LeaderAnalysisExport";
+import { levelNameTransform } from "@/plugins/utils";
+
+export default {
+  name: "leader-statistics",
+  components: { EchartRender, LeaderAnalysisExport },
+  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", "areas"]),
+  },
+  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],
+      });
+
+      const groups = [
+        {
+          key: "levelProp",
+          label: "考区",
+        },
+        {
+          key: "gpercent",
+          label: "全部",
+        },
+      ];
+      const groupList = this.areas.length === 1 ? groups.slice(0, 1) : groups;
+      this.lineChartData = groupList.map((group) => {
+        const data = this.levelData.map((item) => {
+          return {
+            name: levelNameTransform(item.code),
+            value: item[group.key],
+          };
+        });
+        return {
+          name: group.label,
+          data,
+        };
+      });
+    },
+    // export
+    toExport() {
+      if (this.isDownload) return;
+      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>

+ 826 - 824
src/modules/grading/marker/MarkerGrading.vue

@@ -1,824 +1,826 @@
-<template>
-  <div class="marker-grading">
-    <marker-header
-      ref="MarkerHeader"
-      v-if="dataReady"
-      @area-change="areaChange"
-      @step-change="stepChange"
-      @page-set-change="pageSetChange"
-      @to-history="toHistory"
-      @to-standard="toStandard"
-      @to-statistics="toStatistics"
-    ></marker-header>
-
-    <div
-      v-if="dataReady"
-      :class="[
-        'marker-action',
-        'dark-mark',
-        { 'marker-action-fullscreen': isFullscreenMarking }
-      ]"
-    >
-      <template v-if="curPaper && curPaper.id">
-        <grade-action-rough
-          v-if="IS_ROUGH_THIN_LEVEL"
-          ref="GradeAction"
-          :cur-paper-or-task="curPaper"
-          :levels="levels"
-          :params-set="paramsSet"
-          :key="paperKey"
-          :is-batch-action="!!multipleGradingList.length"
-          @on-leader-change-level="leaderGradeCurPaper"
-          @on-select-level="gradeCurPaper"
-          @on-pass="passCurPaper"
-          @on-batch-level="multipleSelectLevel"
-          @on-history-mark="historyMarkChange"
-        ></grade-action-rough>
-        <grade-action
-          v-else
-          ref="GradeAction"
-          :cur-paper-or-task="curPaper"
-          :levels="levels"
-          :params-set="paramsSet"
-          :key="paperKey"
-          :is-batch-action="!!multipleGradingList.length"
-          @on-select-level="gradeCurPaper"
-          @on-pass="passCurPaper"
-          @on-batch-level="multipleSelectLevel"
-          @on-history-mark="historyMarkChange"
-        ></grade-action>
-      </template>
-
-      <grade-ribbon ref="GradeRibbon"></grade-ribbon>
-    </div>
-
-    <div
-      :class="['marker-body', { 'marker-body-low': ribbonSet.fastLevelNav }]"
-    >
-      <div :class="markerImageListClasses" v-if="papers.length">
-        <div
-          v-for="(paper, index) in papers"
-          :key="paper.key"
-          :class="[
-            'marker-image-item',
-            {
-              'marker-image-item-act': curPaperIndex === index
-            }
-          ]"
-        >
-          <div class="marker-image-content">
-            <marker-image-view
-              :data="paper"
-              :stage="curSubject.stage"
-              :can-mark="canMark"
-              :can-select="canSelect"
-              :select-handle="selectHandle"
-              @to-review="toReview"
-              @to-select="selectMultiplePaper"
-              @on-mark="markChange"
-            ></marker-image-view>
-          </div>
-        </div>
-      </div>
-      <div v-else class="marker-image-none">暂无数据</div>
-    </div>
-
-    <!-- MarkerHistory -->
-    <marker-history
-      :question-id="filter.questionId"
-      :stage="curSubject.stage"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers, 'history');
-        }
-      "
-      @on-close="historyClose"
-      @on-mark="historyMarkChange"
-      ref="MarkerHistory"
-    ></marker-history>
-    <!-- MarkerStandard -->
-    <marker-standard
-      :question-id="filter.questionId"
-      :levels="levels"
-      :stage="curSubject.stage"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers, 'sample');
-        }
-      "
-      @on-close="standardClose"
-      ref="MarkerStandard"
-      v-if="levels.length && filter.questionId"
-    ></marker-standard>
-    <!-- MarkerStatistics -->
-    <marker-statistics
-      ref="MarkerStatistics"
-      @on-close="statisticsClose"
-    ></marker-statistics>
-    <!-- image-preview -->
-    <simple-image-preview
-      class="grading-operation-image-preview"
-      :cur-image="curPaper"
-      :can-close="!curPaper.selfCheck"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      @on-close="imagePreviewClose"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-
-    <!-- carousel paper review -->
-    <simple-image-preview
-      class="grading-operation-image-preview"
-      :cur-image="curPaper"
-      @on-prev="toCarousePaper('prev')"
-      @on-next="toCarousePaper('next')"
-      @on-close="carouseImagePreviewClose"
-      ref="CarouselPapersPreview"
-    ></simple-image-preview>
-    <!-- level-change-modal-info -->
-    <Modal
-      v-model="levelChangeModalIsShow"
-      width="400"
-      footer-hide
-      :z-index="2001"
-      :closable="false"
-      :mask-closable="false"
-    >
-      <div class="ivu-modal-confirm">
-        <div class="ivu-modal-confirm-body">
-          <div>{{ levelChangeTips }}</div>
-        </div>
-        <div class="ivu-modal-confirm-footer">
-          <Button type="primary" @click="levelChangeModalIsShow = false"
-            >确定</Button
-          >
-        </div>
-      </div>
-    </Modal>
-  </div>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-import MarkerHeader from "./MarkerHeader";
-import MarkerImageView from "./MarkerImageView";
-import MarkerHistory from "./MarkerHistory";
-import MarkerStandard from "./MarkerStandard";
-import MarkerStatistics from "./MarkerStatistics";
-import GradeAction from "../components/GradeAction";
-import GradeActionRough from "../components/GradeActionRough";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import GradeRibbon from "../components/GradeRibbon";
-import { levelNameTransform } from "@/plugins/utils";
-
-import {
-  markerTaskList,
-  markerMarkPaperList,
-  markerChangeLevelPaperList,
-  markerSelfCheckTask,
-  markerSelfCheckLevel,
-  markerLevelTotalStatData,
-  workLevelList,
-  paperSelectLevelOrScore,
-  paperSelectLevelBatch,
-  paperTaskPass,
-  getParamsSet,
-  subjectDetail
-} from "@/api";
-
-export default {
-  name: "marker-grading",
-  components: {
-    MarkerHeader,
-    MarkerImageView,
-    MarkerHistory,
-    MarkerStandard,
-    MarkerStatistics,
-    GradeAction,
-    GradeActionRough,
-    GradeRibbon,
-    SimpleImagePreview
-  },
-  data() {
-    return {
-      filter: {
-        markerId: this.$ls.get("user").id,
-        questionId: "",
-        sort: "randomSeq,asc",
-        stage: "LEVEL"
-      },
-      typeFilter: {
-        done: {
-          level: ""
-        },
-        undo: {},
-        reject: {
-          reject: true
-        },
-        shift: {
-          isShift: true,
-          isShiftScore: false
-        },
-        shiftScore: {
-          isShift: false,
-          isShiftScore: true
-        },
-        markPaper: {}
-      },
-      dataReady: false,
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      workSubject: {},
-      curStandardGradeId: "",
-      levels: [],
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      paperKey: "",
-      // multiple grading
-      multiplebtnClicked: false,
-      multipleGradingList: [],
-      // carousel paper review,
-      carouselType: "",
-      carouselPapers: [],
-      curCarouselPaperIndex: 0,
-      isFullscreenMarking: false,
-      // tips-modal
-      levelChangeTips: "",
-      levelChangeModalIsShow: false
-    };
-  },
-  computed: {
-    ...mapState("marker", [
-      "paramsSet",
-      "page",
-      "steps",
-      "curStep",
-      "curArea",
-      "curSubject",
-      "ribbonSet"
-    ]),
-    markerImageListClasses() {
-      return ["marker-image-list", `marker-image-list-${this.page.size}`];
-    },
-    IS_ROUGH_THIN_LEVEL() {
-      return (
-        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
-      );
-    },
-    IS_UNDO_STEP() {
-      return this.curStep.type === "undo";
-    },
-    canMark() {
-      return !this.curStep.type.includes("shift");
-    },
-    canSelect() {
-      return !this.curStep.type.includes("shift");
-    }
-  },
-  created() {
-    this.subject = this.subjectId.split("-")[1];
-    this.workSubject = {
-      workId: this.workId,
-      subject: this.subject
-    };
-    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.setCurUserRoleType(curUserRoleType);
-    this.initData();
-  },
-  methods: {
-    ...mapMutations("marker", [
-      "setParamSet",
-      "setCurSubject",
-      "setPage",
-      "setSteps",
-      "setCurArea",
-      "setCurStep",
-      "setCurUserRoleType",
-      "setShortcut",
-      "clearState"
-    ]),
-    async initData() {
-      this.dataReady = false;
-      await this.getSubjectDetail();
-      await this.getParamsSetInfo();
-      // 必须在获取subject之后再获取levels
-      await this.getWorkLevels();
-      this.dataReady = true;
-    },
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.setParamSet(data || {});
-    },
-    async getSubjectDetail() {
-      const curSubject = await subjectDetail(this.subjectId);
-      this.setCurSubject(curSubject || {});
-      this.filter.stage = this.curSubject.stage;
-    },
-    async getList() {
-      this.clearMultiplePaper();
-      const datas = {
-        ...this.filter,
-        ...this.typeFilter[this.curStep.type],
-        ...this.workSubject,
-        page: this.page.current - 1,
-        size: this.page.size
-      };
-      if (this.curStep.type === "done") {
-        datas.level = this.curStep.name;
-        datas.sort = "updatedOn,desc";
-      }
-
-      let requestAction = null;
-      if (this.curStep.type.includes("shift")) {
-        //  细分档的改大裆
-        requestAction = markerChangeLevelPaperList;
-      } else if (this.curStep.type === "markPaper") {
-        requestAction = markerMarkPaperList;
-      } else {
-        requestAction = markerTaskList;
-      }
-
-      const data = await requestAction(datas);
-      this.papers = data.data.map(paper => {
-        paper.key = this.$randomCode();
-        paper.title = `NO.${paper.sn}`;
-        paper.selected = false;
-        return paper;
-      });
-      this.setPage({
-        total: data.totalCount,
-        totalPage: data.pageCount
-      });
-    },
-    async toPage(page) {
-      this.setPage({
-        current: page
-      });
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async gotoSelfCheckTask() {
-      const task = await markerSelfCheckTask({
-        stage: this.curSubject.stage,
-        markerId: this.filter.markerId,
-        workId: this.workId,
-        subject: this.subject
-      });
-      if (!task) return;
-
-      this.paperKey = this.$randomCode();
-      this.curPaper = task;
-      if (this.isFullscreenMarking) return;
-
-      this.setShortcut(["action"]);
-      this.isFullscreenMarking = true;
-      this.$refs.SimpleImagePreview.open();
-    },
-    async getStepLevels() {
-      const data = await markerLevelTotalStatData(
-        this.filter.markerId,
-        this.filter.questionId,
-        this.curSubject.stage
-      );
-      const undoIndex = data.findIndex(item => item.id === null);
-      let otherStep = [];
-      let undo = {
-        count: 0,
-        rejected: 0
-      };
-      if (undoIndex !== -1) {
-        undo = { ...data[undoIndex] };
-        data.splice(undoIndex, 1);
-      }
-
-      otherStep.push({
-        name: "待评",
-        count: undo.count,
-        type: "undo"
-      });
-      otherStep.push({
-        name: "打回",
-        count: undo.rejected,
-        type: "reject"
-      });
-
-      if (this.IS_ROUGH_THIN_LEVEL) {
-        otherStep.push({
-          name: "改大档",
-          count: undo.shift || 0,
-          type: "shift"
-        });
-        otherStep.push({
-          name: "改大档打小档",
-          count: undo.shiftScore || 0,
-          type: "shiftScore"
-        });
-      }
-
-      const mpInfo = data.find(item => item.id === "markPaper");
-      if (mpInfo) {
-        otherStep.push({
-          count: mpInfo.count,
-          name: "标记",
-          type: "markPaper"
-        });
-      }
-
-      let levelStep = data
-        .filter(item => item.id !== "markPaper")
-        .map(item => {
-          // 评卷员不展示kdpt
-          item.kdpt = null;
-          return {
-            ...item,
-            name: item.id,
-            type: "done"
-          };
-        });
-
-      this.setSteps({ levelStep, otherStep });
-
-      if (!this.curStep.name) {
-        let curStep = {};
-        if (undoIndex === -1) {
-          curStep = levelStep[0];
-        } else {
-          const firstStep = otherStep.find(item => item.count);
-          curStep = firstStep || levelStep[0];
-        }
-        this.setCurStep(curStep);
-      } else {
-        const curStep = [...levelStep, ...otherStep].find(
-          item => item.name === this.curStep.name
-        );
-        this.setCurStep(curStep);
-      }
-    },
-    updateStepLevel(curStep, curLevel, count) {
-      if (curStep.type === "markPaper" || this.curStep.type === "reject") {
-        this.getStepLevels();
-        return;
-      }
-      if (curStep.type === "done") {
-        const lpos = this.steps.levelStep.findIndex(
-          item => item.name === curStep.name
-        );
-        this.steps.levelStep[lpos].count -= count;
-      } else {
-        if (curStep.type !== "markPaper") {
-          const opos = this.steps.otherStep.findIndex(
-            item => item.type === curStep.type
-          );
-          this.steps.otherStep[opos].count -= count;
-        }
-      }
-
-      if (curStep.type !== "shift") {
-        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.curSubject.stage);
-      this.levels = data || [];
-      // console.log(this.levels);
-    },
-    async pageSetChange() {
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async stepChange(step) {
-      this.setCurStep(step);
-      this.setPage({ current: 1 });
-      this.isFullscreenMarking = false;
-      await this.getList();
-      await this.getStepLevels();
-      if (this.papers.length) {
-        this.selectPaper(0);
-      } else {
-        this.curPaper = {};
-      }
-      if (this.IS_UNDO_STEP) {
-        await this.gotoSelfCheckTask();
-      }
-    },
-    async areaChange(curArea) {
-      this.setCurArea(curArea);
-      this.filter.questionId = curArea.id;
-      await this.getStepLevels();
-      await this.toPage(1);
-      // 刷新页面时只触发areaChange
-      if (this.IS_UNDO_STEP) {
-        await this.gotoSelfCheckTask();
-      }
-    },
-    // selectMultiplePaper
-    selectHandle(curPaper) {
-      if (this.IS_ROUGH_THIN_LEVEL && this.multipleGradingList.length) {
-        if (curPaper.roughLevel !== this.multipleGradingList[0].roughLevel) {
-          this.$Message.error("不得跨档批量操作");
-          return;
-        }
-      }
-
-      return true;
-    },
-    selectMultiplePaper(paper) {
-      if (paper.sample) return;
-      const curPaper = this.papers.find(p => p.id === paper.id);
-      curPaper.selected = paper.selected;
-      this.multipleGradingList = this.papers.filter(paper => paper.selected);
-    },
-    clearMultiplePaper() {
-      this.multipleGradingList = [];
-      this.papers.forEach(paper => {
-        paper.selected = false;
-      });
-      this.$refs.MarkerHeader.changeAllSelect(false);
-    },
-    checkPapersIsSelectLevel(levelName, papers) {
-      const firstLevel = papers[0].level;
-      const hasOtherLevel = this.papers.some(item => item.level !== firstLevel);
-      return hasOtherLevel ? false : firstLevel === levelName;
-    },
-    async multipleSelectLevel(level) {
-      if (!this.multipleGradingList.length) return;
-
-      if (this.checkPapersIsSelectLevel(level.name, this.multipleGradingList)) {
-        this.$Message.error("已选试卷档位和设置档位一样!");
-        return;
-      }
-
-      if (this.multiplebtnClicked) return;
-      this.multiplebtnClicked = true;
-      const multipleGradingListCount = this.multipleGradingList.length;
-
-      const gradeRes = await paperSelectLevelBatch(
-        this.multipleGradingList.map(item => item.id).join(), // is taskId
-        level.name,
-        this.curSubject.stage
-      ).catch(() => {});
-
-      this.multiplebtnClicked = false;
-      if (!gradeRes) return;
-
-      this.multipleGradingList = [];
-      // this.getStepLevels();
-      this.updateStepLevel(this.curStep, level.name, multipleGradingListCount);
-
-      // 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 });
-      }
-
-      // 待评阶段:自查卷获取逻辑
-      if (this.IS_UNDO_STEP && gradeRes.hasSelfTask) {
-        await this.gotoSelfCheckTask();
-        return;
-      }
-
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    // paper view action
-    markChange(mark) {
-      const spos = this.steps.otherStep.findIndex(
-        item => item.type === "markPaper"
-      );
-      if (spos === -1) return;
-      if (mark) {
-        this.steps.otherStep[spos].count++;
-      } else {
-        this.steps.otherStep[spos].count--;
-        if (this.curStep.type === "markPaper") this.getList();
-      }
-    },
-    async historyMarkChange(mark) {
-      this.markChange(mark);
-      const data = await this.$refs.MarkerHistory.updatePapers();
-      this.carouselPapers = data || [];
-    },
-    toReview(data) {
-      this.setShortcut(["action"]);
-      this.isFullscreenMarking = true;
-      this.clearMultiplePaper();
-      this.curPaperIndex = this.papers.findIndex(item => item.id === data.id);
-      this.curPaper = Object.assign({}, this.papers[this.curPaperIndex], data);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      this.paperKey = this.$randomCode();
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      const lastPaper = { ...this.curPaper };
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-
-      // 待评时,检查当前试卷是否已经切换粗档位
-      if (
-        this.IS_ROUGH_THIN_LEVEL &&
-        this.curStep.type === "undo" &&
-        this.curPaper["roughLevel"] &&
-        this.curPaper["roughLevel"] !== lastPaper["roughLevel"]
-      ) {
-        this.levelChangeTips = `即将分档粗档位:${levelNameTransform(
-          this.curPaper.roughLevel
-        )}`;
-        this.levelChangeModalIsShow = true;
-      }
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        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("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.page.current === this.page.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.setPage({ current: this.page.current + 1 });
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toActionNextPaper() {
-      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 leaderGradeCurPaper({ selectedLevel }) {
-      await paperSelectLevelOrScore(
-        this.curPaper.id, // is taskId
-        selectedLevel,
-        "ROUGH_LEVEL"
-      );
-      this.updateStepLevel(this.curStep, "shiftScore", 1);
-      this.toActionNextPaper();
-    },
-    async gradeCurPaper(level) {
-      let gradeRes = null;
-      if (this.curPaper.selfCheck) {
-        gradeRes = await markerSelfCheckLevel(
-          this.curPaper.id, // is taskId
-          level.name
-        );
-      } else {
-        gradeRes = await paperSelectLevelOrScore(
-          this.curPaper.id, // is taskId
-          level.name,
-          this.curSubject.stage
-        );
-      }
-      if (!gradeRes) return;
-
-      if (this.carouselType) {
-        this.updateStepLevel(
-          { type: "done", name: this.curPaper.level },
-          level.name,
-          1
-        );
-
-        this.$refs.CarouselPapersPreview.cancel();
-        this.$refs.MarkerHistory.updatePapers();
-      } else {
-        if (!this.curPaper.selfCheck)
-          this.updateStepLevel(this.curStep, level.name, 1);
-
-        // 待评阶段:自查卷获取逻辑
-        if (this.IS_UNDO_STEP && gradeRes.hasSelfTask) {
-          await this.gotoSelfCheckTask();
-          return;
-        }
-        this.toActionNextPaper();
-      }
-    },
-    async passCurPaper() {
-      await paperTaskPass(this.filter.stage, this.curPaper.id);
-      this.toActionNextPaper();
-    },
-    imagePreviewClose() {
-      this.isFullscreenMarking = false;
-      this.setShortcut(["page", "action"]);
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers, type) {
-      this.carouselType = type;
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-        this.setShortcut(["action"]);
-      });
-    },
-    selectCarouselPaper(index) {
-      this.paperKey = this.$randomCode();
-      this.curCarouselPaperIndex = index;
-      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 (
-        type === "next" &&
-        this.curCarouselPaperIndex < this.carouselPapers.length - 1
-      ) {
-        this.curCarouselPaperIndex++;
-      } else {
-        return;
-      }
-      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.setShortcut([]);
-      this.isFullscreenMarking = false;
-      this.carouselType = "";
-    },
-    // header
-    toHistory() {
-      this.setShortcut([]);
-      this.$refs.MarkerHistory.open();
-    },
-    async historyClose() {
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-      this.setShortcut(["page", "action"]);
-    },
-    toStandard() {
-      this.setShortcut([]);
-      this.$refs.MarkerStandard.open();
-    },
-    standardClose() {
-      this.selectPaper(this.curPaperIndex);
-      this.setShortcut(["page", "action"]);
-    },
-    async toStatistics() {
-      this.setShortcut([]);
-      await this.getStepLevels();
-      this.$refs.MarkerStatistics.open();
-    },
-    statisticsClose() {
-      this.setShortcut(["page", "action"]);
-    }
-  },
-  beforeDestroy() {
-    this.clearState();
-  }
-};
-</script>
+<template>
+  <div class="marker-grading">
+    <marker-header
+      ref="MarkerHeader"
+      v-if="dataReady"
+      @area-change="areaChange"
+      @step-change="stepChange"
+      @page-set-change="pageSetChange"
+      @to-history="toHistory"
+      @to-standard="toStandard"
+      @to-statistics="toStatistics"
+    ></marker-header>
+
+    <div
+      v-if="dataReady"
+      :class="[
+        'marker-action',
+        'dark-mark',
+        { 'marker-action-fullscreen': isFullscreenMarking },
+      ]"
+    >
+      <template v-if="curPaper && curPaper.id">
+        <grade-action-rough
+          v-if="IS_ROUGH_THIN_LEVEL"
+          ref="GradeAction"
+          :cur-paper-or-task="curPaper"
+          :levels="levels"
+          :params-set="paramsSet"
+          :key="paperKey"
+          :is-batch-action="!!multipleGradingList.length"
+          @on-leader-change-level="leaderGradeCurPaper"
+          @on-select-level="gradeCurPaper"
+          @on-pass="passCurPaper"
+          @on-batch-level="multipleSelectLevel"
+          @on-history-mark="historyMarkChange"
+        ></grade-action-rough>
+        <grade-action
+          v-else
+          ref="GradeAction"
+          :cur-paper-or-task="curPaper"
+          :levels="levels"
+          :params-set="paramsSet"
+          :key="paperKey"
+          :is-batch-action="!!multipleGradingList.length"
+          @on-select-level="gradeCurPaper"
+          @on-pass="passCurPaper"
+          @on-batch-level="multipleSelectLevel"
+          @on-history-mark="historyMarkChange"
+        ></grade-action>
+      </template>
+
+      <grade-ribbon ref="GradeRibbon"></grade-ribbon>
+    </div>
+
+    <div
+      :class="['marker-body', { 'marker-body-low': ribbonSet.fastLevelNav }]"
+    >
+      <div :class="markerImageListClasses" v-if="papers.length">
+        <div
+          v-for="(paper, index) in papers"
+          :key="paper.key"
+          :class="[
+            'marker-image-item',
+            {
+              'marker-image-item-act': curPaperIndex === index,
+            },
+          ]"
+        >
+          <div class="marker-image-content">
+            <marker-image-view
+              :data="paper"
+              :stage="curSubject.stage"
+              :can-mark="canMark"
+              :can-select="canSelect"
+              :select-handle="selectHandle"
+              @to-review="toReview"
+              @to-select="selectMultiplePaper"
+              @on-mark="markChange"
+            ></marker-image-view>
+          </div>
+        </div>
+      </div>
+      <div v-else class="marker-image-none">暂无数据</div>
+    </div>
+
+    <!-- MarkerHistory -->
+    <marker-history
+      :question-id="filter.questionId"
+      :stage="curSubject.stage"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers, 'history');
+        }
+      "
+      @on-close="historyClose"
+      @on-mark="historyMarkChange"
+      ref="MarkerHistory"
+    ></marker-history>
+    <!-- MarkerStandard -->
+    <marker-standard
+      :question-id="filter.questionId"
+      :levels="levels"
+      :stage="curSubject.stage"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers, 'sample');
+        }
+      "
+      @on-close="standardClose"
+      ref="MarkerStandard"
+      v-if="levels.length && filter.questionId"
+    ></marker-standard>
+    <!-- MarkerStatistics -->
+    <marker-statistics
+      ref="MarkerStatistics"
+      @on-close="statisticsClose"
+    ></marker-statistics>
+    <!-- image-preview -->
+    <simple-image-preview
+      class="grading-operation-image-preview"
+      :cur-image="curPaper"
+      :can-close="!curPaper.selfCheck"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      @on-close="imagePreviewClose"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+
+    <!-- carousel paper review -->
+    <simple-image-preview
+      class="grading-operation-image-preview"
+      :cur-image="curPaper"
+      @on-prev="toCarousePaper('prev')"
+      @on-next="toCarousePaper('next')"
+      @on-close="carouseImagePreviewClose"
+      ref="CarouselPapersPreview"
+    ></simple-image-preview>
+    <!-- level-change-modal-info -->
+    <Modal
+      v-model="levelChangeModalIsShow"
+      width="400"
+      footer-hide
+      :z-index="2001"
+      :closable="false"
+      :mask-closable="false"
+    >
+      <div class="ivu-modal-confirm">
+        <div class="ivu-modal-confirm-body">
+          <div>{{ levelChangeTips }}</div>
+        </div>
+        <div class="ivu-modal-confirm-footer">
+          <Button type="primary" @click="levelChangeModalIsShow = false"
+            >确定</Button
+          >
+        </div>
+      </div>
+    </Modal>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import MarkerHeader from "./MarkerHeader";
+import MarkerImageView from "./MarkerImageView";
+import MarkerHistory from "./MarkerHistory";
+import MarkerStandard from "./MarkerStandard";
+import MarkerStatistics from "./MarkerStatistics";
+import GradeAction from "../components/GradeAction";
+import GradeActionRough from "../components/GradeActionRough";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import GradeRibbon from "../components/GradeRibbon";
+import { levelNameTransform } from "@/plugins/utils";
+
+import {
+  markerTaskList,
+  markerMarkPaperList,
+  markerChangeLevelPaperList,
+  markerSelfCheckTask,
+  markerSelfCheckLevel,
+  markerLevelTotalStatData,
+  workLevelList,
+  paperSelectLevelOrScore,
+  paperSelectLevelBatch,
+  paperTaskPass,
+  getParamsSet,
+  subjectDetail,
+} from "@/api";
+
+export default {
+  name: "marker-grading",
+  components: {
+    MarkerHeader,
+    MarkerImageView,
+    MarkerHistory,
+    MarkerStandard,
+    MarkerStatistics,
+    GradeAction,
+    GradeActionRough,
+    GradeRibbon,
+    SimpleImagePreview,
+  },
+  data() {
+    return {
+      filter: {
+        markerId: this.$ls.get("user").id,
+        questionId: "",
+        sort: "randomSeq,asc",
+        stage: "LEVEL",
+      },
+      typeFilter: {
+        done: {
+          level: "",
+        },
+        undo: {},
+        reject: {
+          reject: true,
+        },
+        shift: {
+          isShift: true,
+          isShiftScore: false,
+        },
+        shiftScore: {
+          isShift: false,
+          isShiftScore: true,
+        },
+        markPaper: {},
+      },
+      dataReady: false,
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      workSubject: {},
+      curStandardGradeId: "",
+      levels: [],
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      paperKey: "",
+      // multiple grading
+      multiplebtnClicked: false,
+      multipleGradingList: [],
+      // carousel paper review,
+      carouselType: "",
+      carouselPapers: [],
+      curCarouselPaperIndex: 0,
+      isFullscreenMarking: false,
+      // tips-modal
+      levelChangeTips: "",
+      levelChangeModalIsShow: false,
+    };
+  },
+  computed: {
+    ...mapState("marker", [
+      "paramsSet",
+      "page",
+      "steps",
+      "curStep",
+      "curArea",
+      "curSubject",
+      "ribbonSet",
+    ]),
+    markerImageListClasses() {
+      return ["marker-image-list", `marker-image-list-${this.page.size}`];
+    },
+    IS_ROUGH_THIN_LEVEL() {
+      return (
+        this.curSubject.roughLevelEnable && this.curSubject.stage === "LEVEL"
+      );
+    },
+    IS_UNDO_STEP() {
+      return this.curStep.type === "undo";
+    },
+    canMark() {
+      return !this.curStep.type.includes("shift");
+    },
+    canSelect() {
+      return !this.curStep.type.includes("shift");
+    },
+  },
+  created() {
+    this.subject = this.subjectId.split("-")[1];
+    this.workSubject = {
+      workId: this.workId,
+      subject: this.subject,
+    };
+    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    this.setCurUserRoleType(curUserRoleType);
+    this.initData();
+  },
+  methods: {
+    ...mapMutations("marker", [
+      "setParamSet",
+      "setCurSubject",
+      "setPage",
+      "setSteps",
+      "setCurArea",
+      "setCurStep",
+      "setCurUserRoleType",
+      "setShortcut",
+      "clearState",
+    ]),
+    async initData() {
+      this.dataReady = false;
+      await this.getSubjectDetail();
+      await this.getParamsSetInfo();
+      // 必须在获取subject之后再获取levels
+      await this.getWorkLevels();
+      this.dataReady = true;
+    },
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.setParamSet(data || {});
+    },
+    async getSubjectDetail() {
+      const curSubject = await subjectDetail(this.subjectId);
+      this.setCurSubject(curSubject || {});
+      this.filter.stage = this.curSubject.stage;
+    },
+    async getList() {
+      this.clearMultiplePaper();
+      const datas = {
+        ...this.filter,
+        ...this.typeFilter[this.curStep.type],
+        ...this.workSubject,
+        page: this.page.current - 1,
+        size: this.page.size,
+      };
+      if (this.curStep.type === "done") {
+        datas.level = this.curStep.name;
+        datas.sort = "updatedOn,desc";
+      }
+
+      let requestAction = null;
+      if (this.curStep.type.includes("shift")) {
+        //  细分档的改大裆
+        requestAction = markerChangeLevelPaperList;
+      } else if (this.curStep.type === "markPaper") {
+        requestAction = markerMarkPaperList;
+      } else {
+        requestAction = markerTaskList;
+      }
+
+      const data = await requestAction(datas);
+      this.papers = data.data.map((paper) => {
+        paper.key = this.$randomCode();
+        paper.title = `NO.${paper.sn}`;
+        paper.selected = false;
+        return paper;
+      });
+      this.setPage({
+        total: data.totalCount,
+        totalPage: data.pageCount,
+      });
+    },
+    async toPage(page) {
+      this.setPage({
+        current: page,
+      });
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async gotoSelfCheckTask() {
+      const task = await markerSelfCheckTask({
+        stage: this.curSubject.stage,
+        markerId: this.filter.markerId,
+        workId: this.workId,
+        subject: this.subject,
+      });
+      if (!task) return;
+
+      this.paperKey = this.$randomCode();
+      this.curPaper = task;
+      if (this.isFullscreenMarking) return;
+
+      this.setShortcut(["action"]);
+      this.isFullscreenMarking = true;
+      this.$refs.SimpleImagePreview.open();
+    },
+    async getStepLevels() {
+      const data = await markerLevelTotalStatData(
+        this.filter.markerId,
+        this.filter.questionId,
+        this.curSubject.stage
+      );
+      const undoIndex = data.findIndex((item) => item.id === null);
+      let otherStep = [];
+      let undo = {
+        count: 0,
+        rejected: 0,
+      };
+      if (undoIndex !== -1) {
+        undo = { ...data[undoIndex] };
+        data.splice(undoIndex, 1);
+      }
+
+      otherStep.push({
+        name: "待评",
+        count: undo.count,
+        type: "undo",
+      });
+      otherStep.push({
+        name: "打回",
+        count: undo.rejected,
+        type: "reject",
+      });
+
+      if (this.IS_ROUGH_THIN_LEVEL) {
+        otherStep.push({
+          name: "改大档",
+          count: undo.shift || 0,
+          type: "shift",
+        });
+        otherStep.push({
+          name: "改大档打小档",
+          count: undo.shiftScore || 0,
+          type: "shiftScore",
+        });
+      }
+
+      const mpInfo = data.find((item) => item.id === "markPaper");
+      if (mpInfo) {
+        otherStep.push({
+          count: mpInfo.count,
+          name: "标记",
+          type: "markPaper",
+        });
+      }
+
+      let levelStep = data
+        .filter((item) => item.id !== "markPaper")
+        .map((item) => {
+          // 评卷员不展示kdpt
+          item.kdpt = null;
+          return {
+            ...item,
+            name: item.id,
+            type: "done",
+          };
+        });
+
+      this.setSteps({ levelStep, otherStep });
+
+      if (!this.curStep.name) {
+        let curStep = {};
+        if (undoIndex === -1) {
+          curStep = levelStep[0];
+        } else {
+          const firstStep = otherStep.find((item) => item.count);
+          curStep = firstStep || levelStep[0];
+        }
+        this.setCurStep(curStep);
+      } else {
+        const curStep = [...levelStep, ...otherStep].find(
+          (item) => item.name === this.curStep.name
+        );
+        this.setCurStep(curStep);
+      }
+    },
+    updateStepLevel(curStep, curLevel, count) {
+      if (curStep.type === "markPaper" || this.curStep.type === "reject") {
+        this.getStepLevels();
+        return;
+      }
+      if (curStep.type === "done") {
+        const lpos = this.steps.levelStep.findIndex(
+          (item) => item.name === curStep.name
+        );
+        this.steps.levelStep[lpos].count -= count;
+      } else {
+        if (curStep.type !== "markPaper") {
+          const opos = this.steps.otherStep.findIndex(
+            (item) => item.type === curStep.type
+          );
+          this.steps.otherStep[opos].count -= count;
+        }
+      }
+
+      if (curStep.type !== "shift") {
+        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.curSubject.stage);
+      this.levels = data || [];
+      // console.log(this.levels);
+    },
+    async pageSetChange() {
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async stepChange(step) {
+      this.setCurStep(step);
+      this.setPage({ current: 1 });
+      this.isFullscreenMarking = false;
+      await this.getList();
+      await this.getStepLevels();
+      if (this.papers.length) {
+        this.selectPaper(0);
+      } else {
+        this.curPaper = {};
+      }
+      if (this.IS_UNDO_STEP) {
+        await this.gotoSelfCheckTask();
+      }
+    },
+    async areaChange(curArea) {
+      this.setCurArea(curArea);
+      this.filter.questionId = curArea.id;
+      await this.getStepLevels();
+      await this.toPage(1);
+      // 刷新页面时只触发areaChange
+      if (this.IS_UNDO_STEP) {
+        await this.gotoSelfCheckTask();
+      }
+    },
+    // selectMultiplePaper
+    selectHandle(curPaper) {
+      if (this.IS_ROUGH_THIN_LEVEL && this.multipleGradingList.length) {
+        if (curPaper.roughLevel !== this.multipleGradingList[0].roughLevel) {
+          this.$Message.error("不得跨档批量操作");
+          return;
+        }
+      }
+
+      return true;
+    },
+    selectMultiplePaper(paper) {
+      if (paper.sample) return;
+      const curPaper = this.papers.find((p) => p.id === paper.id);
+      curPaper.selected = paper.selected;
+      this.multipleGradingList = this.papers.filter((paper) => paper.selected);
+    },
+    clearMultiplePaper() {
+      this.multipleGradingList = [];
+      this.papers.forEach((paper) => {
+        paper.selected = false;
+      });
+      this.$refs.MarkerHeader.changeAllSelect(false);
+    },
+    checkPapersIsSelectLevel(levelName, papers) {
+      const firstLevel = papers[0].level;
+      const hasOtherLevel = this.papers.some(
+        (item) => item.level !== firstLevel
+      );
+      return hasOtherLevel ? false : firstLevel === levelName;
+    },
+    async multipleSelectLevel(level) {
+      if (!this.multipleGradingList.length) return;
+
+      if (this.checkPapersIsSelectLevel(level.name, this.multipleGradingList)) {
+        this.$Message.error("已选试卷档位和设置档位一样!");
+        return;
+      }
+
+      if (this.multiplebtnClicked) return;
+      this.multiplebtnClicked = true;
+      const multipleGradingListCount = this.multipleGradingList.length;
+
+      const gradeRes = await paperSelectLevelBatch(
+        this.multipleGradingList.map((item) => item.id).join(), // is taskId
+        level.name,
+        this.curSubject.stage
+      ).catch(() => {});
+
+      this.multiplebtnClicked = false;
+      if (!gradeRes) return;
+
+      this.multipleGradingList = [];
+      // this.getStepLevels();
+      this.updateStepLevel(this.curStep, level.name, multipleGradingListCount);
+
+      // 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 });
+      }
+
+      // 待评阶段:自查卷获取逻辑
+      if (this.IS_UNDO_STEP && gradeRes.hasSelfTask) {
+        await this.gotoSelfCheckTask();
+        return;
+      }
+
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    // paper view action
+    markChange(mark) {
+      const spos = this.steps.otherStep.findIndex(
+        (item) => item.type === "markPaper"
+      );
+      if (spos === -1) return;
+      if (mark) {
+        this.steps.otherStep[spos].count++;
+      } else {
+        this.steps.otherStep[spos].count--;
+        if (this.curStep.type === "markPaper") this.getList();
+      }
+    },
+    async historyMarkChange(mark) {
+      this.markChange(mark);
+      const data = await this.$refs.MarkerHistory.updatePapers();
+      this.carouselPapers = data || [];
+    },
+    toReview(data) {
+      this.setShortcut(["action"]);
+      this.isFullscreenMarking = true;
+      this.clearMultiplePaper();
+      this.curPaperIndex = this.papers.findIndex((item) => item.id === data.id);
+      this.curPaper = Object.assign({}, this.papers[this.curPaperIndex], data);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      this.paperKey = this.$randomCode();
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      const lastPaper = { ...this.curPaper };
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+
+      // 待评时,检查当前试卷是否已经切换粗档位
+      if (
+        this.IS_ROUGH_THIN_LEVEL &&
+        this.curStep.type === "undo" &&
+        this.curPaper["roughLevel"] &&
+        this.curPaper["roughLevel"] !== lastPaper["roughLevel"]
+      ) {
+        this.levelChangeTips = `即将分档粗档位:${levelNameTransform(
+          this.curPaper.roughLevel
+        )}`;
+        this.levelChangeModalIsShow = true;
+      }
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        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("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.page.current === this.page.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.setPage({ current: this.page.current + 1 });
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toActionNextPaper() {
+      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 leaderGradeCurPaper({ selectedLevel }) {
+      await paperSelectLevelOrScore(
+        this.curPaper.id, // is taskId
+        selectedLevel,
+        "ROUGH_LEVEL"
+      );
+      this.updateStepLevel(this.curStep, "shiftScore", 1);
+      this.toActionNextPaper();
+    },
+    async gradeCurPaper(level) {
+      let gradeRes = null;
+      if (this.curPaper.selfCheck) {
+        gradeRes = await markerSelfCheckLevel(
+          this.curPaper.id, // is taskId
+          level.name
+        );
+      } else {
+        gradeRes = await paperSelectLevelOrScore(
+          this.curPaper.id, // is taskId
+          level.name,
+          this.curSubject.stage
+        );
+      }
+      if (!gradeRes) return;
+
+      if (this.carouselType) {
+        this.updateStepLevel(
+          { type: "done", name: this.curPaper.level },
+          level.name,
+          1
+        );
+
+        this.$refs.CarouselPapersPreview.cancel();
+        this.$refs.MarkerHistory.updatePapers();
+      } else {
+        if (!this.curPaper.selfCheck)
+          this.updateStepLevel(this.curStep, level.name, 1);
+
+        // 待评阶段:自查卷获取逻辑
+        if (this.IS_UNDO_STEP && gradeRes.hasSelfTask) {
+          await this.gotoSelfCheckTask();
+          return;
+        }
+        this.toActionNextPaper();
+      }
+    },
+    async passCurPaper() {
+      await paperTaskPass(this.filter.stage, this.curPaper.id);
+      this.toActionNextPaper();
+    },
+    imagePreviewClose() {
+      this.isFullscreenMarking = false;
+      this.setShortcut(["page", "action"]);
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers, type) {
+      this.carouselType = type;
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+        this.setShortcut(["action"]);
+      });
+    },
+    selectCarouselPaper(index) {
+      this.paperKey = this.$randomCode();
+      this.curCarouselPaperIndex = index;
+      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 (
+        type === "next" &&
+        this.curCarouselPaperIndex < this.carouselPapers.length - 1
+      ) {
+        this.curCarouselPaperIndex++;
+      } else {
+        return;
+      }
+      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.setShortcut([]);
+      this.isFullscreenMarking = false;
+      this.carouselType = "";
+    },
+    // header
+    toHistory() {
+      this.setShortcut([]);
+      this.$refs.MarkerHistory.open();
+    },
+    async historyClose() {
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+      this.setShortcut(["page", "action"]);
+    },
+    toStandard() {
+      this.setShortcut([]);
+      this.$refs.MarkerStandard.open();
+    },
+    standardClose() {
+      this.selectPaper(this.curPaperIndex);
+      this.setShortcut(["page", "action"]);
+    },
+    async toStatistics() {
+      this.setShortcut([]);
+      await this.getStepLevels();
+      this.$refs.MarkerStatistics.open();
+    },
+    statisticsClose() {
+      this.setShortcut(["page", "action"]);
+    },
+  },
+  beforeDestroy() {
+    this.clearState();
+  },
+};
+</script>

+ 577 - 577
src/modules/grading/marker/MarkerHeader.vue

@@ -1,577 +1,577 @@
-<template>
-  <div class="marker-header">
-    <div class="header-main">
-      <!-- left action -->
-      <div class="header-group">
-        <div class="header-part">
-          <Dropdown
-            v-if="areas.length > 1"
-            placement="bottom"
-            transfer
-            trigger="click"
-            transfer-class-name="marker-dropdown"
-            @on-click="areaClick"
-          >
-            <span class="el-dropdown-link">
-              {{ curArea.areaName }} <Icon type="ios-arrow-down"></Icon>
-            </span>
-            <DropdownMenu slot="list">
-              <DropdownItem
-                v-for="area in areas"
-                :key="area.id"
-                :name="area.id"
-                >{{ area.areaName }}</DropdownItem
-              >
-            </DropdownMenu>
-          </Dropdown>
-          <p v-else>{{ curArea.areaName }}</p>
-        </div>
-        <div v-if="showStatistics" class="header-part" @click="toStatistics">
-          <p>统计分析 <Icon type="ios-arrow-down"></Icon></p>
-        </div>
-      </div>
-      <!-- header-page -->
-      <div class="header-group header-page">
-        <div class="page-total">共{{ page.total }}张</div>
-        <div class="page-item" @click="toFirstPage" title="首页">
-          <Icon type="ios-skip-backward" />
-        </div>
-        <div class="page-item" @click="toPrevPage" title="上一页">
-          <Icon type="md-arrow-dropleft" />
-        </div>
-        <Poptip
-          popper-class="marker-popper"
-          placement="bottom"
-          trigger="hover"
-          transfer
-        >
-          <div class="page-item page-cpage">
-            <span>{{ page.current }}</span
-            ><span>/</span><span>{{ page.totalPage }}</span>
-          </div>
-          <div class="header-filter-body dark-mark" slot="content">
-            <div class="filter-part-body">
-              <span class="filter-label">页面跳转:</span>
-              <InputNumber
-                class="filter-input"
-                :min="1"
-                :max="page.totalPage"
-                :step="1"
-                :precision="0"
-                v-model="pageNo"
-              ></InputNumber>
-              <Button
-                type="primary"
-                size="small"
-                class="filter-btn"
-                @click="pageNoSet"
-                >跳转</Button
-              >
-            </div>
-          </div>
-        </Poptip>
-        <div class="page-item" @click="toNextPage" title="下一页">
-          <Icon type="md-arrow-dropright" />
-        </div>
-        <div class="page-item" @click="toLastPage" title="尾页">
-          <Icon type="ios-skip-forward" />
-        </div>
-        <div class="page-item page-size">
-          <Dropdown
-            placement="bottom"
-            transfer
-            trigger="click"
-            transfer-class-name="marker-dropdown"
-            @on-click="pageSizeChange"
-          >
-            <span class="el-dropdown-link">
-              {{ page.size }}张/页 <Icon type="ios-arrow-down"></Icon>
-            </span>
-            <DropdownMenu slot="list">
-              <DropdownItem
-                v-for="item in pageSizeList"
-                :key="item"
-                :name="item"
-                >{{ item }}</DropdownItem
-              >
-            </DropdownMenu>
-          </Dropdown>
-        </div>
-      </div>
-      <!-- right action -->
-      <div class="header-group">
-        <div
-          v-if="showSelectAll"
-          class="header-part header-selection"
-          @click="toSelectAll"
-        >
-          <div
-            :class="[
-              'image-checkbox',
-              {
-                'image-selected': allSelected
-              }
-            ]"
-          >
-            <Icon v-if="allSelected" type="md-checkmark" />
-          </div>
-          全选
-        </div>
-        <Poptip
-          v-if="IS_MARK_LEADER"
-          popper-class="marker-popper"
-          placement="bottom"
-          trigger="click"
-          transfer
-        >
-          <div class="header-part header-filter">
-            筛选 <Icon type="ios-arrow-down"></Icon>
-          </div>
-          <div
-            class="header-filter-body dark-mark"
-            slot="content"
-            @keydown.stop
-          >
-            <!-- 查询标记 -->
-            <div class="filter-part">
-              <h4 class="filter-part-title">查询标记试卷</h4>
-              <div class="filter-part-body">
-                <Select
-                  class="filter-select"
-                  v-model="markFilter.markerId"
-                  placeholder="评卷员"
-                >
-                  <Option
-                    v-for="item in markers"
-                    :key="item.id"
-                    :value="item.id"
-                    :label="item.name"
-                  ></Option>
-                </Select>
-                <Button
-                  type="primary"
-                  size="small"
-                  class="filter-btn"
-                  @click="searchMarkFilter"
-                  >查询</Button
-                >
-              </div>
-            </div>
-            <!-- 查询密号 -->
-            <div class="filter-part">
-              <h4 class="filter-part-title">密号查询试卷</h4>
-              <div class="filter-part-body">
-                <Select
-                  class="filter-select"
-                  v-model="codeFilter.codeType"
-                  placeholder="密号类型"
-                >
-                  <Option
-                    v-for="item in codeTypes"
-                    :key="item.key"
-                    :value="item.key"
-                    :label="item.val"
-                  ></Option>
-                </Select>
-                <Input
-                  class="filter-input"
-                  v-model.trim="codeFilter.code"
-                  placeholder="输入密号"
-                  clearable
-                >
-                </Input>
-                <Button
-                  type="primary"
-                  size="small"
-                  class="filter-btn"
-                  @click="searchCodeFilter"
-                  >查询</Button
-                >
-              </div>
-            </div>
-          </div>
-        </Poptip>
-        <div class="header-part header-step">
-          <Dropdown
-            placement="bottom"
-            transfer
-            trigger="click"
-            transfer-class-name="marker-dropdown header-step-dropdown"
-            @on-click="stepClick"
-          >
-            <span class="el-dropdown-link">
-              <i>{{ curStep.name | levelNameFilter }}</i>
-              <i>:{{ curStep.count }} </i>
-              <Icon type="ios-arrow-down"></Icon>
-            </span>
-            <DropdownMenu slot="list">
-              <DropdownItem
-                class="header-step-item"
-                v-for="step in steps.otherStep"
-                :key="step.type"
-                :name="step.name"
-              >
-                <i>{{ step.name }}</i>
-                <i>({{ step.count }})</i>
-              </DropdownItem>
-              <DropdownItem
-                class="header-step-item"
-                v-for="step in steps.levelStep"
-                :key="step.name"
-                :name="step.name"
-              >
-                <i>{{ step.name | levelNameFilter }}</i>
-                <i v-if="!IS_MARK_LEADER__SCORE"
-                  >({{ step.count }} / {{ step.gcount }})</i
-                >
-                <i v-else>({{ step.count }})</i>
-              </DropdownItem>
-            </DropdownMenu>
-          </Dropdown>
-        </div>
-        <div v-if="IS_MARK_LEADER" class="header-part" @click="toProgress">
-          <p>{{ stageName }}进度 <Icon type="ios-arrow-down"></Icon></p>
-        </div>
-        <div v-if="showStandard" class="header-part" @click="toStandard">
-          <p>标准卷 <Icon type="ios-arrow-down"></Icon></p>
-        </div>
-        <div class="header-part header-history" @click="toHistory">
-          <p>操作记录 <Icon type="ios-arrow-down"></Icon></p>
-        </div>
-        <div class="header-user">
-          <Dropdown
-            placement="bottom"
-            transfer
-            trigger="click"
-            transfer-class-name="marker-dropdown"
-            @on-click="userClick"
-          >
-            <div class="user-name">
-              <Icon type="md-person" size="16" /> {{ username }}
-              <Icon type="ios-arrow-down"></Icon>
-            </div>
-            <DropdownMenu slot="list">
-              <DropdownItem class="color-default-hover" name="toResetPwd"
-                >修改密码</DropdownItem
-              >
-              <DropdownItem class="color-error-hover" name="logout">
-                退出登录
-              </DropdownItem>
-            </DropdownMenu>
-          </Dropdown>
-        </div>
-      </div>
-    </div>
-
-    <!-- fast-level-nav -->
-    <div v-if="ribbonSet.fastLevelNav" class="header-group fast-nav">
-      <div class="fast-nav-list">
-        <div
-          v-for="step in steps.levelStep"
-          :key="step.name"
-          :class="[
-            'fast-nav-item',
-            { 'is-active': curStep.name === step.name }
-          ]"
-          @click="stepClick(step.name)"
-        >
-          {{ step.name | levelNameFilter }}
-          <span>({{ step.count }})</span>
-        </div>
-        <div
-          v-for="step in steps.otherStep"
-          :key="step.name"
-          :class="[
-            'fast-nav-item',
-            { 'is-active': curStep.name === step.name }
-          ]"
-          @click="stepClick(step.name)"
-        >
-          {{ step.name }}
-          <span>({{ step.count }})</span>
-        </div>
-        <div
-          class="fast-nav-item fast-nav-close is-danger"
-          title="关闭快捷档位导航"
-          @click="closeFastNav"
-        >
-          <Icon type="md-close" :size="18" />
-        </div>
-      </div>
-    </div>
-
-    <!-- ResetPwd -->
-    <reset-pwd ref="ResetPwd"></reset-pwd>
-  </div>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-import { areaList, leaderMarkUserList, logout } from "@/api";
-import ResetPwd from "@/modules/login/ResetPwd";
-import { CODE_TYPE, SUBJECT_STAGE } from "@/constants/enumerate";
-
-export default {
-  name: "marker-header",
-  components: { ResetPwd },
-  props: {
-    showStandard: {
-      type: Boolean,
-      default: true
-    },
-    showStatistics: {
-      type: Boolean,
-      default: true
-    },
-    showSelectAll: {
-      type: Boolean,
-      default: false
-    }
-  },
-  data() {
-    return {
-      filter: {
-        workId: "",
-        subject: ""
-      },
-      username: this.$ls.get("user", { loginName: "" }).loginName,
-      pageVisible: false,
-      pageSizeList: [2, 3, 4, 6, 8, 9, 10, 12, 15, 16, 20, 24],
-      pageNo: 1,
-      allSelected: false,
-      codeTypes: [],
-      codeFilter: {
-        codeType: "examNumber",
-        code: ""
-      },
-      markers: [],
-      markFilter: {
-        markerId: ""
-      }
-    };
-  },
-  computed: {
-    ...mapState("marker", [
-      "paramsSet",
-      "page",
-      "curStep",
-      "steps",
-      "curArea",
-      "curSubject",
-      "areas",
-      "IS_MARK_LEADER",
-      "shortcutKeyStatus",
-      "ribbonSet"
-    ]),
-    stageName() {
-      return this.getStageName(
-        this.curSubject.stage,
-        this.curSubject.roughLevelEnable
-      ).replace("阶段", "");
-    },
-    IS_MARK_LEADER__SCORE() {
-      return this.IS_MARK_LEADER && this.curSubject.stage === "SCORE";
-    }
-  },
-  watch: {
-    "shortcutKeyStatus.page": {
-      immediate: true,
-      handler(val, oldval) {
-        if (val === oldval) return;
-        if (val) {
-          document.addEventListener("keydown", this.keyEvent);
-        } else {
-          document.removeEventListener("keydown", this.keyEvent);
-        }
-      }
-    }
-  },
-  mounted() {
-    const subjectId = this.$route.params.subjectId.split("-");
-    this.filter.workId = subjectId[0];
-    this.filter.subject = subjectId[1];
-    this.getAreaList();
-    if (this.IS_MARK_LEADER) this.getLeaderMarkerList();
-
-    this.codeTypes = Object.entries(CODE_TYPE)
-      .map(([key, val]) => {
-        return {
-          key,
-          val
-        };
-      })
-      .filter(item => item.key !== "examNumber");
-  },
-  methods: {
-    ...mapMutations("marker", ["setPage", "setAreas", "setRibbonSet"]),
-    async getAreaList() {
-      const data = await areaList(this.filter);
-      const areas = data.map(item => {
-        return {
-          id: item.id,
-          areaName: item.areaName,
-          areaCode: item.areaCode
-        };
-      });
-      this.setAreas(areas);
-
-      if (!this.curArea.id) {
-        this.$emit("area-change", areas[0]);
-      }
-    },
-    async getLeaderMarkerList() {
-      const markerId = this.$ls.get("user", { id: "" }).id;
-      const data = await leaderMarkUserList({
-        ...this.filter,
-        stage: this.curSubject.stage,
-        markerId
-      });
-      this.markers = data || [];
-      const user = this.$ls.get("user", { id: "", name: "" });
-      this.markers.push({
-        id: user.id,
-        name: "我自己"
-      });
-    },
-    getStageName(stage, roughLevelEnable) {
-      let stageName = SUBJECT_STAGE[stage];
-      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档阶段";
-      return stageName;
-    },
-    keyEvent(e) {
-      if (!e.altKey && !e.shiftKey && !e.repeat) {
-        // 左右键切换分页
-        if (e.code === "ArrowLeft") {
-          e.preventDefault();
-          if (e.ctrlKey) {
-            this.toFirstPage();
-          } else {
-            this.toPrevPage();
-          }
-          return;
-        }
-
-        if (e.code === "ArrowRight") {
-          e.preventDefault();
-          if (e.ctrlKey) {
-            this.toLastPage();
-          } else {
-            this.toNextPage();
-          }
-          return;
-        }
-      }
-    },
-    areaClick(val) {
-      if (this.curArea.id === val) return;
-      const curArea = this.areas.find(item => item.id === val);
-      this.$emit("area-change", curArea);
-    },
-    stepClick(val) {
-      const curStep = [...this.steps.levelStep, ...this.steps.otherStep].find(
-        item => item.name === val
-      );
-      this.$emit("step-change", curStep);
-    },
-    changeAllSelect(selected) {
-      this.allSelected = selected;
-    },
-    toSelectAll() {
-      this.allSelected = !this.allSelected;
-      this.$emit("to-select-all", this.allSelected);
-    },
-    toProgress() {
-      this.$emit("to-progress");
-    },
-    toHistory() {
-      this.$emit("to-history");
-    },
-    toStandard() {
-      this.$emit("to-standard");
-    },
-    toStatistics() {
-      this.$emit("to-statistics");
-    },
-    pageNoSet() {
-      this.pageNo = this.pageNo || 1;
-      this.setPage({ current: this.pageNo });
-      this.pageSetChange();
-    },
-    toFirstPage() {
-      this.setPage({ current: 1 });
-      this.pageSetChange();
-    },
-    toLastPage() {
-      this.setPage({ current: this.page.totalPage });
-      this.pageSetChange();
-    },
-    toPrevPage() {
-      if (this.page.current === 1) return;
-      this.setPage({ current: this.page.current - 1 });
-      this.pageSetChange();
-    },
-    toNextPage() {
-      if (this.page.current === this.page.totalPage) return;
-      this.setPage({ current: this.page.current + 1 });
-      this.pageSetChange();
-    },
-    pageSizeChange(size) {
-      let current = this.page.current;
-      const newTotalPage = Math.ceil(this.page.total / size);
-      if (newTotalPage < current) {
-        current = newTotalPage;
-      }
-
-      this.setPage({ size, current });
-      this.pageSetChange();
-    },
-    pageSetChange() {
-      this.pageVisible = false;
-      this.$emit("page-set-change", this.page);
-    },
-    searchCodeFilter() {
-      if (!this.codeFilter.code || !this.codeFilter.codeType) {
-        this.$Message.error("请设置密号类型和密号!");
-        return;
-      }
-      this.$emit("on-code-search", this.codeFilter);
-    },
-    searchMarkFilter() {
-      if (!this.markFilter.markerId) {
-        this.$Message.error("请选择评卷员!");
-        return;
-      }
-      this.$emit("on-mark-search", {
-        type: "mark",
-        params: this.markFilter
-      });
-    },
-    closeFastNav() {
-      const userId = this.$ls.get("user", { id: "" }).id;
-      const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
-      const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
-      const cacheUserRibbonSet = ribbonSet[userId] || { ...this.ribbonSet };
-      ribbonSet[userId] = Object.assign({}, cacheUserRibbonSet, {
-        fastLevelNav: false
-      });
-      this.setRibbonSet(ribbonSet[userId]);
-      window.localStorage.setItem("ribbonSet", JSON.stringify(ribbonSet));
-    },
-    userClick(name) {
-      if (!name) return;
-      this[name]();
-    },
-    toResetPwd() {
-      this.$refs.ResetPwd.open();
-    },
-    async logout() {
-      await logout();
-      this.$ls.clear();
-      this.$router.push({ name: "Login" });
-    }
-  },
-  beforeDestroy() {
-    document.removeEventListener("keydown", this.keyEvent);
-  }
-};
-</script>
+<template>
+  <div class="marker-header">
+    <div class="header-main">
+      <!-- left action -->
+      <div class="header-group">
+        <div class="header-part">
+          <Dropdown
+            v-if="areas.length > 1"
+            placement="bottom"
+            transfer
+            trigger="click"
+            transfer-class-name="marker-dropdown"
+            @on-click="areaClick"
+          >
+            <span class="el-dropdown-link">
+              {{ curArea.areaName }} <Icon type="ios-arrow-down"></Icon>
+            </span>
+            <DropdownMenu slot="list">
+              <DropdownItem
+                v-for="area in areas"
+                :key="area.id"
+                :name="area.id"
+                >{{ area.areaName }}</DropdownItem
+              >
+            </DropdownMenu>
+          </Dropdown>
+          <p v-else>{{ curArea.areaName }}</p>
+        </div>
+        <div v-if="showStatistics" class="header-part" @click="toStatistics">
+          <p>统计分析 <Icon type="ios-arrow-down"></Icon></p>
+        </div>
+      </div>
+      <!-- header-page -->
+      <div class="header-group header-page">
+        <div class="page-total">共{{ page.total }}张</div>
+        <div class="page-item" @click="toFirstPage" title="首页">
+          <Icon type="ios-skip-backward" />
+        </div>
+        <div class="page-item" @click="toPrevPage" title="上一页">
+          <Icon type="md-arrow-dropleft" />
+        </div>
+        <Poptip
+          popper-class="marker-popper"
+          placement="bottom"
+          trigger="hover"
+          transfer
+        >
+          <div class="page-item page-cpage">
+            <span>{{ page.current }}</span
+            ><span>/</span><span>{{ page.totalPage }}</span>
+          </div>
+          <div class="header-filter-body dark-mark" slot="content">
+            <div class="filter-part-body">
+              <span class="filter-label">页面跳转:</span>
+              <InputNumber
+                class="filter-input"
+                :min="1"
+                :max="page.totalPage"
+                :step="1"
+                :precision="0"
+                v-model="pageNo"
+              ></InputNumber>
+              <Button
+                type="primary"
+                size="small"
+                class="filter-btn"
+                @click="pageNoSet"
+                >跳转</Button
+              >
+            </div>
+          </div>
+        </Poptip>
+        <div class="page-item" @click="toNextPage" title="下一页">
+          <Icon type="md-arrow-dropright" />
+        </div>
+        <div class="page-item" @click="toLastPage" title="尾页">
+          <Icon type="ios-skip-forward" />
+        </div>
+        <div class="page-item page-size">
+          <Dropdown
+            placement="bottom"
+            transfer
+            trigger="click"
+            transfer-class-name="marker-dropdown"
+            @on-click="pageSizeChange"
+          >
+            <span class="el-dropdown-link">
+              {{ page.size }}张/页 <Icon type="ios-arrow-down"></Icon>
+            </span>
+            <DropdownMenu slot="list">
+              <DropdownItem
+                v-for="item in pageSizeList"
+                :key="item"
+                :name="item"
+                >{{ item }}</DropdownItem
+              >
+            </DropdownMenu>
+          </Dropdown>
+        </div>
+      </div>
+      <!-- right action -->
+      <div class="header-group">
+        <div
+          v-if="showSelectAll"
+          class="header-part header-selection"
+          @click="toSelectAll"
+        >
+          <div
+            :class="[
+              'image-checkbox',
+              {
+                'image-selected': allSelected,
+              },
+            ]"
+          >
+            <Icon v-if="allSelected" type="md-checkmark" />
+          </div>
+          全选
+        </div>
+        <Poptip
+          v-if="IS_MARK_LEADER"
+          popper-class="marker-popper"
+          placement="bottom"
+          trigger="click"
+          transfer
+        >
+          <div class="header-part header-filter">
+            筛选 <Icon type="ios-arrow-down"></Icon>
+          </div>
+          <div
+            class="header-filter-body dark-mark"
+            slot="content"
+            @keydown.stop
+          >
+            <!-- 查询标记 -->
+            <div class="filter-part">
+              <h4 class="filter-part-title">查询标记试卷</h4>
+              <div class="filter-part-body">
+                <Select
+                  class="filter-select"
+                  v-model="markFilter.markerId"
+                  placeholder="评卷员"
+                >
+                  <Option
+                    v-for="item in markers"
+                    :key="item.id"
+                    :value="item.id"
+                    :label="item.name"
+                  ></Option>
+                </Select>
+                <Button
+                  type="primary"
+                  size="small"
+                  class="filter-btn"
+                  @click="searchMarkFilter"
+                  >查询</Button
+                >
+              </div>
+            </div>
+            <!-- 查询密号 -->
+            <div class="filter-part">
+              <h4 class="filter-part-title">密号查询试卷</h4>
+              <div class="filter-part-body">
+                <Select
+                  class="filter-select"
+                  v-model="codeFilter.codeType"
+                  placeholder="密号类型"
+                >
+                  <Option
+                    v-for="item in codeTypes"
+                    :key="item.key"
+                    :value="item.key"
+                    :label="item.val"
+                  ></Option>
+                </Select>
+                <Input
+                  class="filter-input"
+                  v-model.trim="codeFilter.code"
+                  placeholder="输入密号"
+                  clearable
+                >
+                </Input>
+                <Button
+                  type="primary"
+                  size="small"
+                  class="filter-btn"
+                  @click="searchCodeFilter"
+                  >查询</Button
+                >
+              </div>
+            </div>
+          </div>
+        </Poptip>
+        <div class="header-part header-step">
+          <Dropdown
+            placement="bottom"
+            transfer
+            trigger="click"
+            transfer-class-name="marker-dropdown header-step-dropdown"
+            @on-click="stepClick"
+          >
+            <span class="el-dropdown-link">
+              <i>{{ curStep.name | levelNameFilter }}</i>
+              <i>:{{ curStep.count }} </i>
+              <Icon type="ios-arrow-down"></Icon>
+            </span>
+            <DropdownMenu slot="list">
+              <DropdownItem
+                class="header-step-item"
+                v-for="step in steps.otherStep"
+                :key="step.type"
+                :name="step.name"
+              >
+                <i>{{ step.name }}</i>
+                <i>({{ step.count }})</i>
+              </DropdownItem>
+              <DropdownItem
+                class="header-step-item"
+                v-for="step in steps.levelStep"
+                :key="step.name"
+                :name="step.name"
+              >
+                <i>{{ step.name | levelNameFilter }}</i>
+                <i v-if="!IS_MARK_LEADER__SCORE"
+                  >({{ step.count }} / {{ step.gcount }})</i
+                >
+                <i v-else>({{ step.count }})</i>
+              </DropdownItem>
+            </DropdownMenu>
+          </Dropdown>
+        </div>
+        <div v-if="IS_MARK_LEADER" class="header-part" @click="toProgress">
+          <p>{{ stageName }}进度 <Icon type="ios-arrow-down"></Icon></p>
+        </div>
+        <div v-if="showStandard" class="header-part" @click="toStandard">
+          <p>标准卷 <Icon type="ios-arrow-down"></Icon></p>
+        </div>
+        <div class="header-part header-history" @click="toHistory">
+          <p>操作记录 <Icon type="ios-arrow-down"></Icon></p>
+        </div>
+        <div class="header-user">
+          <Dropdown
+            placement="bottom"
+            transfer
+            trigger="click"
+            transfer-class-name="marker-dropdown"
+            @on-click="userClick"
+          >
+            <div class="user-name">
+              <Icon type="md-person" size="16" /> {{ username }}
+              <Icon type="ios-arrow-down"></Icon>
+            </div>
+            <DropdownMenu slot="list">
+              <DropdownItem class="color-default-hover" name="toResetPwd"
+                >修改密码</DropdownItem
+              >
+              <DropdownItem class="color-error-hover" name="logout">
+                退出登录
+              </DropdownItem>
+            </DropdownMenu>
+          </Dropdown>
+        </div>
+      </div>
+    </div>
+
+    <!-- fast-level-nav -->
+    <div v-if="ribbonSet.fastLevelNav" class="header-group fast-nav">
+      <div class="fast-nav-list">
+        <div
+          v-for="step in steps.levelStep"
+          :key="step.name"
+          :class="[
+            'fast-nav-item',
+            { 'is-active': curStep.name === step.name },
+          ]"
+          @click="stepClick(step.name)"
+        >
+          {{ step.name | levelNameFilter }}
+          <span>({{ step.count }})</span>
+        </div>
+        <div
+          v-for="step in steps.otherStep"
+          :key="step.name"
+          :class="[
+            'fast-nav-item',
+            { 'is-active': curStep.name === step.name },
+          ]"
+          @click="stepClick(step.name)"
+        >
+          {{ step.name }}
+          <span>({{ step.count }})</span>
+        </div>
+        <div
+          class="fast-nav-item fast-nav-close is-danger"
+          title="关闭快捷档位导航"
+          @click="closeFastNav"
+        >
+          <Icon type="md-close" :size="18" />
+        </div>
+      </div>
+    </div>
+
+    <!-- ResetPwd -->
+    <reset-pwd ref="ResetPwd"></reset-pwd>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import { areaList, leaderMarkUserList, logout } from "@/api";
+import ResetPwd from "@/modules/login/ResetPwd";
+import { CODE_TYPE, SUBJECT_STAGE } from "@/constants/enumerate";
+
+export default {
+  name: "marker-header",
+  components: { ResetPwd },
+  props: {
+    showStandard: {
+      type: Boolean,
+      default: true,
+    },
+    showStatistics: {
+      type: Boolean,
+      default: true,
+    },
+    showSelectAll: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      filter: {
+        workId: "",
+        subject: "",
+      },
+      username: this.$ls.get("user", { loginName: "" }).loginName,
+      pageVisible: false,
+      pageSizeList: [2, 3, 4, 6, 8, 9, 10, 12, 15, 16, 20, 24],
+      pageNo: 1,
+      allSelected: false,
+      codeTypes: [],
+      codeFilter: {
+        codeType: "examNumber",
+        code: "",
+      },
+      markers: [],
+      markFilter: {
+        markerId: "",
+      },
+    };
+  },
+  computed: {
+    ...mapState("marker", [
+      "paramsSet",
+      "page",
+      "curStep",
+      "steps",
+      "curArea",
+      "curSubject",
+      "areas",
+      "IS_MARK_LEADER",
+      "shortcutKeyStatus",
+      "ribbonSet",
+    ]),
+    stageName() {
+      return this.getStageName(
+        this.curSubject.stage,
+        this.curSubject.roughLevelEnable
+      ).replace("阶段", "");
+    },
+    IS_MARK_LEADER__SCORE() {
+      return this.IS_MARK_LEADER && this.curSubject.stage === "SCORE";
+    },
+  },
+  watch: {
+    "shortcutKeyStatus.page": {
+      immediate: true,
+      handler(val, oldval) {
+        if (val === oldval) return;
+        if (val) {
+          document.addEventListener("keydown", this.keyEvent);
+        } else {
+          document.removeEventListener("keydown", this.keyEvent);
+        }
+      },
+    },
+  },
+  mounted() {
+    const subjectId = this.$route.params.subjectId.split("-");
+    this.filter.workId = subjectId[0];
+    this.filter.subject = subjectId[1];
+    this.getAreaList();
+    if (this.IS_MARK_LEADER) this.getLeaderMarkerList();
+
+    this.codeTypes = Object.entries(CODE_TYPE)
+      .map(([key, val]) => {
+        return {
+          key,
+          val,
+        };
+      })
+      .filter((item) => item.key !== "examNumber");
+  },
+  methods: {
+    ...mapMutations("marker", ["setPage", "setAreas", "setRibbonSet"]),
+    async getAreaList() {
+      const data = await areaList(this.filter);
+      const areas = data.map((item) => {
+        return {
+          id: item.id,
+          areaName: item.areaName,
+          areaCode: item.areaCode,
+        };
+      });
+      this.setAreas(areas);
+
+      if (!this.curArea.id) {
+        this.$emit("area-change", areas[0]);
+      }
+    },
+    async getLeaderMarkerList() {
+      const markerId = this.$ls.get("user", { id: "" }).id;
+      const data = await leaderMarkUserList({
+        ...this.filter,
+        stage: this.curSubject.stage,
+        markerId,
+      });
+      this.markers = data || [];
+      const user = this.$ls.get("user", { id: "", name: "" });
+      this.markers.push({
+        id: user.id,
+        name: "我自己",
+      });
+    },
+    getStageName(stage, roughLevelEnable) {
+      let stageName = SUBJECT_STAGE[stage];
+      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档阶段";
+      return stageName;
+    },
+    keyEvent(e) {
+      if (!e.altKey && !e.shiftKey && !e.repeat) {
+        // 左右键切换分页
+        if (e.code === "ArrowLeft") {
+          e.preventDefault();
+          if (e.ctrlKey) {
+            this.toFirstPage();
+          } else {
+            this.toPrevPage();
+          }
+          return;
+        }
+
+        if (e.code === "ArrowRight") {
+          e.preventDefault();
+          if (e.ctrlKey) {
+            this.toLastPage();
+          } else {
+            this.toNextPage();
+          }
+          return;
+        }
+      }
+    },
+    areaClick(val) {
+      if (this.curArea.id === val) return;
+      const curArea = this.areas.find((item) => item.id === val);
+      this.$emit("area-change", curArea);
+    },
+    stepClick(val) {
+      const curStep = [...this.steps.levelStep, ...this.steps.otherStep].find(
+        (item) => item.name === val
+      );
+      this.$emit("step-change", curStep);
+    },
+    changeAllSelect(selected) {
+      this.allSelected = selected;
+    },
+    toSelectAll() {
+      this.allSelected = !this.allSelected;
+      this.$emit("to-select-all", this.allSelected);
+    },
+    toProgress() {
+      this.$emit("to-progress");
+    },
+    toHistory() {
+      this.$emit("to-history");
+    },
+    toStandard() {
+      this.$emit("to-standard");
+    },
+    toStatistics() {
+      this.$emit("to-statistics");
+    },
+    pageNoSet() {
+      this.pageNo = this.pageNo || 1;
+      this.setPage({ current: this.pageNo });
+      this.pageSetChange();
+    },
+    toFirstPage() {
+      this.setPage({ current: 1 });
+      this.pageSetChange();
+    },
+    toLastPage() {
+      this.setPage({ current: this.page.totalPage });
+      this.pageSetChange();
+    },
+    toPrevPage() {
+      if (this.page.current === 1) return;
+      this.setPage({ current: this.page.current - 1 });
+      this.pageSetChange();
+    },
+    toNextPage() {
+      if (this.page.current === this.page.totalPage) return;
+      this.setPage({ current: this.page.current + 1 });
+      this.pageSetChange();
+    },
+    pageSizeChange(size) {
+      let current = this.page.current;
+      const newTotalPage = Math.ceil(this.page.total / size);
+      if (newTotalPage < current) {
+        current = newTotalPage;
+      }
+
+      this.setPage({ size, current });
+      this.pageSetChange();
+    },
+    pageSetChange() {
+      this.pageVisible = false;
+      this.$emit("page-set-change", this.page);
+    },
+    searchCodeFilter() {
+      if (!this.codeFilter.code || !this.codeFilter.codeType) {
+        this.$Message.error("请设置密号类型和密号!");
+        return;
+      }
+      this.$emit("on-code-search", this.codeFilter);
+    },
+    searchMarkFilter() {
+      if (!this.markFilter.markerId) {
+        this.$Message.error("请选择评卷员!");
+        return;
+      }
+      this.$emit("on-mark-search", {
+        type: "mark",
+        params: this.markFilter,
+      });
+    },
+    closeFastNav() {
+      const userId = this.$ls.get("user", { id: "" }).id;
+      const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
+      const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
+      const cacheUserRibbonSet = ribbonSet[userId] || { ...this.ribbonSet };
+      ribbonSet[userId] = Object.assign({}, cacheUserRibbonSet, {
+        fastLevelNav: false,
+      });
+      this.setRibbonSet(ribbonSet[userId]);
+      window.localStorage.setItem("ribbonSet", JSON.stringify(ribbonSet));
+    },
+    userClick(name) {
+      if (!name) return;
+      this[name]();
+    },
+    toResetPwd() {
+      this.$refs.ResetPwd.open();
+    },
+    async logout() {
+      await logout();
+      this.$ls.clear();
+      this.$router.push({ name: "Login" });
+    },
+  },
+  beforeDestroy() {
+    document.removeEventListener("keydown", this.keyEvent);
+  },
+};
+</script>

+ 192 - 192
src/modules/grading/marker/MarkerHistory.vue

@@ -1,192 +1,192 @@
-<template>
-  <Modal
-    v-model="modalIsShow"
-    class="marker-history marker-modal"
-    title="操作记录"
-    footer-hide
-    :transition-names="['slide-up', 'fade']"
-    @on-visible-change="visibleChange"
-  >
-    <div class="history-image-list marker-image-list" v-if="papers.length">
-      <div
-        v-for="(paper, index) in papers"
-        :key="paper.id"
-        class="marker-image-item"
-      >
-        <div class="marker-image-content">
-          <marker-image-view :data="paper" @to-review="toReview(index)">
-            <div class="image-info">
-              <div v-if="IS_SCORE" class="image-level">
-                {{ paper.actionResult }}
-              </div>
-              <div v-else class="image-level">
-                {{ paper.actionResult | levelNameFilter }}
-              </div>
-              <div class="image-action-name">{{ paper.actionName }}</div>
-            </div>
-            <div
-              class="image-sn"
-              :title="'NO.' + paper.sn"
-              @click="toReview(index)"
-            >
-              NO.{{ paper.sn }}
-            </div>
-            <div class="image-action">
-              <div :class="['image-action-li']" @click="toMark(paper)">
-                <Icon :class="{ 'mark-act': paper.mark }" type="md-bookmark" />
-              </div>
-            </div>
-          </marker-image-view>
-        </div>
-      </div>
-    </div>
-    <div v-else class="history-image-list marker-image-none">暂无数据</div>
-  </Modal>
-</template>
-
-<script>
-import { mapState } from "vuex";
-
-import { actionHistory, actionLeaderHistory, markTask, markPaper } from "@/api";
-import MarkerImageView from "./MarkerImageView";
-
-export default {
-  name: "marker-history",
-  props: {
-    questionId: {
-      type: [Number, String]
-    },
-    stage: {
-      type: String,
-      default: "LEVEL"
-    }
-  },
-  components: { MarkerImageView },
-  data() {
-    return {
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      modalIsShow: false,
-      workId: "",
-      subject: "",
-      subjectId: this.$route.params.subjectId,
-      userId: "",
-      curPaper: {},
-      papers: [],
-      loading: false
-    };
-  },
-  computed: {
-    ...mapState("marker", ["IS_MARK_LEADER"]),
-    IS_SCORE() {
-      return this.stage === "SCORE";
-    }
-  },
-  mounted() {
-    this.userId = this.$ls.get("user", { id: "" }).id;
-    const subjectId = this.subjectId.split("-");
-    this.workId = subjectId[0];
-    this.subject = subjectId[1];
-  },
-  methods: {
-    visibleChange(visible) {
-      if (visible) {
-        this.updatePapers();
-      } else {
-        this.$emit("on-close");
-      }
-    },
-    async updatePapers() {
-      let data = [];
-      if (this.IS_MARK_LEADER) {
-        const datas = {
-          workId: this.workId,
-          subject: this.subject,
-          questionId: this.questionId
-        };
-
-        data = await actionLeaderHistory(datas);
-      } else {
-        const datas = {
-          markerId: this.userId,
-          stage: this.stage,
-          questionId: this.questionId
-        };
-
-        data = await actionHistory(datas);
-      }
-
-      this.papers = data;
-      this.papers.forEach(paper => {
-        paper.actionResult = this.IS_MARK_LEADER
-          ? this.getLevelResult(paper)
-          : paper.result;
-        paper.actionName = this.IS_MARK_LEADER
-          ? this.getLeaderActionName(paper)
-          : "已评";
-        paper.fontFrom = "history";
-      });
-      return this.papers;
-    },
-    getLevelResult(paper) {
-      return this.stage === "LEVEL" ? paper.level : paper.roughLevel;
-    },
-    getLeaderActionName(info) {
-      if (
-        (this.stage === "LEVEL" && info.sample) ||
-        (this.stage === "ROUGH_LEVEL" && info.roughSample)
-      )
-        return "设立标准卷";
-
-      if (
-        (this.stage === "LEVEL" && info.oneClick) ||
-        (this.stage === "ROUGH_LEVEL" && info.roughOneClick)
-      )
-        return "一键定档";
-      if (info.isRejectedByLeader) return "打回";
-      return "";
-    },
-    updateCachePapers(papers) {
-      papers.forEach(paper => {
-        const paperIndex = this.papers.findIndex(
-          item => item.paperId === paper.paperId
-        );
-        if (paperIndex !== -1) {
-          this.papers.splice(paperIndex, 1);
-        }
-      });
-      this.papers = [...this.papers, ...papers].slice(-5);
-    },
-    async toMark(paper) {
-      if (this.loading) return;
-      this.loading = true;
-      let res = null;
-      if (this.curUserRoleType === "MARK_LEADER") {
-        res = await markPaper({
-          paperId: paper.id,
-          isMark: !paper.mark,
-          role: this.curUserRoleType
-        }).catch(() => {});
-      } else {
-        res = await markTask({
-          markTaskId: paper.id,
-          isMark: !paper.mark,
-          stage: this.stage
-        }).catch(() => {});
-      }
-      this.loading = false;
-      if (!res) return;
-      paper.mark = !paper.mark;
-      this.$emit("on-mark", paper.mark);
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    toReview(index) {
-      this.$emit("on-paper-click", index, this.papers);
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="marker-history marker-modal"
+    title="操作记录"
+    footer-hide
+    :transition-names="['slide-up', 'fade']"
+    @on-visible-change="visibleChange"
+  >
+    <div class="history-image-list marker-image-list" v-if="papers.length">
+      <div
+        v-for="(paper, index) in papers"
+        :key="paper.id"
+        class="marker-image-item"
+      >
+        <div class="marker-image-content">
+          <marker-image-view :data="paper" @to-review="toReview(index)">
+            <div class="image-info">
+              <div v-if="IS_SCORE" class="image-level">
+                {{ paper.actionResult }}
+              </div>
+              <div v-else class="image-level">
+                {{ paper.actionResult | levelNameFilter }}
+              </div>
+              <div class="image-action-name">{{ paper.actionName }}</div>
+            </div>
+            <div
+              class="image-sn"
+              :title="'NO.' + paper.sn"
+              @click="toReview(index)"
+            >
+              NO.{{ paper.sn }}
+            </div>
+            <div class="image-action">
+              <div :class="['image-action-li']" @click="toMark(paper)">
+                <Icon :class="{ 'mark-act': paper.mark }" type="md-bookmark" />
+              </div>
+            </div>
+          </marker-image-view>
+        </div>
+      </div>
+    </div>
+    <div v-else class="history-image-list marker-image-none">暂无数据</div>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+
+import { actionHistory, actionLeaderHistory, markTask, markPaper } from "@/api";
+import MarkerImageView from "./MarkerImageView";
+
+export default {
+  name: "marker-history",
+  props: {
+    questionId: {
+      type: [Number, String],
+    },
+    stage: {
+      type: String,
+      default: "LEVEL",
+    },
+  },
+  components: { MarkerImageView },
+  data() {
+    return {
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      modalIsShow: false,
+      workId: "",
+      subject: "",
+      subjectId: this.$route.params.subjectId,
+      userId: "",
+      curPaper: {},
+      papers: [],
+      loading: false,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["IS_MARK_LEADER"]),
+    IS_SCORE() {
+      return this.stage === "SCORE";
+    },
+  },
+  mounted() {
+    this.userId = this.$ls.get("user", { id: "" }).id;
+    const subjectId = this.subjectId.split("-");
+    this.workId = subjectId[0];
+    this.subject = subjectId[1];
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.updatePapers();
+      } else {
+        this.$emit("on-close");
+      }
+    },
+    async updatePapers() {
+      let data = [];
+      if (this.IS_MARK_LEADER) {
+        const datas = {
+          workId: this.workId,
+          subject: this.subject,
+          questionId: this.questionId,
+        };
+
+        data = await actionLeaderHistory(datas);
+      } else {
+        const datas = {
+          markerId: this.userId,
+          stage: this.stage,
+          questionId: this.questionId,
+        };
+
+        data = await actionHistory(datas);
+      }
+
+      this.papers = data;
+      this.papers.forEach((paper) => {
+        paper.actionResult = this.IS_MARK_LEADER
+          ? this.getLevelResult(paper)
+          : paper.result;
+        paper.actionName = this.IS_MARK_LEADER
+          ? this.getLeaderActionName(paper)
+          : "已评";
+        paper.fontFrom = "history";
+      });
+      return this.papers;
+    },
+    getLevelResult(paper) {
+      return this.stage === "LEVEL" ? paper.level : paper.roughLevel;
+    },
+    getLeaderActionName(info) {
+      if (
+        (this.stage === "LEVEL" && info.sample) ||
+        (this.stage === "ROUGH_LEVEL" && info.roughSample)
+      )
+        return "设立标准卷";
+
+      if (
+        (this.stage === "LEVEL" && info.oneClick) ||
+        (this.stage === "ROUGH_LEVEL" && info.roughOneClick)
+      )
+        return "一键定档";
+      if (info.isRejectedByLeader) return "打回";
+      return "";
+    },
+    updateCachePapers(papers) {
+      papers.forEach((paper) => {
+        const paperIndex = this.papers.findIndex(
+          (item) => item.paperId === paper.paperId
+        );
+        if (paperIndex !== -1) {
+          this.papers.splice(paperIndex, 1);
+        }
+      });
+      this.papers = [...this.papers, ...papers].slice(-5);
+    },
+    async toMark(paper) {
+      if (this.loading) return;
+      this.loading = true;
+      let res = null;
+      if (this.curUserRoleType === "MARK_LEADER") {
+        res = await markPaper({
+          paperId: paper.id,
+          isMark: !paper.mark,
+          role: this.curUserRoleType,
+        }).catch(() => {});
+      } else {
+        res = await markTask({
+          markTaskId: paper.id,
+          isMark: !paper.mark,
+          stage: this.stage,
+        }).catch(() => {});
+      }
+      this.loading = false;
+      if (!res) return;
+      paper.mark = !paper.mark;
+      this.$emit("on-mark", paper.mark);
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    toReview(index) {
+      this.$emit("on-paper-click", index, this.papers);
+    },
+  },
+};
+</script>

+ 180 - 180
src/modules/grading/marker/MarkerImageView.vue

@@ -1,180 +1,180 @@
-<template>
-  <div class="marker-image-view">
-    <image-view-contain
-      ref="ImageViewContain"
-      :image="image"
-      @to-review="toReview"
-    ></image-view-contain>
-    <div class="image-view-footer">
-      <slot>
-        <div v-if="IS_LEVEL" class="image-info">
-          <div v-if="image.roughLevel" class="image-level">
-            {{ image.roughLevel | levelNameFilter }}
-          </div>
-          <div v-if="image.level" class="image-level">
-            {{ image.level | levelNameFilter }}
-          </div>
-          <div v-if="IS_SAMPLE" class="image-sample">标</div>
-          <div
-            v-if="canSelect && !IS_SAMPLE"
-            :class="[
-              'image-checkbox',
-              {
-                'image-selected': image.selected
-              }
-            ]"
-            @click="toSelect"
-          >
-            <Icon v-if="image.selected" type="md-checkmark" />
-          </div>
-        </div>
-        <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>
-        <div class="image-title" :title="image.title" @click="toSelect">
-          {{ image.title }}
-        </div>
-        <div class="image-action">
-          <div
-            v-if="canMark"
-            :class="['image-action-li', { 'is-disabled': image.markDisabled }]"
-            @click="toMark"
-          >
-            <Icon :class="{ 'mark-act': image.mark }" type="md-bookmark" />
-          </div>
-          <div class="image-action-li" @click="toRotate">
-            <Icon type="md-refresh-circle" />
-          </div>
-        </div>
-      </slot>
-    </div>
-  </div>
-</template>
-
-<script>
-import ImageViewContain from "@/components/ImageViewContain";
-import { markTask, markPaper } from "@/api";
-
-export default {
-  name: "marker-image-view",
-  components: { ImageViewContain },
-  props: {
-    data: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    stage: {
-      type: String,
-      default: "LEVEL"
-    },
-    canSelect: {
-      type: Boolean,
-      default: true
-    },
-    canMark: {
-      type: Boolean,
-      default: true
-    },
-    selectHandle: {
-      type: Function,
-      default: null
-    }
-  },
-  computed: {
-    IS_LEVEL() {
-      return this.stage === "LEVEL" || this.stage === "ROUGH_LEVEL";
-    },
-    IS_SAMPLE() {
-      return (
-        (this.stage === "LEVEL" && this.image.sample) ||
-        (this.stage === "ROUGH_LEVEL" && this.image.roughSample)
-      );
-    }
-  },
-  created() {
-    this.initData();
-  },
-  watch: {
-    "data.selected": {
-      handler() {
-        this.initData();
-      }
-    }
-  },
-  data() {
-    return {
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      initImage: {
-        id: "",
-        thumbSrc: "",
-        title: "",
-        level: "",
-        roughLevel: "",
-        score: "",
-        deg: 0,
-        mark: false,
-        markDisabled: false,
-        sample: false,
-        roughSample: false,
-        selected: false
-      },
-      loading: false,
-      image: {}
-    };
-  },
-  methods: {
-    initData() {
-      this.image = this.$objAssign(this.initImage, this.data);
-    },
-    toReview() {
-      this.$emit("to-review", this.image);
-    },
-    toRotate() {
-      const image = this.image;
-      image.deg += 90;
-      if (image.deg === 360) image.deg = 0;
-
-      this.$refs.ImageViewContain.resizeImage(image.deg);
-    },
-    async toMark() {
-      if (this.image.markDisabled) return;
-      if (this.loading) return;
-      this.loading = true;
-      let res = null;
-      if (this.curUserRoleType === "MARK_LEADER") {
-        res = await markPaper({
-          paperId: this.image.id,
-          isMark: !this.image.mark,
-          role: this.curUserRoleType
-        }).catch(() => {});
-      } else {
-        res = await markTask({
-          markTaskId: this.image.id,
-          isMark: !this.image.mark,
-          stage: this.stage
-        }).catch(() => {});
-      }
-      this.loading = false;
-      if (!res) return;
-      this.image.mark = !this.image.mark;
-      this.$emit("on-mark", this.image.mark);
-    },
-    toSelect() {
-      if (this.IS_SAMPLE || !this.IS_LEVEL || !this.canSelect) return;
-      if (this.selectHandle && !this.selectHandle(this.image)) return;
-      this.image.selected = !this.image.selected;
-      this.$emit("to-select", this.image);
-    },
-    changeSelect(selected) {
-      if (this.IS_SAMPLE) return;
-      this.image.selected = selected;
-      this.$emit("to-select", this.image);
-    }
-  }
-};
-</script>
+<template>
+  <div class="marker-image-view">
+    <image-view-contain
+      ref="ImageViewContain"
+      :image="image"
+      @to-review="toReview"
+    ></image-view-contain>
+    <div class="image-view-footer">
+      <slot>
+        <div v-if="IS_LEVEL" class="image-info">
+          <div v-if="image.roughLevel" class="image-level">
+            {{ image.roughLevel | levelNameFilter }}
+          </div>
+          <div v-if="image.level" class="image-level">
+            {{ image.level | levelNameFilter }}
+          </div>
+          <div v-if="IS_SAMPLE" class="image-sample">标</div>
+          <div
+            v-if="canSelect && !IS_SAMPLE"
+            :class="[
+              'image-checkbox',
+              {
+                'image-selected': image.selected,
+              },
+            ]"
+            @click="toSelect"
+          >
+            <Icon v-if="image.selected" type="md-checkmark" />
+          </div>
+        </div>
+        <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>
+        <div class="image-title" :title="image.title" @click="toSelect">
+          {{ image.title }}
+        </div>
+        <div class="image-action">
+          <div
+            v-if="canMark"
+            :class="['image-action-li', { 'is-disabled': image.markDisabled }]"
+            @click="toMark"
+          >
+            <Icon :class="{ 'mark-act': image.mark }" type="md-bookmark" />
+          </div>
+          <div class="image-action-li" @click="toRotate">
+            <Icon type="md-refresh-circle" />
+          </div>
+        </div>
+      </slot>
+    </div>
+  </div>
+</template>
+
+<script>
+import ImageViewContain from "@/components/ImageViewContain";
+import { markTask, markPaper } from "@/api";
+
+export default {
+  name: "marker-image-view",
+  components: { ImageViewContain },
+  props: {
+    data: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    stage: {
+      type: String,
+      default: "LEVEL",
+    },
+    canSelect: {
+      type: Boolean,
+      default: true,
+    },
+    canMark: {
+      type: Boolean,
+      default: true,
+    },
+    selectHandle: {
+      type: Function,
+      default: null,
+    },
+  },
+  computed: {
+    IS_LEVEL() {
+      return this.stage === "LEVEL" || this.stage === "ROUGH_LEVEL";
+    },
+    IS_SAMPLE() {
+      return (
+        (this.stage === "LEVEL" && this.image.sample) ||
+        (this.stage === "ROUGH_LEVEL" && this.image.roughSample)
+      );
+    },
+  },
+  created() {
+    this.initData();
+  },
+  watch: {
+    "data.selected": {
+      handler() {
+        this.initData();
+      },
+    },
+  },
+  data() {
+    return {
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      initImage: {
+        id: "",
+        thumbSrc: "",
+        title: "",
+        level: "",
+        roughLevel: "",
+        score: "",
+        deg: 0,
+        mark: false,
+        markDisabled: false,
+        sample: false,
+        roughSample: false,
+        selected: false,
+      },
+      loading: false,
+      image: {},
+    };
+  },
+  methods: {
+    initData() {
+      this.image = this.$objAssign(this.initImage, this.data);
+    },
+    toReview() {
+      this.$emit("to-review", this.image);
+    },
+    toRotate() {
+      const image = this.image;
+      image.deg += 90;
+      if (image.deg === 360) image.deg = 0;
+
+      this.$refs.ImageViewContain.resizeImage(image.deg);
+    },
+    async toMark() {
+      if (this.image.markDisabled) return;
+      if (this.loading) return;
+      this.loading = true;
+      let res = null;
+      if (this.curUserRoleType === "MARK_LEADER") {
+        res = await markPaper({
+          paperId: this.image.id,
+          isMark: !this.image.mark,
+          role: this.curUserRoleType,
+        }).catch(() => {});
+      } else {
+        res = await markTask({
+          markTaskId: this.image.id,
+          isMark: !this.image.mark,
+          stage: this.stage,
+        }).catch(() => {});
+      }
+      this.loading = false;
+      if (!res) return;
+      this.image.mark = !this.image.mark;
+      this.$emit("on-mark", this.image.mark);
+    },
+    toSelect() {
+      if (this.IS_SAMPLE || !this.IS_LEVEL || !this.canSelect) return;
+      if (this.selectHandle && !this.selectHandle(this.image)) return;
+      this.image.selected = !this.image.selected;
+      this.$emit("to-select", this.image);
+    },
+    changeSelect(selected) {
+      if (this.IS_SAMPLE) return;
+      this.image.selected = selected;
+      this.$emit("to-select", this.image);
+    },
+  },
+};
+</script>

+ 264 - 264
src/modules/grading/marker/MarkerStandard.vue

@@ -1,264 +1,264 @@
-<template>
-  <Modal
-    v-model="modalIsShow"
-    class="marker-standard marker-modal"
-    title="标准卷"
-    footer-hide
-    fullscreen
-    @on-visible-change="visibleChange"
-  >
-    <div class="level-list">
-      <div
-        v-for="(level, index) in levels"
-        :key="index"
-        :class="['level-item', { 'level-item-act': curLevel === level.name }]"
-        @click="setCurLevel(level.name)"
-      >
-        {{ level.name | levelNameFilter }}
-      </div>
-      <div
-        :class="['level-item', { 'level-item-act': !curLevel }]"
-        @click="setCurLevel('')"
-      >
-        全部
-      </div>
-    </div>
-
-    <div class="standard-image-list marker-image-list" v-if="papers.length">
-      <div
-        v-for="(paper, index) in papers"
-        :key="paper.id"
-        class="marker-image-item"
-      >
-        <div class="marker-image-content">
-          <marker-image-view :data="paper" @to-review="toReview(index)">
-            <div class="image-info">
-              <div class="image-level">
-                {{ paper.level | levelNameFilter }}
-              </div>
-            </div>
-            <div class="image-title" :title="paper.title">
-              {{ paper.title }}
-            </div>
-            <div v-if="canEditStandard" class="image-action">
-              <Button
-                type="error"
-                size="small"
-                icon="md-trash"
-                :disabled="paper.loading"
-                @click="cancelPaper(paper)"
-              ></Button>
-              <Button
-                type="primary"
-                size="small"
-                icon="md-create"
-                @click="toChangePaper(paper)"
-              ></Button>
-            </div>
-          </marker-image-view>
-        </div>
-      </div>
-    </div>
-    <div v-else class="standard-image-none">
-      <p>暂无数据</p>
-    </div>
-
-    <!-- change-standard -->
-    <Modal
-      class="change-standard marker-modal"
-      v-model="levelModalIsShow"
-      title="修改标准卷"
-      width="400px"
-      :mask-closable="false"
-    >
-      <div class="level-list">
-        <p
-          v-for="level in levels"
-          :key="level.name"
-          :class="[
-            'level-item',
-            {
-              'level-item-act': level.name === curSelectLevel,
-              'level-item-disabled': level.name === curChangePaper.level
-            }
-          ]"
-          @click="selectLevel(level.name)"
-        >
-          {{ level.name | levelNameFilter }}
-        </p>
-      </div>
-
-      <div slot="footer">
-        <Button
-          type="primary"
-          size="small"
-          :disabled="isSubmit || !curSelectLevel"
-          @click="confirmChange"
-          >确认</Button
-        >
-        <Button size="small" @click="cancelChange">取消</Button>
-      </div>
-    </Modal>
-  </Modal>
-</template>
-
-<script>
-import { mapState } from "vuex";
-import { paperList, cancelStandardPaper, leaderGradingPaper } from "@/api";
-import MarkerImageView from "./MarkerImageView";
-
-export default {
-  name: "marker-standard",
-  props: {
-    questionId: {
-      type: [Number, String]
-    },
-    stage: {
-      type: String,
-      default: "LEVEL"
-    },
-    levels: {
-      type: Array,
-      default() {
-        return [];
-      }
-    }
-  },
-  components: { MarkerImageView },
-  data() {
-    return {
-      modalIsShow: false,
-      curLevel: "",
-      paperList: [],
-      papers: [],
-      isLoading: false,
-      // change standard
-      levelModalIsShow: false,
-      curChangePaper: {},
-      curSelectLevel: null,
-      isSubmit: false
-    };
-  },
-  computed: {
-    ...mapState("marker", ["IS_MARK_LEADER", "paramsSet"]),
-    showStandardPaperManage() {
-      return this.paramsSet.levelConfig["showStandardPaperManage"] !== 0;
-    },
-    canEditStandard() {
-      const user = this.$ls.get("user", {});
-      return (
-        this.IS_MARK_LEADER &&
-        this.showStandardPaperManage &&
-        user.standardVolume
-      );
-    }
-  },
-  methods: {
-    async visibleChange(visible) {
-      if (!visible) {
-        this.$emit("on-close");
-        return;
-      }
-
-      this.getPaperList();
-    },
-    async getPaperList() {
-      this.isLoading = true;
-      const datas = {
-        questionId: this.questionId,
-        level: "",
-        sort: "secretNumber",
-        isSample: true,
-        page: 0,
-        size: 1000
-      };
-      const data = await paperList(datas).catch(() => {});
-      this.isLoading = false;
-      if (!data) return;
-      this.paperList = data.data.map(item => {
-        item.title = `NO.${item.sn}`;
-        item.loading = false;
-        if (this.stage === "ROUGH_LEVEL") item.level = item.roughLevel;
-        return item;
-      });
-      this.paperList.sort((a, b) => (a.level < b.level ? -1 : 1));
-      this.updatePapers();
-    },
-    updatePapers() {
-      if (this.curLevel) {
-        this.papers = this.paperList.filter(
-          paper => paper.level === this.curLevel
-        );
-      } else {
-        this.papers = this.paperList;
-      }
-    },
-    setCurLevel(levelName) {
-      this.curLevel = levelName;
-      this.updatePapers();
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    toReview(index) {
-      this.$emit("on-paper-click", index, this.papers);
-    },
-    cancelPaper(paper) {
-      if (paper.loading) return;
-      this.$Modal.confirm({
-        content: "确定要取消当前标准卷吗?",
-        onOk: async () => {
-          paper.loading = true;
-          const res = await cancelStandardPaper({
-            paperIds: paper.id,
-            stage: this.stage
-          }).catch(() => {});
-          paper.loading = false;
-          if (!res) return;
-          this.getPaperList();
-        }
-      });
-    },
-    // change standard paper
-    toChangePaper(paper) {
-      this.curChangePaper = paper;
-      this.levelModalIsShow = true;
-    },
-    selectLevel(levelName) {
-      if (levelName === this.curChangePaper.level) return;
-      this.curSelectLevel = levelName;
-    },
-    async confirmChange() {
-      if (!this.curSelectLevel) return;
-      if (this.isSubmit) return;
-
-      this.isSubmit = true;
-      const datas = {
-        action: "sampling",
-        level: this.curSelectLevel,
-        originLevel: this.curChangePaper.level,
-        paperIds: this.curChangePaper.id,
-        stage: this.stage
-      };
-      let result = true;
-      await leaderGradingPaper(datas).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-
-      if (!result) return;
-
-      this.$Message.success("操作成功!");
-      this.getPaperList();
-      this.cancelChange();
-    },
-    cancelChange() {
-      this.curSelectLevel = null;
-      this.levelModalIsShow = false;
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="marker-standard marker-modal"
+    title="标准卷"
+    footer-hide
+    fullscreen
+    @on-visible-change="visibleChange"
+  >
+    <div class="level-list">
+      <div
+        v-for="(level, index) in levels"
+        :key="index"
+        :class="['level-item', { 'level-item-act': curLevel === level.name }]"
+        @click="setCurLevel(level.name)"
+      >
+        {{ level.name | levelNameFilter }}
+      </div>
+      <div
+        :class="['level-item', { 'level-item-act': !curLevel }]"
+        @click="setCurLevel('')"
+      >
+        全部
+      </div>
+    </div>
+
+    <div class="standard-image-list marker-image-list" v-if="papers.length">
+      <div
+        v-for="(paper, index) in papers"
+        :key="paper.id"
+        class="marker-image-item"
+      >
+        <div class="marker-image-content">
+          <marker-image-view :data="paper" @to-review="toReview(index)">
+            <div class="image-info">
+              <div class="image-level">
+                {{ paper.level | levelNameFilter }}
+              </div>
+            </div>
+            <div class="image-title" :title="paper.title">
+              {{ paper.title }}
+            </div>
+            <div v-if="canEditStandard" class="image-action">
+              <Button
+                type="error"
+                size="small"
+                icon="md-trash"
+                :disabled="paper.loading"
+                @click="cancelPaper(paper)"
+              ></Button>
+              <Button
+                type="primary"
+                size="small"
+                icon="md-create"
+                @click="toChangePaper(paper)"
+              ></Button>
+            </div>
+          </marker-image-view>
+        </div>
+      </div>
+    </div>
+    <div v-else class="standard-image-none">
+      <p>暂无数据</p>
+    </div>
+
+    <!-- change-standard -->
+    <Modal
+      class="change-standard marker-modal"
+      v-model="levelModalIsShow"
+      title="修改标准卷"
+      width="400px"
+      :mask-closable="false"
+    >
+      <div class="level-list">
+        <p
+          v-for="level in levels"
+          :key="level.name"
+          :class="[
+            'level-item',
+            {
+              'level-item-act': level.name === curSelectLevel,
+              'level-item-disabled': level.name === curChangePaper.level,
+            },
+          ]"
+          @click="selectLevel(level.name)"
+        >
+          {{ level.name | levelNameFilter }}
+        </p>
+      </div>
+
+      <div slot="footer">
+        <Button
+          type="primary"
+          size="small"
+          :disabled="isSubmit || !curSelectLevel"
+          @click="confirmChange"
+          >确认</Button
+        >
+        <Button size="small" @click="cancelChange">取消</Button>
+      </div>
+    </Modal>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { paperList, cancelStandardPaper, leaderGradingPaper } from "@/api";
+import MarkerImageView from "./MarkerImageView";
+
+export default {
+  name: "marker-standard",
+  props: {
+    questionId: {
+      type: [Number, String],
+    },
+    stage: {
+      type: String,
+      default: "LEVEL",
+    },
+    levels: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+  },
+  components: { MarkerImageView },
+  data() {
+    return {
+      modalIsShow: false,
+      curLevel: "",
+      paperList: [],
+      papers: [],
+      isLoading: false,
+      // change standard
+      levelModalIsShow: false,
+      curChangePaper: {},
+      curSelectLevel: null,
+      isSubmit: false,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["IS_MARK_LEADER", "paramsSet"]),
+    showStandardPaperManage() {
+      return this.paramsSet.levelConfig["showStandardPaperManage"] !== 0;
+    },
+    canEditStandard() {
+      const user = this.$ls.get("user", {});
+      return (
+        this.IS_MARK_LEADER &&
+        this.showStandardPaperManage &&
+        user.standardVolume
+      );
+    },
+  },
+  methods: {
+    async visibleChange(visible) {
+      if (!visible) {
+        this.$emit("on-close");
+        return;
+      }
+
+      this.getPaperList();
+    },
+    async getPaperList() {
+      this.isLoading = true;
+      const datas = {
+        questionId: this.questionId,
+        level: "",
+        sort: "secretNumber",
+        isSample: true,
+        page: 0,
+        size: 1000,
+      };
+      const data = await paperList(datas).catch(() => {});
+      this.isLoading = false;
+      if (!data) return;
+      this.paperList = data.data.map((item) => {
+        item.title = `NO.${item.sn}`;
+        item.loading = false;
+        if (this.stage === "ROUGH_LEVEL") item.level = item.roughLevel;
+        return item;
+      });
+      this.paperList.sort((a, b) => (a.level < b.level ? -1 : 1));
+      this.updatePapers();
+    },
+    updatePapers() {
+      if (this.curLevel) {
+        this.papers = this.paperList.filter(
+          (paper) => paper.level === this.curLevel
+        );
+      } else {
+        this.papers = this.paperList;
+      }
+    },
+    setCurLevel(levelName) {
+      this.curLevel = levelName;
+      this.updatePapers();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    toReview(index) {
+      this.$emit("on-paper-click", index, this.papers);
+    },
+    cancelPaper(paper) {
+      if (paper.loading) return;
+      this.$Modal.confirm({
+        content: "确定要取消当前标准卷吗?",
+        onOk: async () => {
+          paper.loading = true;
+          const res = await cancelStandardPaper({
+            paperIds: paper.id,
+            stage: this.stage,
+          }).catch(() => {});
+          paper.loading = false;
+          if (!res) return;
+          this.getPaperList();
+        },
+      });
+    },
+    // change standard paper
+    toChangePaper(paper) {
+      this.curChangePaper = paper;
+      this.levelModalIsShow = true;
+    },
+    selectLevel(levelName) {
+      if (levelName === this.curChangePaper.level) return;
+      this.curSelectLevel = levelName;
+    },
+    async confirmChange() {
+      if (!this.curSelectLevel) return;
+      if (this.isSubmit) return;
+
+      this.isSubmit = true;
+      const datas = {
+        action: "sampling",
+        level: this.curSelectLevel,
+        originLevel: this.curChangePaper.level,
+        paperIds: this.curChangePaper.id,
+        stage: this.stage,
+      };
+      let result = true;
+      await leaderGradingPaper(datas).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+
+      if (!result) return;
+
+      this.$Message.success("操作成功!");
+      this.getPaperList();
+      this.cancelChange();
+    },
+    cancelChange() {
+      this.curSelectLevel = null;
+      this.levelModalIsShow = false;
+    },
+  },
+};
+</script>

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

@@ -1,105 +1,105 @@
-<template>
-  <Modal
-    v-model="modalIsShow"
-    class="marker-statistics marker-modal"
-    title="统计分析"
-    footer-hide
-    fullscreen
-    @on-visible-change="visibleChange"
-  >
-    <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> -->
-        </tr>
-        <tr v-for="(step, sindex) in steps.levelStep" :key="sindex">
-          <td>{{ step.name | levelNameFilter }}</td>
-          <td>{{ step.gcount }}</td>
-          <td>{{ step.finalTotal }}</td>
-          <td>{{ step.pt }}%</td>
-          <td>{{ step.count }}</td>
-          <td>{{ step.finalKdTotal }}</td>
-          <!-- <td>{{ step.kdpt !== null ? step.kdpt + "%" : "" }}</td> -->
-        </tr>
-      </table>
-    </div>
-    <div class="marker-statistics-chart">
-      <h3>分档数量分布图</h3>
-      <echart-render
-        :chart-data="lineChartData"
-        chart-type="darkLines"
-        v-if="lineChartData"
-      ></echart-render>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { mapState } from "vuex";
-import EchartRender from "@/components/EchartRender";
-import { levelNameTransform } from "@/plugins/utils";
-
-export default {
-  name: "marker-statistics",
-  components: { EchartRender },
-  data() {
-    return {
-      modalIsShow: false,
-      lineChartData: null
-    };
-  },
-  computed: {
-    ...mapState("marker", ["paramsSet", "steps"])
-  },
-  methods: {
-    visibleChange(visible) {
-      if (visible) {
-        this.initData();
-      } else {
-        this.lineChartData = null;
-        this.$emit("on-close");
-      }
-    },
-    initData() {
-      const groups = [
-        {
-          key: "percent",
-          label: "当前批次评卷员"
-        },
-        {
-          key: "gpercent",
-          label: "考区定档"
-        }
-      ];
-      this.lineChartData = groups.map(group => {
-        const data = this.steps.levelStep.map(item => {
-          return {
-            name: levelNameTransform(item.name),
-            value: item[group.key]
-          };
-        });
-        return {
-          name: group.label,
-          data
-        };
-      });
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    stepClick(step) {
-      this.cancel();
-      this.$emit("step-change", step.name);
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="marker-statistics marker-modal"
+    title="统计分析"
+    footer-hide
+    fullscreen
+    @on-visible-change="visibleChange"
+  >
+    <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> -->
+        </tr>
+        <tr v-for="(step, sindex) in steps.levelStep" :key="sindex">
+          <td>{{ step.name | levelNameFilter }}</td>
+          <td>{{ step.gcount }}</td>
+          <td>{{ step.finalTotal }}</td>
+          <td>{{ step.pt }}%</td>
+          <td>{{ step.count }}</td>
+          <td>{{ step.finalKdTotal }}</td>
+          <!-- <td>{{ step.kdpt !== null ? step.kdpt + "%" : "" }}</td> -->
+        </tr>
+      </table>
+    </div>
+    <div class="marker-statistics-chart">
+      <h3>分档数量分布图</h3>
+      <echart-render
+        :chart-data="lineChartData"
+        chart-type="darkLines"
+        v-if="lineChartData"
+      ></echart-render>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import EchartRender from "@/components/EchartRender";
+import { levelNameTransform } from "@/plugins/utils";
+
+export default {
+  name: "marker-statistics",
+  components: { EchartRender },
+  data() {
+    return {
+      modalIsShow: false,
+      lineChartData: null,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["paramsSet", "steps"]),
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.initData();
+      } else {
+        this.lineChartData = null;
+        this.$emit("on-close");
+      }
+    },
+    initData() {
+      const groups = [
+        {
+          key: "percent",
+          label: "当前批次评卷员",
+        },
+        {
+          key: "gpercent",
+          label: "考区定档",
+        },
+      ];
+      this.lineChartData = groups.map((group) => {
+        const data = this.steps.levelStep.map((item) => {
+          return {
+            name: levelNameTransform(item.name),
+            value: item[group.key],
+          };
+        });
+        return {
+          name: group.label,
+          data,
+        };
+      });
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    stepClick(step) {
+      this.cancel();
+      this.$emit("step-change", step.name);
+    },
+  },
+};
+</script>

+ 122 - 122
src/modules/grading/marker/store.js

@@ -1,122 +1,122 @@
-const state = {
-  paramsSet: {
-    collectConfig: {},
-    levelConfig: {},
-    roughLevelConfig: {},
-    scoreConfig: {}
-  },
-  page: {
-    current: 1,
-    size: 12,
-    total: 0,
-    totalPage: 1
-  },
-  steps: {},
-  curStep: { name: "", count: 0 },
-  areas: [],
-  curArea: {},
-  curSubject: {},
-  ribbonSet: {
-    keyboardMark: false,
-    needEnterSubmit: true,
-    fastLevelNav: false
-  },
-  curUserRoleType: "",
-  IS_MARKER: false,
-  IS_MARK_LEADER: false,
-  // key shortcut:
-  shortcutKeyStatus: {
-    page: false,
-    action: false
-  },
-  prevShortcutKeyStatus: {
-    page: false,
-    action: false
-  }
-};
-const mutations = {
-  setParamSet(state, paramsSet) {
-    state.paramsSet = paramsSet;
-  },
-  setPage(state, page) {
-    if (
-      Object.prototype.hasOwnProperty.call(page, "totalPage") &&
-      !page.totalPage
-    )
-      page.totalPage = 1;
-    state.page = Object.assign({}, state.page, page);
-  },
-  setSteps(state, steps) {
-    state.steps = steps;
-  },
-  setCurStep(state, curStep) {
-    state.curStep = curStep;
-  },
-  setAreas(state, areas) {
-    state.areas = areas;
-  },
-  setCurArea(state, curArea) {
-    state.curArea = curArea;
-  },
-  setCurSubject(state, curSubject) {
-    state.curSubject = curSubject;
-  },
-  setCurUserRoleType(state, curUserRoleType) {
-    state.curUserRoleType = curUserRoleType;
-    state.IS_MARKER = curUserRoleType === "MARKER";
-    state.IS_MARK_LEADER = curUserRoleType === "MARK_LEADER";
-  },
-  setRibbonSet(state, ribbonSet) {
-    state.ribbonSet = ribbonSet;
-  },
-  setShortcutStatus(state, data) {
-    state.shortcutKeyStatus = Object.assign({}, state.shortcutKeyStatus, data);
-  },
-  setShortcut(state, types) {
-    state.prevShortcutKeyStatus = { ...state.shortcutKeyStatus };
-
-    Object.keys(state.shortcutKeyStatus).forEach(key => {
-      if (key === "action") {
-        if (state.ribbonSet.keyboardMark) {
-          state.shortcutKeyStatus[key] = types.includes(key);
-        }
-      } else {
-        state.shortcutKeyStatus[key] = types.includes(key);
-      }
-    });
-    // console.log(JSON.stringify(state.shortcutKeyStatus));
-  },
-  recoverShortcut(state) {
-    state.shortcutKeyStatus = { ...state.prevShortcutKeyStatus };
-  },
-  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 = {};
-    state.curUserRoleType = "";
-    state.IS_MARKER = false;
-    state.IS_MARK_LEADER = false;
-    state.shortcutKeyStatus = {
-      page: false,
-      action: false
-    };
-    state.prevShortcutKeyStatus = {
-      page: false,
-      action: false
-    };
-  }
-};
-
-export default {
-  namespaced: true,
-  state,
-  mutations
-};
+const state = {
+  paramsSet: {
+    collectConfig: {},
+    levelConfig: {},
+    roughLevelConfig: {},
+    scoreConfig: {},
+  },
+  page: {
+    current: 1,
+    size: 12,
+    total: 0,
+    totalPage: 1,
+  },
+  steps: {},
+  curStep: { name: "", count: 0 },
+  areas: [],
+  curArea: {},
+  curSubject: {},
+  ribbonSet: {
+    keyboardMark: false,
+    needEnterSubmit: true,
+    fastLevelNav: false,
+  },
+  curUserRoleType: "",
+  IS_MARKER: false,
+  IS_MARK_LEADER: false,
+  // key shortcut:
+  shortcutKeyStatus: {
+    page: false,
+    action: false,
+  },
+  prevShortcutKeyStatus: {
+    page: false,
+    action: false,
+  },
+};
+const mutations = {
+  setParamSet(state, paramsSet) {
+    state.paramsSet = paramsSet;
+  },
+  setPage(state, page) {
+    if (
+      Object.prototype.hasOwnProperty.call(page, "totalPage") &&
+      !page.totalPage
+    )
+      page.totalPage = 1;
+    state.page = Object.assign({}, state.page, page);
+  },
+  setSteps(state, steps) {
+    state.steps = steps;
+  },
+  setCurStep(state, curStep) {
+    state.curStep = curStep;
+  },
+  setAreas(state, areas) {
+    state.areas = areas;
+  },
+  setCurArea(state, curArea) {
+    state.curArea = curArea;
+  },
+  setCurSubject(state, curSubject) {
+    state.curSubject = curSubject;
+  },
+  setCurUserRoleType(state, curUserRoleType) {
+    state.curUserRoleType = curUserRoleType;
+    state.IS_MARKER = curUserRoleType === "MARKER";
+    state.IS_MARK_LEADER = curUserRoleType === "MARK_LEADER";
+  },
+  setRibbonSet(state, ribbonSet) {
+    state.ribbonSet = ribbonSet;
+  },
+  setShortcutStatus(state, data) {
+    state.shortcutKeyStatus = Object.assign({}, state.shortcutKeyStatus, data);
+  },
+  setShortcut(state, types) {
+    state.prevShortcutKeyStatus = { ...state.shortcutKeyStatus };
+
+    Object.keys(state.shortcutKeyStatus).forEach((key) => {
+      if (key === "action") {
+        if (state.ribbonSet.keyboardMark) {
+          state.shortcutKeyStatus[key] = types.includes(key);
+        }
+      } else {
+        state.shortcutKeyStatus[key] = types.includes(key);
+      }
+    });
+    // console.log(JSON.stringify(state.shortcutKeyStatus));
+  },
+  recoverShortcut(state) {
+    state.shortcutKeyStatus = { ...state.prevShortcutKeyStatus };
+  },
+  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 = {};
+    state.curUserRoleType = "";
+    state.IS_MARKER = false;
+    state.IS_MARK_LEADER = false;
+    state.shortcutKeyStatus = {
+      page: false,
+      action: false,
+    };
+    state.prevShortcutKeyStatus = {
+      page: false,
+      action: false,
+    };
+  },
+};
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+};

+ 4 - 4
src/modules/inspection/Inspection.vue

@@ -12,7 +12,7 @@
             <i
             <i
               :class="[
               :class="[
                 'icon',
                 'icon',
-                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon
+                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon,
               ]"
               ]"
               v-if="nav.icon"
               v-if="nav.icon"
             ></i>
             ></i>
@@ -44,11 +44,11 @@ export default {
     $route: {
     $route: {
       handler(val) {
       handler(val) {
         this.actCurNav(val);
         this.actCurNav(val);
-      }
-    }
+      },
+    },
   },
   },
   mounted() {
   mounted() {
     this.actCurNav(this.$route);
     this.actCurNav(this.$route);
-  }
+  },
 };
 };
 </script>
 </script>

+ 20 - 20
src/modules/inspection/InspectionActionLogs.vue

@@ -118,7 +118,7 @@ export default {
         studentName: "",
         studentName: "",
         operType: null,
         operType: null,
         startTime: null,
         startTime: null,
-        endTime: null
+        endTime: null,
       },
       },
       actionTypes: [],
       actionTypes: [],
       ACTION_TYPE: {},
       ACTION_TYPE: {},
@@ -133,57 +133,57 @@ export default {
       columns: [
       columns: [
         {
         {
           title: "工作",
           title: "工作",
-          key: "workName"
+          key: "workName",
         },
         },
         {
         {
           title: "操作人",
           title: "操作人",
-          key: "createUserName"
+          key: "createUserName",
         },
         },
         {
         {
           title: "阶段",
           title: "阶段",
-          key: "stageName"
+          key: "stageName",
         },
         },
         {
         {
           title: "角色",
           title: "角色",
-          key: "createRole"
+          key: "createRole",
         },
         },
         {
         {
           title: "科目",
           title: "科目",
           key: "subject",
           key: "subject",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", this.SUBJECT_TYPE[param.row.subject]);
             return h("div", this.SUBJECT_TYPE[param.row.subject]);
-          }
+          },
         },
         },
         {
         {
           title: "准考证号",
           title: "准考证号",
           key: "examNumber",
           key: "examNumber",
-          width: 130
+          width: 130,
         },
         },
         {
         {
           title: "学生姓名",
           title: "学生姓名",
-          key: "studentName"
+          key: "studentName",
         },
         },
         {
         {
           title: "操作类型",
           title: "操作类型",
           key: "operType",
           key: "operType",
           render: (h, param) => {
           render: (h, param) => {
             return h("div", this.ACTION_TYPE[param.row.operType]);
             return h("div", this.ACTION_TYPE[param.row.operType]);
-          }
+          },
         },
         },
         {
         {
           title: "操作前数据",
           title: "操作前数据",
-          key: "operDataBefore"
+          key: "operDataBefore",
         },
         },
         {
         {
           title: "操作后数据",
           title: "操作后数据",
-          key: "operDataAfter"
+          key: "operDataAfter",
         },
         },
         {
         {
           title: "操作时间",
           title: "操作时间",
           key: "createTime",
           key: "createTime",
-          width: 200
-        }
-      ]
+          width: 200,
+        },
+      ],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -200,7 +200,7 @@ export default {
     },
     },
     async getActionTypeList() {
     async getActionTypeList() {
       this.actionTypes = await logTypeList();
       this.actionTypes = await logTypeList();
-      this.actionTypes.map(item => {
+      this.actionTypes.map((item) => {
         this.ACTION_TYPE[item.id] = item.name;
         this.ACTION_TYPE[item.id] = item.name;
       });
       });
     },
     },
@@ -211,7 +211,7 @@ export default {
       const datas = {
       const datas = {
         ...this.filter,
         ...this.filter,
         curPage: this.current - 1,
         curPage: this.current - 1,
-        pageSize: this.size
+        pageSize: this.size,
       };
       };
 
 
       const data = await inspectionActionLogPageList(filterObjNull(datas));
       const data = await inspectionActionLogPageList(filterObjNull(datas));
@@ -223,14 +223,14 @@ export default {
       this.getList();
       this.getList();
     },
     },
     toSearch() {
     toSearch() {
-      this.subjects.map(item => {
+      this.subjects.map((item) => {
         this.SUBJECT_TYPE[item.subject] = item.name;
         this.SUBJECT_TYPE[item.subject] = item.name;
       });
       });
       this.toPage(1);
       this.toPage(1);
     },
     },
     workChange() {
     workChange() {
       this.filter.subject = null;
       this.filter.subject = null;
-      const curWork = this.works.find(item => item.id === this.filter.workId);
+      const curWork = this.works.find((item) => item.id === this.filter.workId);
       this.subjects = curWork.subjects;
       this.subjects = curWork.subjects;
       this.filter.subject = this.subjects[0].subject;
       this.filter.subject = this.subjects[0].subject;
     },
     },
@@ -248,7 +248,7 @@ export default {
           `${this.GLOBAL.domain}/api/export/log/oper?${qsParams(this.filter)}`
           `${this.GLOBAL.domain}/api/export/log/oper?${qsParams(this.filter)}`
         )
         )
       );
       );
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 18 - 18
src/modules/inspection/InspectionCollectLogs.vue

@@ -107,7 +107,7 @@
 import {
 import {
   inspectionCollectLogPageList,
   inspectionCollectLogPageList,
   workList,
   workList,
-  clientUserPageList
+  clientUserPageList,
 } from "@/api";
 } from "@/api";
 import { filterObjNull, qsParams } from "@/plugins/utils";
 import { filterObjNull, qsParams } from "@/plugins/utils";
 
 
@@ -122,7 +122,7 @@ export default {
         studentName: "",
         studentName: "",
         createUserId: null,
         createUserId: null,
         startTime: null,
         startTime: null,
-        endTime: null
+        endTime: null,
       },
       },
       current: 1,
       current: 1,
       size: this.GLOBAL.pageSize,
       size: this.GLOBAL.pageSize,
@@ -135,41 +135,41 @@ export default {
       columns: [
       columns: [
         {
         {
           title: "工作",
           title: "工作",
-          key: "workName"
+          key: "workName",
         },
         },
         {
         {
           title: "科目",
           title: "科目",
-          key: "subject"
+          key: "subject",
         },
         },
         {
         {
           title: "学生姓名",
           title: "学生姓名",
-          key: "studentName"
+          key: "studentName",
         },
         },
         {
         {
           title: "准考证号",
           title: "准考证号",
           key: "examNumber",
           key: "examNumber",
-          width: 130
+          width: 130,
         },
         },
         {
         {
           title: "采集账号",
           title: "采集账号",
-          key: "createUserName"
+          key: "createUserName",
         },
         },
         {
         {
           title: "上传时间",
           title: "上传时间",
           key: "createTime",
           key: "createTime",
-          width: 200
+          width: 200,
         },
         },
 
 
         {
         {
           title: "识别方式",
           title: "识别方式",
-          key: "remark"
+          key: "remark",
         },
         },
         {
         {
           title: "登录时间",
           title: "登录时间",
           key: "loginTime",
           key: "loginTime",
-          width: 200
-        }
-      ]
+          width: 200,
+        },
+      ],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -186,9 +186,9 @@ export default {
       const data = await clientUserPageList({
       const data = await clientUserPageList({
         workId,
         workId,
         curPage: 0,
         curPage: 0,
-        pageSize: 100
+        pageSize: 100,
       });
       });
-      this.collectionUsers = data.data.filter(item => item.enabled);
+      this.collectionUsers = data.data.filter((item) => item.enabled);
     },
     },
     async getWorkList() {
     async getWorkList() {
       this.works = await workList();
       this.works = await workList();
@@ -197,7 +197,7 @@ export default {
       const datas = {
       const datas = {
         ...this.filter,
         ...this.filter,
         curPage: this.current - 1,
         curPage: this.current - 1,
-        pageSize: this.size
+        pageSize: this.size,
       };
       };
       const data = await inspectionCollectLogPageList(filterObjNull(datas));
       const data = await inspectionCollectLogPageList(filterObjNull(datas));
       this.dataList = data.data;
       this.dataList = data.data;
@@ -210,7 +210,7 @@ export default {
     workChange() {
     workChange() {
       this.filter.subject = null;
       this.filter.subject = null;
       this.filter.createUserId = null;
       this.filter.createUserId = null;
-      const curWork = this.works.find(item => item.id === this.filter.workId);
+      const curWork = this.works.find((item) => item.id === this.filter.workId);
       this.subjects = curWork.subjects;
       this.subjects = curWork.subjects;
       this.filter.subject = this.subjects[0].subject;
       this.filter.subject = this.subjects[0].subject;
       this.getCollectionUsers(this.filter.workId);
       this.getCollectionUsers(this.filter.workId);
@@ -231,7 +231,7 @@ export default {
           )}`
           )}`
         )
         )
       );
       );
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 348 - 348
src/modules/inspection/InspectionGrading.vue

@@ -1,348 +1,348 @@
-<template>
-  <div class="inspection-grading page-container-flex">
-    <div class="part-box part-box-filter">
-      <Form ref="FilterForm" label-position="left" inline>
-        <FormItem>
-          <Select
-            v-model="filter.workId"
-            @on-change="workChange"
-            placeholder="工作文件夹"
-            style="width: 150px"
-          >
-            <Option
-              v-for="(work, windex) in works"
-              :key="windex"
-              :value="work.id"
-              :label="work.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="filter.subject"
-            @on-change="subjectChange"
-            placeholder="科目"
-          >
-            <Option
-              v-for="subject in subjects"
-              :key="subject.id"
-              :value="subject.subject"
-              :label="subject.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.questionId" placeholder="考区">
-            <Option
-              v-for="area in areas"
-              :key="area.id"
-              :value="area.id"
-              :label="area.areaName"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="filter.status"
-            placeholder="类型"
-            clearable
-            style="width: 120px"
-          >
-            <Option
-              v-for="(val, key) in CHANGE_LEVEL_STATUS"
-              :key="key"
-              :value="key * 1"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Button
-            type="primary"
-            class="btn-form-search"
-            size="small"
-            @click="toPage(1)"
-            >查询</Button
-          >
-        </FormItem>
-      </Form>
-    </div>
-
-    <div class="check-grade" v-if="papers.length">
-      <!-- paper-list -->
-      <div class="check-grade-body part-box">
-        <div class="check-grade-list image-view-list image-view-list-4">
-          <div
-            :class="[
-              'image-view',
-              { 'image-view-act': curPaperIndex === index }
-            ]"
-            v-for="(image, index) in papers"
-            :key="index"
-          >
-            <div class="image-view-container">
-              <h5 class="image-view-title">{{ image.title }}</h5>
-              <div class="image-view-contain">
-                <img
-                  :src="image.thumbSrc"
-                  :alt="image.title"
-                  @click="toReview(index)"
-                />
-              </div>
-            </div>
-          </div>
-        </div>
-        <div class="part-page">
-          <Page
-            :current="current"
-            :total="total"
-            :page-size="size"
-            show-total
-            show-elevator
-            @on-change="toPage"
-          ></Page>
-        </div>
-      </div>
-      <!-- action -->
-      <div
-        :class="[
-          'check-grade-action',
-          { 'check-grade-action-fullscreen': isFullscreenMarking }
-        ]"
-        v-if="curPaper.id"
-      >
-        <div class="action-paper-info">
-          <p>
-            <span>试卷考号:</span><span>{{ curPaper.examNumber }}</span>
-          </p>
-          <p>
-            <span>试卷密号:</span><span>NO.{{ curPaper.sn }}</span>
-          </p>
-        </div>
-        <div class="action-grade-info">
-          <p>
-            <span>原始档位:</span
-            ><span>{{ curPaper.originLevel | levelNameFilter }}</span>
-          </p>
-          <p>
-            <span>申请档位:</span
-            ><span>{{ curPaper.redoLevel | levelNameFilter }}</span>
-          </p>
-        </div>
-        <div
-          :class="[
-            'action-grade-result',
-            { 'action-grade-result-error': curPaper.auditStatus === 2 }
-          ]"
-          v-if="curPaper.auditStatus !== 0"
-        >
-          <p>{{ curPaper.auditStatus === 1 ? "同意改档" : "不同意改档" }}</p>
-        </div>
-        <div class="action-grade-btn" v-else>
-          <Button shape="circle" type="primary" @click="confirm(1)"
-            >同意改档</Button
-          >
-          <Button shape="circle" type="error" @click="confirm(2)"
-            >不同意改档</Button
-          >
-        </div>
-      </div>
-      <!-- 占位 -->
-      <div class="check-grade-action" v-if="isFullscreenMarking"></div>
-    </div>
-    <div class="check-grade" v-else>
-      <p class="check-grade-none">暂无数据</p>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      class="check-grade-image-preview"
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      @on-close="isFullscreenMarking = false"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import {
-  changeLevelPaperList,
-  inspectionConfirmCheckGrade,
-  workList,
-  areaList
-} from "@/api";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import { CHANGE_LEVEL_STATUS } from "@/constants/enumerate";
-
-export default {
-  name: "inspection-grading",
-  components: { SimpleImagePreview },
-  data() {
-    return {
-      filter: {
-        workId: "",
-        subject: "",
-        questionId: "",
-        status: 0,
-        type: 1
-      },
-      CHANGE_LEVEL_STATUS,
-      works: [],
-      subjects: [],
-      areas: [],
-      current: 1,
-      size: 8,
-      total: 0,
-      totalPage: 1,
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      isFullscreenMarking: false
-    };
-  },
-  mounted() {
-    this.initData();
-  },
-  methods: {
-    async initData() {
-      await this.getWorkList();
-      this.filter.workId = this.works[0].id;
-      this.workChange();
-      await this.getAreaList();
-      this.filter.questionId = this.areas[0].id;
-      this.getList();
-    },
-    async getWorkList() {
-      this.works = await workList();
-    },
-    async getAreaList() {
-      const data = await areaList({
-        workId: this.filter.workId,
-        subject: this.filter.subject
-      });
-      this.areas = data.map(item => {
-        return {
-          id: item.id,
-          areaName: item.areaName,
-          areaCode: item.areaCode
-        };
-      });
-    },
-    async getList() {
-      const datas = {
-        ...this.filter,
-        page: this.current - 1,
-        size: this.size
-      };
-      const data = await changeLevelPaperList(datas);
-      this.papers = data.data.map(item => {
-        item.title = `NO.${item.sn}`;
-        return item;
-      });
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-      this.selectPaper(0);
-    },
-    toPage(page) {
-      this.current = page;
-      this.getList();
-    },
-    workChange() {
-      this.filter.subject = null;
-      this.filter.questionId = null;
-      const curWork = this.works.find(item => item.id === this.filter.workId);
-      this.subjects = curWork.subjects;
-      this.filter.subject = this.subjects[0].subject;
-      this.subjectChange();
-    },
-    subjectChange() {
-      this.areas = [];
-      this.filter.questionId = null;
-      this.getAreaList();
-    },
-    async confirm(isAgree) {
-      if (isAgree === 1) {
-        this.updateCheckGradeState(isAgree);
-        return;
-      }
-
-      this.$Modal.confirm({
-        content: "确定不同意当前改档吗?",
-        onOk: () => {
-          this.updateCheckGradeState(isAgree);
-        }
-      });
-    },
-    async updateCheckGradeState(auditStatus) {
-      await inspectionConfirmCheckGrade({
-        id: this.curPaper.id,
-        auditStatus,
-        userId: this.$ls.get("user", { id: "" }).id
-      });
-      this.toActionNextPaper();
-    },
-    // paper view action
-    toReview(index) {
-      this.isFullscreenMarking = true;
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toActionNextPaper() {
-      if (this.current > 1 && this.papers.length === 1) {
-        this.current--;
-        this.curPaperIndex = this.size;
-      }
-
-      await this.getList();
-      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="inspection-grading page-container-flex">
+    <div class="part-box part-box-filter">
+      <Form ref="FilterForm" label-position="left" inline>
+        <FormItem>
+          <Select
+            v-model="filter.workId"
+            @on-change="workChange"
+            placeholder="工作文件夹"
+            style="width: 150px"
+          >
+            <Option
+              v-for="(work, windex) in works"
+              :key="windex"
+              :value="work.id"
+              :label="work.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="filter.subject"
+            @on-change="subjectChange"
+            placeholder="科目"
+          >
+            <Option
+              v-for="subject in subjects"
+              :key="subject.id"
+              :value="subject.subject"
+              :label="subject.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.questionId" placeholder="考区">
+            <Option
+              v-for="area in areas"
+              :key="area.id"
+              :value="area.id"
+              :label="area.areaName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="filter.status"
+            placeholder="类型"
+            clearable
+            style="width: 120px"
+          >
+            <Option
+              v-for="(val, key) in CHANGE_LEVEL_STATUS"
+              :key="key"
+              :value="key * 1"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Button
+            type="primary"
+            class="btn-form-search"
+            size="small"
+            @click="toPage(1)"
+            >查询</Button
+          >
+        </FormItem>
+      </Form>
+    </div>
+
+    <div class="check-grade" v-if="papers.length">
+      <!-- paper-list -->
+      <div class="check-grade-body part-box">
+        <div class="check-grade-list image-view-list image-view-list-4">
+          <div
+            :class="[
+              'image-view',
+              { 'image-view-act': curPaperIndex === index },
+            ]"
+            v-for="(image, index) in papers"
+            :key="index"
+          >
+            <div class="image-view-container">
+              <h5 class="image-view-title">{{ image.title }}</h5>
+              <div class="image-view-contain">
+                <img
+                  :src="image.thumbSrc"
+                  :alt="image.title"
+                  @click="toReview(index)"
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="part-page">
+          <Page
+            :current="current"
+            :total="total"
+            :page-size="size"
+            show-total
+            show-elevator
+            @on-change="toPage"
+          ></Page>
+        </div>
+      </div>
+      <!-- action -->
+      <div
+        :class="[
+          'check-grade-action',
+          { 'check-grade-action-fullscreen': isFullscreenMarking },
+        ]"
+        v-if="curPaper.id"
+      >
+        <div class="action-paper-info">
+          <p>
+            <span>试卷考号:</span><span>{{ curPaper.examNumber }}</span>
+          </p>
+          <p>
+            <span>试卷密号:</span><span>NO.{{ curPaper.sn }}</span>
+          </p>
+        </div>
+        <div class="action-grade-info">
+          <p>
+            <span>原始档位:</span
+            ><span>{{ curPaper.originLevel | levelNameFilter }}</span>
+          </p>
+          <p>
+            <span>申请档位:</span
+            ><span>{{ curPaper.redoLevel | levelNameFilter }}</span>
+          </p>
+        </div>
+        <div
+          :class="[
+            'action-grade-result',
+            { 'action-grade-result-error': curPaper.auditStatus === 2 },
+          ]"
+          v-if="curPaper.auditStatus !== 0"
+        >
+          <p>{{ curPaper.auditStatus === 1 ? "同意改档" : "不同意改档" }}</p>
+        </div>
+        <div class="action-grade-btn" v-else>
+          <Button shape="circle" type="primary" @click="confirm(1)"
+            >同意改档</Button
+          >
+          <Button shape="circle" type="error" @click="confirm(2)"
+            >不同意改档</Button
+          >
+        </div>
+      </div>
+      <!-- 占位 -->
+      <div class="check-grade-action" v-if="isFullscreenMarking"></div>
+    </div>
+    <div class="check-grade" v-else>
+      <p class="check-grade-none">暂无数据</p>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      class="check-grade-image-preview"
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      @on-close="isFullscreenMarking = false"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import {
+  changeLevelPaperList,
+  inspectionConfirmCheckGrade,
+  workList,
+  areaList,
+} from "@/api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import { CHANGE_LEVEL_STATUS } from "@/constants/enumerate";
+
+export default {
+  name: "inspection-grading",
+  components: { SimpleImagePreview },
+  data() {
+    return {
+      filter: {
+        workId: "",
+        subject: "",
+        questionId: "",
+        status: 0,
+        type: 1,
+      },
+      CHANGE_LEVEL_STATUS,
+      works: [],
+      subjects: [],
+      areas: [],
+      current: 1,
+      size: 8,
+      total: 0,
+      totalPage: 1,
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      isFullscreenMarking: false,
+    };
+  },
+  mounted() {
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      await this.getWorkList();
+      this.filter.workId = this.works[0].id;
+      this.workChange();
+      await this.getAreaList();
+      this.filter.questionId = this.areas[0].id;
+      this.getList();
+    },
+    async getWorkList() {
+      this.works = await workList();
+    },
+    async getAreaList() {
+      const data = await areaList({
+        workId: this.filter.workId,
+        subject: this.filter.subject,
+      });
+      this.areas = data.map((item) => {
+        return {
+          id: item.id,
+          areaName: item.areaName,
+          areaCode: item.areaCode,
+        };
+      });
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        page: this.current - 1,
+        size: this.size,
+      };
+      const data = await changeLevelPaperList(datas);
+      this.papers = data.data.map((item) => {
+        item.title = `NO.${item.sn}`;
+        return item;
+      });
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+      this.selectPaper(0);
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    workChange() {
+      this.filter.subject = null;
+      this.filter.questionId = null;
+      const curWork = this.works.find((item) => item.id === this.filter.workId);
+      this.subjects = curWork.subjects;
+      this.filter.subject = this.subjects[0].subject;
+      this.subjectChange();
+    },
+    subjectChange() {
+      this.areas = [];
+      this.filter.questionId = null;
+      this.getAreaList();
+    },
+    async confirm(isAgree) {
+      if (isAgree === 1) {
+        this.updateCheckGradeState(isAgree);
+        return;
+      }
+
+      this.$Modal.confirm({
+        content: "确定不同意当前改档吗?",
+        onOk: () => {
+          this.updateCheckGradeState(isAgree);
+        },
+      });
+    },
+    async updateCheckGradeState(auditStatus) {
+      await inspectionConfirmCheckGrade({
+        id: this.curPaper.id,
+        auditStatus,
+        userId: this.$ls.get("user", { id: "" }).id,
+      });
+      this.toActionNextPaper();
+    },
+    // paper view action
+    toReview(index) {
+      this.isFullscreenMarking = true;
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toActionNextPaper() {
+      if (this.current > 1 && this.papers.length === 1) {
+        this.current--;
+        this.curPaperIndex = this.size;
+      }
+
+      await this.getList();
+      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

+ 2 - 4
src/modules/inspection/InspectionScore.vue

@@ -1,7 +1,5 @@
 <template>
 <template>
-  <div class="inspection-score">
-    直接使用-main-StudentScore
-  </div>
+  <div class="inspection-score">直接使用-main-StudentScore</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -10,6 +8,6 @@ export default {
   data() {
   data() {
     return {};
     return {};
   },
   },
-  methods: {}
+  methods: {},
 };
 };
 </script>
 </script>

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

@@ -1,211 +1,211 @@
-<template>
-  <div :class="['login', 'login-home', { 'login-dark': isDark }]">
-    <div class="login login-box">
-      <div class="login-title">
-        <h1>美术阅卷系统</h1>
-      </div>
-      <div class="login-form">
-        <Form ref="loginForm" :model="loginModel" :rules="loginRules">
-          <FormItem prop="loginName">
-            <Input
-              size="large"
-              class="input-huge"
-              v-model.trim="loginModel.loginName"
-              prefix="md-person"
-              placeholder="输入账号"
-              clearable
-            ></Input>
-          </FormItem>
-          <FormItem prop="password">
-            <Input
-              size="large"
-              class="input-huge"
-              type="password"
-              v-model.trim="loginModel.password"
-              prefix="md-lock"
-              placeholder="输入密码"
-              clearable
-            ></Input>
-          </FormItem>
-          <FormItem style="margin-top:70px;">
-            <Button
-              long
-              size="large"
-              shape="circle"
-              type="primary"
-              :disabled="isSubmit"
-              @click="submit('loginForm')"
-              >登录</Button
-            >
-          </FormItem>
-        </Form>
-      </div>
-    </div>
-    <div class="login-footer">
-      <p>
-        Copyright ©
-        <a href="http:\\www.qmth.com" target="_blank">www.qmth.com.cn</a>, All
-        Rights Reserved.
-      </p>
-    </div>
-
-    <reset-pwd @confirm="resetSuccess" ref="ResetPwd"></reset-pwd>
-  </div>
-</template>
-
-<script>
-import { mapMutations } from "vuex";
-import { username, password } from "@/plugins/formRules";
-import { login, subjectDetail } from "@/api";
-import ResetPwd from "./ResetPwd";
-import { MARK_LEADER_RIGHTS } from "@/constants/enumerate";
-
-export default {
-  name: "login",
-  components: { ResetPwd },
-  data() {
-    return {
-      loginModel: {
-        loginName: "",
-        password: ""
-      },
-      loginRules: {
-        loginName: username,
-        password
-      },
-      rightRoutes: {
-        ADMIN: {
-          router: "WorkManage"
-        },
-        MARKER_LEVEL: {
-          router: "MarkerGrading"
-        },
-        MARKER_SCORE: {
-          router: "MarkerMarking"
-        },
-        MARK_LEADER_LEVEL: {
-          router: "LeaderGrading"
-        },
-        MARK_LEADER_SCORE: {
-          router: "LeaderMarking"
-        },
-        INSPECTION: {
-          router: "Inspection"
-        },
-        QC: {
-          router: "Quality"
-        }
-      },
-      isSubmit: false
-    };
-  },
-  computed: {
-    isDark() {
-      return !this.$route.name.includes("Admin");
-    }
-  },
-  mounted() {
-    this.$ls.clear();
-    document.addEventListener("keyup", this.keyEvent);
-  },
-  beforeDestroy() {
-    document.removeEventListener("keyup", this.keyEvent);
-  },
-  methods: {
-    ...mapMutations("marker", ["setRibbonSet"]),
-    keyEvent(e) {
-      if (
-        !e.altKey &&
-        !e.shiftKey &&
-        !e.ctrlKey &&
-        !e.repeat &&
-        e.key === "Enter"
-      ) {
-        e.preventDefault();
-        this.submit("loginForm");
-      }
-    },
-    async submit(name) {
-      const valid = await this.$refs[name].validate();
-      if (!valid) return;
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      const data = await login(this.loginModel).catch(() => {});
-      this.isSubmit = false;
-      if (!data) return;
-
-      // 如果是科组长,解析是否只有唯一权限
-      const rights = Object.entries(MARK_LEADER_RIGHTS).filter(
-        ([k, v]) => data[k]
-      );
-      if (rights.length === 1 && !data.leaderConfirm) {
-        data.markLeaderOnlyRight = {
-          code: rights[0][0],
-          ...rights[0][1]
-        };
-      } else {
-        data.markLeaderOnlyRight = null;
-      }
-
-      this.$ls.set("user", data);
-      this.$store.commit("setUser", data);
-      // 初次登陆强制修改密码
-      if (
-        data.role !== "ADMIN" &&
-        data.role !== "INSPECTION" &&
-        !data.pwChangedCount
-      ) {
-        this.$refs.ResetPwd.open();
-        return;
-      }
-
-      const params = {
-        workId: data.workId,
-        subjectId: `${data.workId}-${data.subject}`
-      };
-      // 根据角色跳转不同的路由
-      const { role, markRight } = data;
-      let routerType = role;
-      if (role.includes("MARK")) {
-        const levelStages = ["LEVEL", "ROUGH_LEVEL"];
-        const curSubject = await subjectDetail(params.subjectId);
-        const stage = levelStages.includes(curSubject.stage)
-          ? "LEVEL"
-          : curSubject.stage;
-        routerType = `${role}_${stage}`;
-
-        if (stage === "INIT") {
-          this.$Message.error("当前工作未开启分档!");
-          return;
-        }
-        if (role === "MARKER") {
-          if (
-            (levelStages.includes(stage) && markRight === "ALLOW_SCORING") ||
-            (stage === "SCORE" && markRight === "ALLOW_LEVELING")
-          ) {
-            this.$Message.error("您的权限不够!");
-            return;
-          }
-        }
-
-        this.initRibbonSet(data.id);
-      }
-
-      const routerName = this.rightRoutes[routerType].router;
-      this.$router.push({
-        name: routerName,
-        params
-      });
-    },
-    initRibbonSet(userId) {
-      const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
-      const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
-      if (ribbonSet[userId]) this.setRibbonSet(ribbonSet[userId]);
-    },
-    resetSuccess(newpassword) {
-      this.loginModel.password = newpassword;
-    }
-  }
-};
-</script>
+<template>
+  <div :class="['login', 'login-home', { 'login-dark': isDark }]">
+    <div class="login login-box">
+      <div class="login-title">
+        <h1>美术阅卷系统</h1>
+      </div>
+      <div class="login-form">
+        <Form ref="loginForm" :model="loginModel" :rules="loginRules">
+          <FormItem prop="loginName">
+            <Input
+              size="large"
+              class="input-huge"
+              v-model.trim="loginModel.loginName"
+              prefix="md-person"
+              placeholder="输入账号"
+              clearable
+            ></Input>
+          </FormItem>
+          <FormItem prop="password">
+            <Input
+              size="large"
+              class="input-huge"
+              type="password"
+              v-model.trim="loginModel.password"
+              prefix="md-lock"
+              placeholder="输入密码"
+              clearable
+            ></Input>
+          </FormItem>
+          <FormItem style="margin-top: 70px">
+            <Button
+              long
+              size="large"
+              shape="circle"
+              type="primary"
+              :disabled="isSubmit"
+              @click="submit('loginForm')"
+              >登录</Button
+            >
+          </FormItem>
+        </Form>
+      </div>
+    </div>
+    <div class="login-footer">
+      <p>
+        Copyright ©
+        <a href="http:\\www.qmth.com" target="_blank">www.qmth.com.cn</a>, All
+        Rights Reserved.
+      </p>
+    </div>
+
+    <reset-pwd @confirm="resetSuccess" ref="ResetPwd"></reset-pwd>
+  </div>
+</template>
+
+<script>
+import { mapMutations } from "vuex";
+import { username, password } from "@/plugins/formRules";
+import { login, subjectDetail } from "@/api";
+import ResetPwd from "./ResetPwd";
+import { MARK_LEADER_RIGHTS } from "@/constants/enumerate";
+
+export default {
+  name: "login",
+  components: { ResetPwd },
+  data() {
+    return {
+      loginModel: {
+        loginName: "",
+        password: "",
+      },
+      loginRules: {
+        loginName: username,
+        password,
+      },
+      rightRoutes: {
+        ADMIN: {
+          router: "WorkManage",
+        },
+        MARKER_LEVEL: {
+          router: "MarkerGrading",
+        },
+        MARKER_SCORE: {
+          router: "MarkerMarking",
+        },
+        MARK_LEADER_LEVEL: {
+          router: "LeaderGrading",
+        },
+        MARK_LEADER_SCORE: {
+          router: "LeaderMarking",
+        },
+        INSPECTION: {
+          router: "Inspection",
+        },
+        QC: {
+          router: "Quality",
+        },
+      },
+      isSubmit: false,
+    };
+  },
+  computed: {
+    isDark() {
+      return !this.$route.name.includes("Admin");
+    },
+  },
+  mounted() {
+    this.$ls.clear();
+    document.addEventListener("keyup", this.keyEvent);
+  },
+  beforeDestroy() {
+    document.removeEventListener("keyup", this.keyEvent);
+  },
+  methods: {
+    ...mapMutations("marker", ["setRibbonSet"]),
+    keyEvent(e) {
+      if (
+        !e.altKey &&
+        !e.shiftKey &&
+        !e.ctrlKey &&
+        !e.repeat &&
+        e.key === "Enter"
+      ) {
+        e.preventDefault();
+        this.submit("loginForm");
+      }
+    },
+    async submit(name) {
+      const valid = await this.$refs[name].validate();
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const data = await login(this.loginModel).catch(() => {});
+      this.isSubmit = false;
+      if (!data) return;
+
+      // 如果是科组长,解析是否只有唯一权限
+      const rights = Object.entries(MARK_LEADER_RIGHTS).filter(
+        ([k, v]) => data[k]
+      );
+      if (rights.length === 1 && !data.leaderConfirm) {
+        data.markLeaderOnlyRight = {
+          code: rights[0][0],
+          ...rights[0][1],
+        };
+      } else {
+        data.markLeaderOnlyRight = null;
+      }
+
+      this.$ls.set("user", data);
+      this.$store.commit("setUser", data);
+      // 初次登陆强制修改密码
+      if (
+        data.role !== "ADMIN" &&
+        data.role !== "INSPECTION" &&
+        !data.pwChangedCount
+      ) {
+        this.$refs.ResetPwd.open();
+        return;
+      }
+
+      const params = {
+        workId: data.workId,
+        subjectId: `${data.workId}-${data.subject}`,
+      };
+      // 根据角色跳转不同的路由
+      const { role, markRight } = data;
+      let routerType = role;
+      if (role.includes("MARK")) {
+        const levelStages = ["LEVEL", "ROUGH_LEVEL"];
+        const curSubject = await subjectDetail(params.subjectId);
+        const stage = levelStages.includes(curSubject.stage)
+          ? "LEVEL"
+          : curSubject.stage;
+        routerType = `${role}_${stage}`;
+
+        if (stage === "INIT") {
+          this.$Message.error("当前工作未开启分档!");
+          return;
+        }
+        if (role === "MARKER") {
+          if (
+            (levelStages.includes(stage) && markRight === "ALLOW_SCORING") ||
+            (stage === "SCORE" && markRight === "ALLOW_LEVELING")
+          ) {
+            this.$Message.error("您的权限不够!");
+            return;
+          }
+        }
+
+        this.initRibbonSet(data.id);
+      }
+
+      const routerName = this.rightRoutes[routerType].router;
+      this.$router.push({
+        name: routerName,
+        params,
+      });
+    },
+    initRibbonSet(userId) {
+      const cacheRibbonSet = window.localStorage.getItem("ribbonSet");
+      const ribbonSet = cacheRibbonSet ? JSON.parse(cacheRibbonSet) : {};
+      if (ribbonSet[userId]) this.setRibbonSet(ribbonSet[userId]);
+    },
+    resetSuccess(newpassword) {
+      this.loginModel.password = newpassword;
+    },
+  },
+};
+</script>

+ 11 - 11
src/modules/login/ResetPwd.vue

@@ -54,13 +54,13 @@
               type="primary"
               type="primary"
               :disabled="isSubmit"
               :disabled="isSubmit"
               @click="submit"
               @click="submit"
-              style="width: 130px;margin-right:10px;"
+              style="width: 130px; margin-right: 10px"
               >确定</Button
               >确定</Button
             >
             >
             <Button
             <Button
               size="large"
               size="large"
               shape="circle"
               shape="circle"
-              style="width: 130px;"
+              style="width: 130px"
               @click="cancel"
               @click="cancel"
               >取消</Button
               >取消</Button
             >
             >
@@ -86,7 +86,7 @@ import { password } from "@/plugins/formRules";
 const initModalForm = {
 const initModalForm = {
   // password: "",
   // password: "",
   newpswd: "",
   newpswd: "",
-  renewpswd: ""
+  renewpswd: "",
 };
 };
 export default {
 export default {
   name: "reset-pswd",
   name: "reset-pswd",
@@ -104,7 +104,7 @@ export default {
       isSubmit: false,
       isSubmit: false,
       userId: "",
       userId: "",
       reset: {
       reset: {
-        ...initModalForm
+        ...initModalForm,
       },
       },
       resetRules: {
       resetRules: {
         // password,
         // password,
@@ -113,10 +113,10 @@ export default {
           ...password,
           ...password,
           {
           {
             validator: equalToPswd,
             validator: equalToPswd,
-            trigger: "blur"
-          }
-        ]
-      }
+            trigger: "blur",
+          },
+        ],
+      },
     };
     };
   },
   },
   methods: {
   methods: {
@@ -142,7 +142,7 @@ export default {
       let result = true;
       let result = true;
       await resetPwd({
       await resetPwd({
         userId: this.userId,
         userId: this.userId,
-        password: this.reset.newpswd
+        password: this.reset.newpswd,
       }).catch(() => {
       }).catch(() => {
         result = false;
         result = false;
       });
       });
@@ -150,7 +150,7 @@ export default {
       if (!result) return;
       if (!result) return;
       this.cancel();
       this.cancel();
       this.$emit("confirm", this.reset.newpswd);
       this.$emit("confirm", this.reset.newpswd);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 7 - 7
src/modules/login/fetchSmsMixins.js

@@ -12,7 +12,7 @@ const wstorage = {
   },
   },
   remove(key) {
   remove(key) {
     window.localStorage.removeItem(key);
     window.localStorage.removeItem(key);
-  }
+  },
 };
 };
 
 
 const codeWaitingTime = 60;
 const codeWaitingTime = 60;
@@ -23,7 +23,7 @@ export default {
       isFetchingCode: false,
       isFetchingCode: false,
       codeContent: "获取验证码",
       codeContent: "获取验证码",
       codeWaitingTime,
       codeWaitingTime,
-      time: codeWaitingTime
+      time: codeWaitingTime,
     };
     };
   },
   },
   methods: {
   methods: {
@@ -39,7 +39,7 @@ export default {
       }
       }
     },
     },
     fetchSmsCode() {
     fetchSmsCode() {
-      this.$refs.modalFormComp.validateField("phone", async valid => {
+      this.$refs.modalFormComp.validateField("phone", async (valid) => {
         if (valid) return;
         if (valid) return;
         this.isFetchingCode = true;
         this.isFetchingCode = true;
         const data = await getSmsCode(this.modalForm.phone).catch(() => {
         const data = await getSmsCode(this.modalForm.phone).catch(() => {
@@ -52,7 +52,7 @@ export default {
     changeContent() {
     changeContent() {
       if (!this.isFetchingCode) return;
       if (!this.isFetchingCode) return;
       this.codeContent = "倒计时" + this.time + "s";
       this.codeContent = "倒计时" + this.time + "s";
-      const circleTime = time => {
+      const circleTime = (time) => {
         let t = setInterval(() => {
         let t = setInterval(() => {
           if (time > 1) {
           if (time > 1) {
             time--;
             time--;
@@ -61,7 +61,7 @@ export default {
               this.nameWaitTime,
               this.nameWaitTime,
               {
               {
                 time,
                 time,
-                expire
+                expire,
               },
               },
               expire
               expire
             );
             );
@@ -76,6 +76,6 @@ export default {
         }, 1e3);
         }, 1e3);
       };
       };
       circleTime(this.time);
       circleTime(this.time);
-    }
-  }
+    },
+  },
 };
 };

+ 188 - 188
src/modules/main/CheckData.vue

@@ -1,188 +1,188 @@
-<template>
-  <div class="check-data ">
-    <div class="part-box check-list">
-      <table class="table">
-        <tr>
-          <th>序号</th>
-          <th>校验内容</th>
-          <th>执行结果</th>
-          <th>校验结果</th>
-          <th>操作</th>
-        </tr>
-        <tr v-for="(citem, cindex) in checkItemInfo" :key="cindex">
-          <td>{{ cindex + 1 }}</td>
-          <td>
-            {{ citem.desc }}
-            <InputNumber
-              v-if="paramCheckItems.includes(citem.checkItem)"
-              v-model="citem.paramValue"
-              :min="1"
-              :max="1000"
-            ></InputNumber>
-          </td>
-          <td>{{ TASK_STATUS[citem.status] }}</td>
-          <td>
-            <span :class="{ 'color-error': !citem.result }">{{
-              resultStr(citem.result)
-            }}</span>
-          </td>
-          <td>
-            <Button
-              size="small"
-              type="primary"
-              :loading="loading"
-              :disabled="citem.status === 'RUNNING'"
-              @click="submit(citem)"
-              >开始</Button
-            >
-            <Button
-              size="small"
-              type="primary"
-              :loading="loading"
-              :disabled="!(citem.content || citem.errorCount > 0)"
-              @click="toView(citem)"
-              >详情</Button
-            >
-          </td>
-        </tr>
-      </table>
-    </div>
-
-    <div class="text-center">
-      <Button
-        size="small"
-        type="primary"
-        :disabled="fetching"
-        @click="getCheckDataInfo(false)"
-        >刷新</Button
-      >
-    </div>
-
-    <!-- CheckDataResult -->
-    <CheckDataResult ref="CheckDataResult" :data="curCheckItem" />
-  </div>
-</template>
-
-<script>
-import { checkDataList, dataItemCheck } from "@/api";
-import CheckDataResult from "./components/CheckDataResult.vue";
-import timeMixin from "../../plugins/timeMixin";
-
-export default {
-  name: "check-data",
-  components: { CheckDataResult },
-  mixins: [timeMixin],
-  data() {
-    return {
-      workId: this.$route.params && this.$route.params.workId,
-      checkItemInfo: [],
-      paramCheckItems: ["LEVEL_DIFF", "SCORE_DIFF"],
-      loading: false,
-      fetching: false,
-      curCheckItem: {},
-      TASK_STATUS: {
-        INIT: "未开始",
-        RUNNING: "执行中",
-        FINISH: "已完成"
-      }
-    };
-  },
-  created() {
-    this.initCheckDataInfo();
-    this.getCheckDataInfo();
-  },
-  beforeDestroy() {
-    this.clearSetTs();
-  },
-  methods: {
-    initCheckDataInfo() {
-      const checkItems = [
-        "PAPER_SIZE",
-        "ALL_SCORE",
-        "LEVEL_SCORE_MATCH",
-        "LEVEL_DIFF",
-        "SCORE_DIFF"
-      ];
-      const checkItemDesc = {
-        PAPER_SIZE: "所有试卷图片大小均不为0",
-        ALL_SCORE: "校验每张试卷都有分数",
-        LEVEL_SCORE_MATCH: "每张试卷分数都在其所属档位分数区间内",
-        LEVEL_DIFF: "同一考生各科目档位差不超过",
-        SCORE_DIFF: "同一考生各科目成绩差不超过"
-      };
-      const checkItemInfo = checkItems.map(item => {
-        return {
-          checkItem: item,
-          desc: checkItemDesc[item],
-          paramValue: null,
-          status: "INIT",
-          result: null,
-          errorCount: 0,
-          content: null
-        };
-      });
-      this.checkItemInfo = checkItemInfo;
-    },
-    async getCheckDataInfo() {
-      this.clearSetTs();
-      if (this.fetching) return;
-      this.fetching = true;
-      const res = await checkDataList(this.workId).catch(() => {});
-      this.fetching = false;
-      const data = res || [];
-      const checkItemInfoMap = {};
-      data.forEach(item => {
-        checkItemInfoMap[item.checkItem] = item;
-      });
-
-      this.checkItemInfo = this.checkItemInfo.map(item => {
-        return Object.assign({}, item, checkItemInfoMap[item.checkItem]);
-      });
-      const hasRunningTask = this.checkItemInfo.some(
-        item => item.status === "RUNNING"
-      );
-      if (hasRunningTask) {
-        this.addSetTime(() => {
-          this.getCheckDataInfo(true);
-        }, 5 * 1000);
-      }
-    },
-    resultStr(val) {
-      if (val === null) return "--";
-      return val ? "通过" : "不通过";
-    },
-    toView(row) {
-      if (["PAPER_SIZE", "ALL_SCORE"].includes(row.checkItem)) {
-        this.$Notice.error({
-          title: "校验详情",
-          desc: row.content
-        });
-        return;
-      }
-      this.curCheckItem = row;
-      this.$refs.CheckDataResult.open();
-    },
-    async submit(row) {
-      if (
-        ["LEVEL_DIFF", "SCORE_DIFF"].includes(row.checkItem) &&
-        !row.paramValue
-      ) {
-        this.$Message.error("请输入参数");
-        return;
-      }
-
-      if (this.loading) return;
-      this.loading = true;
-      const res = await dataItemCheck({
-        workId: this.workId,
-        checkItem: row.checkItem,
-        paramValue: row.paramValue
-      }).catch(() => {});
-      this.loading = false;
-      if (!res) return;
-      this.$Message.success("提交成功!");
-      this.getCheckDataInfo();
-    }
-  }
-};
-</script>
+<template>
+  <div class="check-data">
+    <div class="part-box check-list">
+      <table class="table">
+        <tr>
+          <th>序号</th>
+          <th>校验内容</th>
+          <th>执行结果</th>
+          <th>校验结果</th>
+          <th>操作</th>
+        </tr>
+        <tr v-for="(citem, cindex) in checkItemInfo" :key="cindex">
+          <td>{{ cindex + 1 }}</td>
+          <td>
+            {{ citem.desc }}
+            <InputNumber
+              v-if="paramCheckItems.includes(citem.checkItem)"
+              v-model="citem.paramValue"
+              :min="1"
+              :max="1000"
+            ></InputNumber>
+          </td>
+          <td>{{ TASK_STATUS[citem.status] }}</td>
+          <td>
+            <span :class="{ 'color-error': !citem.result }">{{
+              resultStr(citem.result)
+            }}</span>
+          </td>
+          <td>
+            <Button
+              size="small"
+              type="primary"
+              :loading="loading"
+              :disabled="citem.status === 'RUNNING'"
+              @click="submit(citem)"
+              >开始</Button
+            >
+            <Button
+              size="small"
+              type="primary"
+              :loading="loading"
+              :disabled="!(citem.content || citem.errorCount > 0)"
+              @click="toView(citem)"
+              >详情</Button
+            >
+          </td>
+        </tr>
+      </table>
+    </div>
+
+    <div class="text-center">
+      <Button
+        size="small"
+        type="primary"
+        :disabled="fetching"
+        @click="getCheckDataInfo(false)"
+        >刷新</Button
+      >
+    </div>
+
+    <!-- CheckDataResult -->
+    <CheckDataResult ref="CheckDataResult" :data="curCheckItem" />
+  </div>
+</template>
+
+<script>
+import { checkDataList, dataItemCheck } from "@/api";
+import CheckDataResult from "./components/CheckDataResult.vue";
+import timeMixin from "../../plugins/timeMixin";
+
+export default {
+  name: "check-data",
+  components: { CheckDataResult },
+  mixins: [timeMixin],
+  data() {
+    return {
+      workId: this.$route.params && this.$route.params.workId,
+      checkItemInfo: [],
+      paramCheckItems: ["LEVEL_DIFF", "SCORE_DIFF"],
+      loading: false,
+      fetching: false,
+      curCheckItem: {},
+      TASK_STATUS: {
+        INIT: "未开始",
+        RUNNING: "执行中",
+        FINISH: "已完成",
+      },
+    };
+  },
+  created() {
+    this.initCheckDataInfo();
+    this.getCheckDataInfo();
+  },
+  beforeDestroy() {
+    this.clearSetTs();
+  },
+  methods: {
+    initCheckDataInfo() {
+      const checkItems = [
+        "PAPER_SIZE",
+        "ALL_SCORE",
+        "LEVEL_SCORE_MATCH",
+        "LEVEL_DIFF",
+        "SCORE_DIFF",
+      ];
+      const checkItemDesc = {
+        PAPER_SIZE: "所有试卷图片大小均不为0",
+        ALL_SCORE: "校验每张试卷都有分数",
+        LEVEL_SCORE_MATCH: "每张试卷分数都在其所属档位分数区间内",
+        LEVEL_DIFF: "同一考生各科目档位差不超过",
+        SCORE_DIFF: "同一考生各科目成绩差不超过",
+      };
+      const checkItemInfo = checkItems.map((item) => {
+        return {
+          checkItem: item,
+          desc: checkItemDesc[item],
+          paramValue: null,
+          status: "INIT",
+          result: null,
+          errorCount: 0,
+          content: null,
+        };
+      });
+      this.checkItemInfo = checkItemInfo;
+    },
+    async getCheckDataInfo() {
+      this.clearSetTs();
+      if (this.fetching) return;
+      this.fetching = true;
+      const res = await checkDataList(this.workId).catch(() => {});
+      this.fetching = false;
+      const data = res || [];
+      const checkItemInfoMap = {};
+      data.forEach((item) => {
+        checkItemInfoMap[item.checkItem] = item;
+      });
+
+      this.checkItemInfo = this.checkItemInfo.map((item) => {
+        return Object.assign({}, item, checkItemInfoMap[item.checkItem]);
+      });
+      const hasRunningTask = this.checkItemInfo.some(
+        (item) => item.status === "RUNNING"
+      );
+      if (hasRunningTask) {
+        this.addSetTime(() => {
+          this.getCheckDataInfo(true);
+        }, 5 * 1000);
+      }
+    },
+    resultStr(val) {
+      if (val === null) return "--";
+      return val ? "通过" : "不通过";
+    },
+    toView(row) {
+      if (["PAPER_SIZE", "ALL_SCORE"].includes(row.checkItem)) {
+        this.$Notice.error({
+          title: "校验详情",
+          desc: row.content,
+        });
+        return;
+      }
+      this.curCheckItem = row;
+      this.$refs.CheckDataResult.open();
+    },
+    async submit(row) {
+      if (
+        ["LEVEL_DIFF", "SCORE_DIFF"].includes(row.checkItem) &&
+        !row.paramValue
+      ) {
+        this.$Message.error("请输入参数");
+        return;
+      }
+
+      if (this.loading) return;
+      this.loading = true;
+      const res = await dataItemCheck({
+        workId: this.workId,
+        checkItem: row.checkItem,
+        paramValue: row.paramValue,
+      }).catch(() => {});
+      this.loading = false;
+      if (!res) return;
+      this.$Message.success("提交成功!");
+      this.getCheckDataInfo();
+    },
+  },
+};
+</script>

+ 179 - 179
src/modules/main/ClientMonitor.vue

@@ -1,179 +1,179 @@
-<template>
-  <div class="client-monitor page-container-flex">
-    <div class="page-action">
-      <div class="set-navs">
-        <div
-          :class="[
-            'set-navs-item',
-            { 'set-navs-item-act': curNav === nav.name }
-          ]"
-          v-for="nav in navs"
-          :key="nav.name"
-          @click="switchNav(nav.name)"
-        >
-          {{ nav.title }}
-        </div>
-      </div>
-      <Button type="success" icon="md-refresh" @click="getList">查询</Button>
-    </div>
-
-    <div class="image-view-list image-view-list-5">
-      <div class="image-view" v-for="(image, index) in papers" :key="image.key">
-        <div class="image-view-container">
-          <h5 class="image-view-title">{{ image.title }}</h5>
-          <div
-            :class="[
-              'image-view-contain',
-              { 'image-view-none': !image.thumbSrc }
-            ]"
-            :style="image.styles"
-          >
-            <img
-              v-if="image.thumbSrc"
-              :src="image.thumbSrc"
-              :alt="image.title"
-              @click="toReview(index)"
-            />
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <div class="part-page" v-if="total > size">
-      <Page
-        :current="current"
-        :total="total"
-        :page-size="size"
-        show-total
-        show-elevator
-        @on-change="toPage"
-      ></Page>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import { clientMonitorList } from "@/api";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-
-export default {
-  name: "client-monitor",
-  components: { SimpleImagePreview },
-  data() {
-    return {
-      workId: this.$route.params.workId,
-      current: 1,
-      size: this.GLOBAL.pageSize,
-      total: 0,
-      totalPage: 0,
-      dataList: [],
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      navs: [
-        {
-          name: "tailor",
-          title: "阅卷图"
-        },
-        {
-          name: "origin",
-          title: "原图"
-        }
-      ],
-      curNav: "tailor"
-    };
-  },
-  mounted() {
-    this.getList();
-  },
-  methods: {
-    async getList() {
-      const data = await clientMonitorList({
-        workId: this.workId,
-        page: this.current - 1,
-        size: this.size
-      });
-      this.dataList = data.data;
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-      this.switchNav(this.curNav);
-    },
-    toPage(page) {
-      this.current = page;
-      this.getList();
-    },
-    toReview(index) {
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    switchNav(navName) {
-      this.curNav = navName;
-      this.papers = this.dataList.map(item => {
-        let nitem = { ...item };
-        nitem.title = item.createUserName;
-        nitem.key = this.$randomCode();
-        if (this.curNav === "origin") {
-          nitem.imgSrc = item.sheetSrc;
-          nitem.thumbSrc = item.sheetSrc;
-        } else {
-          nitem.imgSrc = item.imgSrc;
-          nitem.thumbSrc = item.thumbSrc;
-        }
-        return nitem;
-      });
-    },
-    selectPaper(index) {
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="client-monitor page-container-flex">
+    <div class="page-action">
+      <div class="set-navs">
+        <div
+          :class="[
+            'set-navs-item',
+            { 'set-navs-item-act': curNav === nav.name },
+          ]"
+          v-for="nav in navs"
+          :key="nav.name"
+          @click="switchNav(nav.name)"
+        >
+          {{ nav.title }}
+        </div>
+      </div>
+      <Button type="success" icon="md-refresh" @click="getList">查询</Button>
+    </div>
+
+    <div class="image-view-list image-view-list-5">
+      <div class="image-view" v-for="(image, index) in papers" :key="image.key">
+        <div class="image-view-container">
+          <h5 class="image-view-title">{{ image.title }}</h5>
+          <div
+            :class="[
+              'image-view-contain',
+              { 'image-view-none': !image.thumbSrc },
+            ]"
+            :style="image.styles"
+          >
+            <img
+              v-if="image.thumbSrc"
+              :src="image.thumbSrc"
+              :alt="image.title"
+              @click="toReview(index)"
+            />
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="part-page" v-if="total > size">
+      <Page
+        :current="current"
+        :total="total"
+        :page-size="size"
+        show-total
+        show-elevator
+        @on-change="toPage"
+      ></Page>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import { clientMonitorList } from "@/api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "client-monitor",
+  components: { SimpleImagePreview },
+  data() {
+    return {
+      workId: this.$route.params.workId,
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      totalPage: 0,
+      dataList: [],
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      navs: [
+        {
+          name: "tailor",
+          title: "阅卷图",
+        },
+        {
+          name: "origin",
+          title: "原图",
+        },
+      ],
+      curNav: "tailor",
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const data = await clientMonitorList({
+        workId: this.workId,
+        page: this.current - 1,
+        size: this.size,
+      });
+      this.dataList = data.data;
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+      this.switchNav(this.curNav);
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    toReview(index) {
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    switchNav(navName) {
+      this.curNav = navName;
+      this.papers = this.dataList.map((item) => {
+        let nitem = { ...item };
+        nitem.title = item.createUserName;
+        nitem.key = this.$randomCode();
+        if (this.curNav === "origin") {
+          nitem.imgSrc = item.sheetSrc;
+          nitem.thumbSrc = item.sheetSrc;
+        } else {
+          nitem.imgSrc = item.imgSrc;
+          nitem.thumbSrc = item.thumbSrc;
+        }
+        return nitem;
+      });
+    },
+    selectPaper(index) {
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

+ 5 - 5
src/modules/main/ExamPaperView.vue

@@ -31,7 +31,7 @@ export default {
       workId: this.$route.params.workId,
       workId: this.$route.params.workId,
       subjectId: this.$route.params.subjectId,
       subjectId: this.$route.params.subjectId,
       subject: "",
       subject: "",
-      dataList: []
+      dataList: [],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -41,16 +41,16 @@ export default {
   methods: {
   methods: {
     async getData() {
     async getData() {
       const data = await uploadPaperList(this.workId);
       const data = await uploadPaperList(this.workId);
-      this.dataList = data.map(area => {
+      this.dataList = data.map((area) => {
         area.subjects = area.subjects.filter(
         area.subjects = area.subjects.filter(
-          subject => subject.subject === this.subject
+          (subject) => subject.subject === this.subject
         );
         );
         return area;
         return area;
       });
       });
     },
     },
     downloadPaper(subject) {
     downloadPaper(subject) {
       if (subject.url) window.open(this.urlAddAuthor(subject.url));
       if (subject.url) window.open(this.urlAddAuthor(subject.url));
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 7 - 7
src/modules/main/Main.vue

@@ -12,7 +12,7 @@
             <i
             <i
               :class="[
               :class="[
                 'icon',
                 'icon',
-                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon
+                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon,
               ]"
               ]"
               v-if="nav.icon"
               v-if="nav.icon"
             ></i>
             ></i>
@@ -42,15 +42,15 @@ export default {
   data() {
   data() {
     return {
     return {
       navs: main,
       navs: main,
-      curNav: {}
+      curNav: {},
     };
     };
   },
   },
   watch: {
   watch: {
     $route: {
     $route: {
       handler(val) {
       handler(val) {
         this.actMainNav();
         this.actMainNav();
-      }
-    }
+      },
+    },
   },
   },
   mounted() {
   mounted() {
     this.actMainNav();
     this.actMainNav();
@@ -58,10 +58,10 @@ export default {
   methods: {
   methods: {
     actMainNav() {
     actMainNav() {
       const router = this.$route.matched.filter(
       const router = this.$route.matched.filter(
-        item => item.name !== "Main"
+        (item) => item.name !== "Main"
       )[0];
       )[0];
       this.actCurNav(router);
       this.actCurNav(router);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 376 - 376
src/modules/main/PaperManage.vue

@@ -1,376 +1,376 @@
-<template>
-  <div class="paper-manage page-container-flex">
-    <div class="part-box">
-      <Form ref="FilterForm" label-position="left" inline>
-        <FormItem>
-          <Select
-            v-model="filter.subject"
-            @on-change="subjectChange"
-            placeholder="科目"
-          >
-            <Option
-              v-for="(item, index) in subjects"
-              :key="index"
-              :value="item.subject"
-              :label="item.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.areaCode" placeholder="选择考区" clearable>
-            <Option
-              v-for="area in areas"
-              :key="area.id"
-              :value="area.areaCode"
-              :label="area.areaName"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model="filter.startNumber"
-            type="text"
-            placeholder="输入开始编号"
-            clearable
-          />
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model="filter.endNumber"
-            type="text"
-            placeholder="输入结束编号"
-            clearable
-          />
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="paperType"
-            @on-change="typeChange"
-            placeholder="类型"
-          >
-            <Option
-              v-for="(val, key) in CAFA_EXCEPTION_TYPE"
-              :key="key"
-              :value="key"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="filter.scanUserId"
-            placeholder="选择采集账号"
-            clearable
-          >
-            <Option
-              v-for="user in scanUsers"
-              :key="user.id"
-              :value="user.id"
-              :label="user.loginName"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model.trim="filter.studentName"
-            placeholder="输入姓名"
-            clearable
-          ></Input>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.sortBy" placeholder="排序方式" clearable>
-            <Option
-              v-for="(val, key) in SORT_RULE_TYPE"
-              :key="key"
-              :value="key"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-      </Form>
-      <div class="box-justify">
-        <Button
-          type="success"
-          shape="circle"
-          icon="upload-white icon"
-          @click="toExportMark"
-          >导出标记试卷</Button
-        >
-        <Button
-          size="small"
-          class="btn-form-search"
-          type="primary"
-          @click="toPage(1)"
-          >查询</Button
-        >
-      </div>
-    </div>
-
-    <image-action-list
-      v-if="papers.length"
-      :data="papers"
-      :actions="actions"
-      @on-review="toReview"
-      ref="ImageActionList"
-    ></image-action-list>
-
-    <div class="part-page">
-      <Page
-        :current="current"
-        :total="total"
-        :page-size="size"
-        show-total
-        show-elevator
-        @on-change="toPage"
-      ></Page>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import { paperPageList, subjectList, areaList, clientUserQuery } from "@/api";
-import { SORT_RULE_TYPE, CAFA_EXCEPTION_TYPE } from "@/constants/enumerate";
-import ImageActionList from "./components/ImageActionList";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-
-export default {
-  name: "paper-manage",
-  components: { ImageActionList, SimpleImagePreview },
-  data() {
-    return {
-      filter: {
-        workId: this.$route.params.workId,
-        studentName: "",
-        areaCode: "",
-        startNumber: null,
-        endNumber: null,
-        subject: "",
-        sortBy: "",
-        scanUserId: "",
-        isManual: null,
-        missing: null,
-        isRelate: null,
-        isMark: null,
-        sizeAbnormal: null
-      },
-      SORT_RULE_TYPE,
-      CAFA_EXCEPTION_TYPE: {},
-      paperType: "9",
-      confirmPaperType: "9",
-      current: 1,
-      size: this.GLOBAL.pageSize,
-      total: 0,
-      totalPage: 0,
-      papers: [],
-      subjects: [],
-      scanUsers: [],
-      areas: [],
-      curPaper: {},
-      curPaperIndex: 0
-    };
-  },
-  computed: {
-    actions() {
-      return this.confirmPaperType === "1"
-        ? ["mark"]
-        : ["rotate", "absent", "mark"];
-    }
-  },
-  mounted() {
-    this.CAFA_EXCEPTION_TYPE = {
-      ...CAFA_EXCEPTION_TYPE,
-      7: "大小异常",
-      8: "已标记",
-      9: "全部"
-    };
-    this.initData();
-    document.addEventListener("keydown", this.keyEvent);
-  },
-  beforeDestroy() {
-    document.removeEventListener("keydown", this.keyEvent);
-  },
-  methods: {
-    async initData() {
-      await this.getSubjects();
-      this.filter.subject = this.subjects[0].subject;
-      this.filter.areaCode = "";
-      this.areas = [];
-      await this.getAreaList();
-      if (!this.filter.areaCode) {
-        this.filter.areaCode = this.areas[0].areaCode;
-      }
-      this.getScanUsers();
-      this.toPage(1);
-    },
-    keyEvent(e) {
-      if (!e.altKey && !e.shiftKey && !e.repeat) {
-        // 左右键切换分页
-        if (e.code === "ArrowLeft") {
-          e.preventDefault();
-          if (e.ctrlKey) {
-            this.toPage(1);
-          } else {
-            if (this.current === 1) return;
-            this.toPage(this.current - 1);
-          }
-          return;
-        }
-
-        if (e.code === "ArrowRight") {
-          e.preventDefault();
-          if (e.ctrlKey) {
-            this.toPage(this.totalPage);
-          } else {
-            if (this.current === this.totalPage) return;
-            this.toPage(this.current + 1);
-          }
-          return;
-        }
-      }
-    },
-    async getAreaList() {
-      const data = await areaList({
-        workId: this.filter.workId,
-        subject: this.filter.subject
-      });
-      this.areas = data.map(item => {
-        return {
-          id: item.id,
-          areaName: item.areaName,
-          areaCode: item.areaCode
-        };
-      });
-      if (this.areas.length === 1) {
-        this.filter.areaCode = this.areas[0].areaCode;
-      }
-    },
-    async getSubjects() {
-      const data = await subjectList(this.filter.workId);
-      this.subjects = data.filter(item => item.enable);
-    },
-    async getScanUsers() {
-      const data = await clientUserQuery(this.filter.workId);
-      this.scanUsers = data;
-    },
-    async getList() {
-      const datas = {
-        ...this.filter,
-        page: this.current - 1,
-        size: this.size
-      };
-      this.papers = [];
-      const data = await paperPageList(datas);
-      this.papers = data.data.map(paper => {
-        const title = paper.manual
-          ? `${paper.examNumber} ${paper.studentName}`
-          : paper.examNumber;
-        return {
-          id: paper.id,
-          key: this.$randomCode(),
-          title,
-          imgSrc: paper.imgSrc,
-          thumbSrc: paper.thumbSrc,
-          missing: paper.missing,
-          mark: paper.adminMark,
-          stage: paper.stage,
-          styles: {},
-          deg: 0
-        };
-      });
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-    },
-    toPage(page) {
-      if (!this.filter.subject || !this.filter.areaCode) {
-        this.$Message.error("请选择科目和考区!");
-        return;
-      }
-      this.confirmPaperType = this.paperType;
-      this.current = page;
-      this.getList();
-    },
-    subjectChange() {
-      this.filter.areaCode = "";
-      this.areas = [];
-      if (!this.filter.subject) return;
-      this.getAreaList();
-    },
-    typeChange() {
-      const typeToField = {
-        0: "missing",
-        1: "isManual",
-        2: "isRelate",
-        7: "sizeAbnormal",
-        8: "isMark"
-      };
-      Object.values(typeToField).forEach(val => {
-        this.filter[val] = typeToField[this.paperType] === val ? true : null;
-      });
-    },
-    toExportMark() {
-      window.open(
-        this.urlAddAuthor(
-          `${this.GLOBAL.domain}/api/export/paper/${this.filter.workId}/mark`
-        )
-      );
-    },
-    // paper view
-    toReview(index) {
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="paper-manage page-container-flex">
+    <div class="part-box">
+      <Form ref="FilterForm" label-position="left" inline>
+        <FormItem>
+          <Select
+            v-model="filter.subject"
+            @on-change="subjectChange"
+            placeholder="科目"
+          >
+            <Option
+              v-for="(item, index) in subjects"
+              :key="index"
+              :value="item.subject"
+              :label="item.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.areaCode" placeholder="选择考区" clearable>
+            <Option
+              v-for="area in areas"
+              :key="area.id"
+              :value="area.areaCode"
+              :label="area.areaName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model="filter.startNumber"
+            type="text"
+            placeholder="输入开始编号"
+            clearable
+          />
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model="filter.endNumber"
+            type="text"
+            placeholder="输入结束编号"
+            clearable
+          />
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="paperType"
+            @on-change="typeChange"
+            placeholder="类型"
+          >
+            <Option
+              v-for="(val, key) in CAFA_EXCEPTION_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="filter.scanUserId"
+            placeholder="选择采集账号"
+            clearable
+          >
+            <Option
+              v-for="user in scanUsers"
+              :key="user.id"
+              :value="user.id"
+              :label="user.loginName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model.trim="filter.studentName"
+            placeholder="输入姓名"
+            clearable
+          ></Input>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.sortBy" placeholder="排序方式" clearable>
+            <Option
+              v-for="(val, key) in SORT_RULE_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+      </Form>
+      <div class="box-justify">
+        <Button
+          type="success"
+          shape="circle"
+          icon="upload-white icon"
+          @click="toExportMark"
+          >导出标记试卷</Button
+        >
+        <Button
+          size="small"
+          class="btn-form-search"
+          type="primary"
+          @click="toPage(1)"
+          >查询</Button
+        >
+      </div>
+    </div>
+
+    <image-action-list
+      v-if="papers.length"
+      :data="papers"
+      :actions="actions"
+      @on-review="toReview"
+      ref="ImageActionList"
+    ></image-action-list>
+
+    <div class="part-page">
+      <Page
+        :current="current"
+        :total="total"
+        :page-size="size"
+        show-total
+        show-elevator
+        @on-change="toPage"
+      ></Page>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import { paperPageList, subjectList, areaList, clientUserQuery } from "@/api";
+import { SORT_RULE_TYPE, CAFA_EXCEPTION_TYPE } from "@/constants/enumerate";
+import ImageActionList from "./components/ImageActionList";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "paper-manage",
+  components: { ImageActionList, SimpleImagePreview },
+  data() {
+    return {
+      filter: {
+        workId: this.$route.params.workId,
+        studentName: "",
+        areaCode: "",
+        startNumber: null,
+        endNumber: null,
+        subject: "",
+        sortBy: "",
+        scanUserId: "",
+        isManual: null,
+        missing: null,
+        isRelate: null,
+        isMark: null,
+        sizeAbnormal: null,
+      },
+      SORT_RULE_TYPE,
+      CAFA_EXCEPTION_TYPE: {},
+      paperType: "9",
+      confirmPaperType: "9",
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      totalPage: 0,
+      papers: [],
+      subjects: [],
+      scanUsers: [],
+      areas: [],
+      curPaper: {},
+      curPaperIndex: 0,
+    };
+  },
+  computed: {
+    actions() {
+      return this.confirmPaperType === "1"
+        ? ["mark"]
+        : ["rotate", "absent", "mark"];
+    },
+  },
+  mounted() {
+    this.CAFA_EXCEPTION_TYPE = {
+      ...CAFA_EXCEPTION_TYPE,
+      7: "大小异常",
+      8: "已标记",
+      9: "全部",
+    };
+    this.initData();
+    document.addEventListener("keydown", this.keyEvent);
+  },
+  beforeDestroy() {
+    document.removeEventListener("keydown", this.keyEvent);
+  },
+  methods: {
+    async initData() {
+      await this.getSubjects();
+      this.filter.subject = this.subjects[0].subject;
+      this.filter.areaCode = "";
+      this.areas = [];
+      await this.getAreaList();
+      if (!this.filter.areaCode) {
+        this.filter.areaCode = this.areas[0].areaCode;
+      }
+      this.getScanUsers();
+      this.toPage(1);
+    },
+    keyEvent(e) {
+      if (!e.altKey && !e.shiftKey && !e.repeat) {
+        // 左右键切换分页
+        if (e.code === "ArrowLeft") {
+          e.preventDefault();
+          if (e.ctrlKey) {
+            this.toPage(1);
+          } else {
+            if (this.current === 1) return;
+            this.toPage(this.current - 1);
+          }
+          return;
+        }
+
+        if (e.code === "ArrowRight") {
+          e.preventDefault();
+          if (e.ctrlKey) {
+            this.toPage(this.totalPage);
+          } else {
+            if (this.current === this.totalPage) return;
+            this.toPage(this.current + 1);
+          }
+          return;
+        }
+      }
+    },
+    async getAreaList() {
+      const data = await areaList({
+        workId: this.filter.workId,
+        subject: this.filter.subject,
+      });
+      this.areas = data.map((item) => {
+        return {
+          id: item.id,
+          areaName: item.areaName,
+          areaCode: item.areaCode,
+        };
+      });
+      if (this.areas.length === 1) {
+        this.filter.areaCode = this.areas[0].areaCode;
+      }
+    },
+    async getSubjects() {
+      const data = await subjectList(this.filter.workId);
+      this.subjects = data.filter((item) => item.enable);
+    },
+    async getScanUsers() {
+      const data = await clientUserQuery(this.filter.workId);
+      this.scanUsers = data;
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        page: this.current - 1,
+        size: this.size,
+      };
+      this.papers = [];
+      const data = await paperPageList(datas);
+      this.papers = data.data.map((paper) => {
+        const title = paper.manual
+          ? `${paper.examNumber} ${paper.studentName}`
+          : paper.examNumber;
+        return {
+          id: paper.id,
+          key: this.$randomCode(),
+          title,
+          imgSrc: paper.imgSrc,
+          thumbSrc: paper.thumbSrc,
+          missing: paper.missing,
+          mark: paper.adminMark,
+          stage: paper.stage,
+          styles: {},
+          deg: 0,
+        };
+      });
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+    },
+    toPage(page) {
+      if (!this.filter.subject || !this.filter.areaCode) {
+        this.$Message.error("请选择科目和考区!");
+        return;
+      }
+      this.confirmPaperType = this.paperType;
+      this.current = page;
+      this.getList();
+    },
+    subjectChange() {
+      this.filter.areaCode = "";
+      this.areas = [];
+      if (!this.filter.subject) return;
+      this.getAreaList();
+    },
+    typeChange() {
+      const typeToField = {
+        0: "missing",
+        1: "isManual",
+        2: "isRelate",
+        7: "sizeAbnormal",
+        8: "isMark",
+      };
+      Object.values(typeToField).forEach((val) => {
+        this.filter[val] = typeToField[this.paperType] === val ? true : null;
+      });
+    },
+    toExportMark() {
+      window.open(
+        this.urlAddAuthor(
+          `${this.GLOBAL.domain}/api/export/paper/${this.filter.workId}/mark`
+        )
+      );
+    },
+    // paper view
+    toReview(index) {
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

+ 26 - 26
src/modules/main/QualityAnalysis.vue

@@ -164,7 +164,7 @@ import {
   subjectList,
   subjectList,
   areaList,
   areaList,
   userGroupList,
   userGroupList,
-  getParamsSet
+  getParamsSet,
 } from "@/api";
 } from "@/api";
 import EchartRender from "@/components/EchartRender";
 import EchartRender from "@/components/EchartRender";
 import QualityAnalysisExport from "./components/QualityAnalysisExport";
 import QualityAnalysisExport from "./components/QualityAnalysisExport";
@@ -181,7 +181,7 @@ export default {
         areaCode: "",
         areaCode: "",
         groupId: "",
         groupId: "",
         startTime: null,
         startTime: null,
-        endTime: null
+        endTime: null,
       },
       },
       searchTime: [],
       searchTime: [],
       levelsPropReportData: null,
       levelsPropReportData: null,
@@ -197,13 +197,13 @@ export default {
       roughLevelEnable: false,
       roughLevelEnable: false,
       levelTypes: {
       levelTypes: {
         ROUGH_LEVEL: "粗分档",
         ROUGH_LEVEL: "粗分档",
-        LEVEL: "细分档"
+        LEVEL: "细分档",
       },
       },
       // export
       // export
       renderExportPage: false,
       renderExportPage: false,
       renderChartData: {},
       renderChartData: {},
       renderPageInfo: {},
       renderPageInfo: {},
-      isDownload: false
+      isDownload: false,
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -228,18 +228,18 @@ export default {
     },
     },
     async getSubjects() {
     async getSubjects() {
       const data = await subjectList(this.filter.workId);
       const data = await subjectList(this.filter.workId);
-      this.subjects = data.filter(item => item.enable);
+      this.subjects = data.filter((item) => item.enable);
     },
     },
     async getAreaList() {
     async getAreaList() {
       const data = await areaList({
       const data = await areaList({
         workId: this.filter.workId,
         workId: this.filter.workId,
-        subject: this.filter.subject
+        subject: this.filter.subject,
       });
       });
-      this.areas = data.map(item => {
+      this.areas = data.map((item) => {
         return {
         return {
           id: item.id,
           id: item.id,
           areaName: item.areaName,
           areaName: item.areaName,
-          areaCode: item.areaCode
+          areaCode: item.areaCode,
         };
         };
       });
       });
 
 
@@ -250,15 +250,15 @@ export default {
     async getGroupList() {
     async getGroupList() {
       let filterData = {
       let filterData = {
         workId: this.filter.workId,
         workId: this.filter.workId,
-        subject: this.filter.subject
+        subject: this.filter.subject,
       };
       };
       if (this.roughLevelEnable) filterData.stage = this.stage;
       if (this.roughLevelEnable) filterData.stage = this.stage;
 
 
       const data = await userGroupList(filterData);
       const data = await userGroupList(filterData);
-      this.groups = data.map(item => {
+      this.groups = data.map((item) => {
         return {
         return {
           id: item.groupId,
           id: item.groupId,
-          name: item.groupName
+          name: item.groupName,
         };
         };
       });
       });
 
 
@@ -280,32 +280,32 @@ export default {
       if (!datas.length) {
       if (!datas.length) {
         return { names: [], dataList: [] };
         return { names: [], dataList: [] };
       }
       }
-      var names = datas[0].data.map(function(item) {
+      var names = datas[0].data.map(function (item) {
         return item.markerName;
         return item.markerName;
       });
       });
-      var dataList = datas.map(function(item) {
+      var dataList = datas.map(function (item) {
         return {
         return {
           name: item.name,
           name: item.name,
-          data: item.data.map(function(elem) {
+          data: item.data.map(function (elem) {
             return elem.prop;
             return elem.prop;
-          })
+          }),
         };
         };
       });
       });
       return {
       return {
         names: names,
         names: names,
-        dataList: dataList
+        dataList: dataList,
       };
       };
     },
     },
     parseReportData(datas) {
     parseReportData(datas) {
       var names = [];
       var names = [];
       var dataList = [];
       var dataList = [];
-      datas.map(function(item, index) {
+      datas.map(function (item, index) {
         names[index] = item.userName;
         names[index] = item.userName;
         dataList[index] = item.sumCount;
         dataList[index] = item.sumCount;
       });
       });
       return {
       return {
         names: names,
         names: names,
-        dataList: dataList
+        dataList: dataList,
       };
       };
     },
     },
     async toSearch() {
     async toSearch() {
@@ -315,7 +315,7 @@ export default {
       this.callbackReportData = null;
       this.callbackReportData = null;
       this.selfCheckData = null;
       this.selfCheckData = null;
       let filterData = {
       let filterData = {
-        ...this.filter
+        ...this.filter,
       };
       };
       if (this.roughLevelEnable) filterData.stage = this.stage;
       if (this.roughLevelEnable) filterData.stage = this.stage;
       const datas = filterObjNull(filterData);
       const datas = filterObjNull(filterData);
@@ -324,7 +324,7 @@ export default {
         deviationReport(datas),
         deviationReport(datas),
         distanceReport(datas),
         distanceReport(datas),
         callbackReport(datas),
         callbackReport(datas),
-        selfCheckReport(datas)
+        selfCheckReport(datas),
       ];
       ];
       const data = await Promise.all(requests);
       const data = await Promise.all(requests);
 
 
@@ -349,23 +349,23 @@ export default {
       if (this.isDownload) return;
       if (this.isDownload) return;
       this.isDownload = true;
       this.isDownload = true;
       const curSubject = this.subjects.find(
       const curSubject = this.subjects.find(
-        item => item.subject === this.filter.subject
+        (item) => item.subject === this.filter.subject
       );
       );
       const curArea = this.areas.find(
       const curArea = this.areas.find(
-        item => item.areaCode === this.filter.areaCode
+        (item) => item.areaCode === this.filter.areaCode
       );
       );
       this.renderPageInfo = {
       this.renderPageInfo = {
         subjectName: curSubject.name,
         subjectName: curSubject.name,
         areaName: curArea.areaName,
         areaName: curArea.areaName,
         startTime: this.filter.startTime || "无",
         startTime: this.filter.startTime || "无",
-        endTime: this.filter.endTime || "无"
+        endTime: this.filter.endTime || "无",
       };
       };
       this.renderChartData = {
       this.renderChartData = {
         levelsPropReportData: this.levelsPropReportData,
         levelsPropReportData: this.levelsPropReportData,
         deviationReportData: this.deviationReportData,
         deviationReportData: this.deviationReportData,
         distanceReportData: this.distanceReportData,
         distanceReportData: this.distanceReportData,
         callbackReportData: this.callbackReportData,
         callbackReportData: this.callbackReportData,
-        selfCheckData: this.selfCheckData
+        selfCheckData: this.selfCheckData,
       };
       };
       this.renderExportPage = true;
       this.renderExportPage = true;
     },
     },
@@ -377,7 +377,7 @@ export default {
       }
       }
       this.renderExportPage = false;
       this.renderExportPage = false;
       this.isDownload = false;
       this.isDownload = false;
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 471 - 471
src/modules/main/StudentManage.vue

@@ -1,471 +1,471 @@
-<template>
-  <div class="students ">
-    <div class="part-box-head">
-      <div class="part-box-head-left">
-        <Button
-          icon="upload icon"
-          shape="circle"
-          @click="$refs.ExportStudent.open()"
-          >导入考生信息</Button
-        >
-        <!-- <Button
-          icon="upload icon"
-          shape="circle"
-          @click="$refs.ExportRelate.open()"
-          >导入关联信息</Button
-        > -->
-      </div>
-      <div class="part-box-head-right">
-        <Button
-          type="success"
-          icon="recode-white icon"
-          shape="circle"
-          @click="toAdd"
-          >添加考生</Button
-        >
-        <Button
-          shape="circle"
-          type="success"
-          icon="upload-white icon"
-          @click="toExport"
-          >导出表格</Button
-        >
-      </div>
-    </div>
-    <div class="part-box part-box-filter">
-      <Form ref="FilterForm" label-position="left" inline>
-        <FormItem>
-          <Select
-            v-model="filter.areaCode"
-            @on-change="areaChange"
-            placeholder="考区"
-            clearable
-          >
-            <Option
-              v-for="area in cascadeList"
-              :key="area.areaCode"
-              :value="area.areaCode"
-              :label="area.areaName"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="filter.school"
-            @on-change="schoolChange"
-            placeholder="学校"
-            filterable
-            clearable
-          >
-            <Option
-              v-for="(item, index) in schools"
-              :key="index"
-              :value="item.school"
-              :label="item.school"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.examRoom" placeholder="考场" clearable>
-            <Option
-              v-for="(room, index) in rooms"
-              :key="index"
-              :value="room"
-              :label="room"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model="filter.startNumber"
-            type="text"
-            placeholder="输入开始编号"
-            clearable
-          />
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model="filter.endNumber"
-            type="text"
-            placeholder="输入结束编号"
-            clearable
-          />
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model.trim="filter.studentName"
-            placeholder="输入姓名"
-            clearable
-          ></Input>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.isAbsent" placeholder="是否缺考" clearable>
-            <Option
-              v-for="(val, key) in BOOLEAN_TYPE"
-              :key="key"
-              :value="key * 1"
-              >{{ val }}</Option
-            >
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.upload" placeholder="是否上传" clearable>
-            <Option
-              v-for="(val, key) in PAPER_UPLOAD_TYPE"
-              :key="key"
-              :value="key * 1"
-              >{{ val }}</Option
-            >
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.subject" placeholder="科目" clearable>
-            <Option
-              v-for="item in subjects"
-              :key="item.subject"
-              :value="item.subject"
-              :label="item.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Button
-            size="small"
-            class="btn-form-search"
-            type="primary"
-            @click="toPage(1)"
-            >查询</Button
-          >
-        </FormItem>
-      </Form>
-    </div>
-    <Table
-      ref="TableList"
-      :columns="columns"
-      :data="students"
-      disabled-hover
-      border
-    ></Table>
-
-    <div class="part-page">
-      <Page
-        :current="current"
-        :total="total"
-        :page-size="size"
-        show-total
-        show-elevator
-        @on-change="toPage"
-      ></Page>
-    </div>
-
-    <!-- import student  -->
-    <import-file
-      title="导入考生信息"
-      :upload-url="uploadStudentUrl"
-      :upload-data="uploadData"
-      :download-url="downloadStudentTemplateUrl"
-      :download-filename="downloadStudentTemplateFilename"
-      :headers="headers"
-      :format="['xls', 'xlsx']"
-      @upload-success="uploadSuccess"
-      ref="ExportStudent"
-    >
-    </import-file>
-    <!-- import-relate -->
-    <import-file
-      title="导入关联信息"
-      :upload-url="uploadRelateUrl"
-      :upload-data="uploadData"
-      :download-url="downloadRelateTemplateUrl"
-      :download-filename="downloadRelateTemplateFilename"
-      :headers="headers"
-      :format="['xls', 'xlsx']"
-      ref="ExportRelate"
-    >
-    </import-file>
-    <!-- modify-student -->
-    <modify-student
-      :cascade-list="cascadeList"
-      :instance="curStudent"
-      @modified="getList"
-      @on-close="getAreaList"
-      ref="ModifyStudent"
-    ></modify-student>
-  </div>
-</template>
-
-<script>
-import {
-  subjectList,
-  studentPageList,
-  deleteStudent,
-  areaSchoolRoomCascadeList
-} from "@/api";
-import ImportFile from "@/components/common/ImportFile";
-import ModifyStudent from "./components/ModifyStudent";
-import { BOOLEAN_TYPE, PAPER_UPLOAD_TYPE } from "@/constants/enumerate";
-import qs from "qs";
-
-export default {
-  name: "students",
-  components: { ImportFile, ModifyStudent },
-  data() {
-    return {
-      filter: {
-        workId: this.$route.params.workId,
-        subject: null,
-        areaCode: null,
-        school: "",
-        examRoom: "",
-        startNumber: null,
-        endNumber: null,
-        studentName: "",
-        upload: null,
-        isAbsent: null
-      },
-      current: 1,
-      size: this.GLOBAL.pageSize,
-      total: 0,
-      students: [],
-      curStudent: {},
-      subjects: [],
-      cascadeList: [],
-      schools: [],
-      rooms: [],
-      BOOLEAN_TYPE,
-      PAPER_UPLOAD_TYPE,
-      columns: [
-        {
-          type: "index",
-          title: "序号",
-          width: 80,
-          align: "center",
-          indexMethod: row => {
-            return (this.current - 1) * this.size + row._index + 1;
-          }
-        },
-        {
-          title: "姓名",
-          key: "name",
-          width: 100
-        },
-        {
-          title: "考号",
-          key: "examNumber",
-          minWidth: 120
-        },
-        // {
-        //   title: "关联考号",
-        //   key: "relateExamNumber",
-        //   minWidth: 120
-        // },
-        {
-          title: "考区",
-          key: "areaName",
-          minWidth: 120
-        },
-        {
-          title: "学校",
-          key: "school",
-          minWidth: 150
-        },
-        {
-          title: "考场",
-          key: "examRoom",
-          minWidth: 100
-        },
-        {
-          title: "操作",
-          key: "action",
-          width: 100,
-          align: "center",
-          className: "table-action",
-          render: (h, param) => {
-            let actions = [];
-
-            if (param.row.canEdit) {
-              actions.push({
-                icon: "md-create",
-                attrs: {
-                  title: "编辑"
-                },
-                action: () => {
-                  this.toEdit(param.row);
-                }
-              });
-            }
-            if (param.row.canDelete) {
-              actions.push({
-                icon: "md-trash",
-                classes: ["icon-danger"],
-                attrs: {
-                  title: "删除"
-                },
-                action: () => {
-                  this.toDelete(param.row);
-                }
-              });
-            }
-
-            return h("div", this.$tableIconAction(h, actions));
-          }
-        }
-      ],
-      // upload
-      headers: {
-        Authorization: this.$ls.get("user", { token: "" }).token,
-        workId: this.$route.params.workId,
-        userId: this.$ls.get("user", { id: "" }).id
-      },
-      uploadData: {
-        workId: this.$route.params.workId
-      },
-      uploadStudentUrl: this.GLOBAL.domain + "/api/import/students",
-      downloadStudentTemplateUrl: "/templates/考生信息表-模板.xlsx",
-      downloadStudentTemplateFilename: "考生信息表-模板.xlsx",
-      uploadRelateUrl: "/api/import/students/relateStudent",
-      downloadRelateTemplateUrl: "/templates/关联考生信息表-模板.xlsx",
-      downloadRelateTemplateFilename: "关联考生信息表-模板.xlsx"
-    };
-  },
-  mounted() {
-    this.iniData();
-  },
-  methods: {
-    async iniData() {
-      await this.getSubjects();
-      this.getAreaList();
-      this.getList();
-    },
-    async getList() {
-      const datas = {
-        ...this.filter,
-        page: this.current - 1,
-        size: this.size
-      };
-      // if (
-      //   ((datas.upload || datas.upload === 0) && !datas.subject) ||
-      //   (!datas.upload && datas.upload !== 0 && datas.subject)
-      // ) {
-      //   this.$Message.error("上传状态和科目必须同时选择!");
-      //   return;
-      // }
-      // if (datas.subject === "ONE") datas.subject = null;
-      const data = await studentPageList(datas);
-      this.students = data.data.map(student => {
-        student.uploadStatus.split(",").map(status => {
-          const [subjectCode, subjectUploadStatus] = status.split(":");
-          student[subjectCode] = subjectUploadStatus * 1;
-        });
-        student.canEdit = !student.uploadStatus.includes("1");
-        student.canDelete = !student.uploadStatus.includes("1");
-        student.uploadStatus.split(",").map(status => {
-          const [subject, hasScan] = status.split(":");
-          student[subject] = hasScan;
-        });
-        student.workId = this.filter.workId;
-        student.relateExamNumber =
-          student.relateExamNumber === student.examNumber
-            ? "--"
-            : student.relateExamNumber;
-        return student;
-      });
-      this.total = data.totalCount;
-    },
-    toPage(page) {
-      this.current = page;
-      this.getList();
-    },
-    async getAreaList() {
-      this.cascadeList = await areaSchoolRoomCascadeList(this.filter.workId);
-    },
-    async getSubjects() {
-      const data = await subjectList(this.filter.workId);
-      this.subjects = data.filter(item => item.enable);
-      this.subjects.map(item => {
-        const column = {
-          title: item.name,
-          key: item.subject,
-          minWidth: 80,
-          render: (h, param) => {
-            return h("Icon", {
-              class: [{ "color-success": param.row[item.subject] == "1" }],
-              props: {
-                size: 18,
-                type:
-                  param.row[item.subject] == "1"
-                    ? "ios-checkmark-circle"
-                    : "ios-radio-button-off"
-              }
-            });
-          }
-        };
-        this.columns.splice(this.columns.length - 1, 0, column);
-      });
-      this.subjects.unshift({
-        subject: "ONE",
-        name: "查漏"
-      });
-    },
-    areaChange() {
-      const curArea = this.cascadeList.find(
-        item => item.areaCode === this.filter.areaCode
-      );
-      this.schools = curArea ? curArea.schools : [];
-      this.rooms = [];
-      this.filter.school = null;
-      this.filter.examRoom = null;
-      if (curArea.schools.length === 1) {
-        this.filter.school = curArea.schools[0].school;
-        this.schoolChange();
-      }
-    },
-    schoolChange() {
-      const curSchool = this.schools.find(
-        item => item.school === this.filter.school
-      );
-      this.rooms = curSchool ? curSchool.rooms : [];
-      this.filter.examRoom = null;
-    },
-    uploadSuccess() {
-      this.getList();
-      this.getAreaList();
-      this.$Notice.success({
-        title: "导入提示",
-        desc: "考生信息导入成功!",
-        duration: 0
-      });
-    },
-    toAdd() {
-      this.curStudent = { workId: this.filter.workId };
-      this.$refs.ModifyStudent.open();
-    },
-    toEdit(row) {
-      this.curStudent = row;
-      this.$refs.ModifyStudent.open();
-    },
-    toDelete(row) {
-      this.$Modal.confirm({
-        width: 340,
-        content: "确定要删除该考生吗?",
-        onOk: () => {
-          this.toDel(row.id);
-        }
-      });
-    },
-    async toDel(id) {
-      await deleteStudent(id);
-      this.$Message.success("删除成功!");
-      this.deletePageLastItem();
-    },
-    toExport() {
-      const sqDatas = qs.stringify(this.filter, {
-        arrayFormat: "brackets"
-      });
-      window.open(
-        this.urlAddAuthor(`${this.GLOBAL.domain}/api/export/student?${sqDatas}`)
-      );
-    }
-  }
-};
-</script>
+<template>
+  <div class="students">
+    <div class="part-box-head">
+      <div class="part-box-head-left">
+        <Button
+          icon="upload icon"
+          shape="circle"
+          @click="$refs.ExportStudent.open()"
+          >导入考生信息</Button
+        >
+        <!-- <Button
+          icon="upload icon"
+          shape="circle"
+          @click="$refs.ExportRelate.open()"
+          >导入关联信息</Button
+        > -->
+      </div>
+      <div class="part-box-head-right">
+        <Button
+          type="success"
+          icon="recode-white icon"
+          shape="circle"
+          @click="toAdd"
+          >添加考生</Button
+        >
+        <Button
+          shape="circle"
+          type="success"
+          icon="upload-white icon"
+          @click="toExport"
+          >导出表格</Button
+        >
+      </div>
+    </div>
+    <div class="part-box part-box-filter">
+      <Form ref="FilterForm" label-position="left" inline>
+        <FormItem>
+          <Select
+            v-model="filter.areaCode"
+            @on-change="areaChange"
+            placeholder="考区"
+            clearable
+          >
+            <Option
+              v-for="area in cascadeList"
+              :key="area.areaCode"
+              :value="area.areaCode"
+              :label="area.areaName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="filter.school"
+            @on-change="schoolChange"
+            placeholder="学校"
+            filterable
+            clearable
+          >
+            <Option
+              v-for="(item, index) in schools"
+              :key="index"
+              :value="item.school"
+              :label="item.school"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.examRoom" placeholder="考场" clearable>
+            <Option
+              v-for="(room, index) in rooms"
+              :key="index"
+              :value="room"
+              :label="room"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model="filter.startNumber"
+            type="text"
+            placeholder="输入开始编号"
+            clearable
+          />
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model="filter.endNumber"
+            type="text"
+            placeholder="输入结束编号"
+            clearable
+          />
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model.trim="filter.studentName"
+            placeholder="输入姓名"
+            clearable
+          ></Input>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.isAbsent" placeholder="是否缺考" clearable>
+            <Option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key * 1"
+              >{{ val }}</Option
+            >
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.upload" placeholder="是否上传" clearable>
+            <Option
+              v-for="(val, key) in PAPER_UPLOAD_TYPE"
+              :key="key"
+              :value="key * 1"
+              >{{ val }}</Option
+            >
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.subject" placeholder="科目" clearable>
+            <Option
+              v-for="item in subjects"
+              :key="item.subject"
+              :value="item.subject"
+              :label="item.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Button
+            size="small"
+            class="btn-form-search"
+            type="primary"
+            @click="toPage(1)"
+            >查询</Button
+          >
+        </FormItem>
+      </Form>
+    </div>
+    <Table
+      ref="TableList"
+      :columns="columns"
+      :data="students"
+      disabled-hover
+      border
+    ></Table>
+
+    <div class="part-page">
+      <Page
+        :current="current"
+        :total="total"
+        :page-size="size"
+        show-total
+        show-elevator
+        @on-change="toPage"
+      ></Page>
+    </div>
+
+    <!-- import student  -->
+    <import-file
+      title="导入考生信息"
+      :upload-url="uploadStudentUrl"
+      :upload-data="uploadData"
+      :download-url="downloadStudentTemplateUrl"
+      :download-filename="downloadStudentTemplateFilename"
+      :headers="headers"
+      :format="['xls', 'xlsx']"
+      @upload-success="uploadSuccess"
+      ref="ExportStudent"
+    >
+    </import-file>
+    <!-- import-relate -->
+    <import-file
+      title="导入关联信息"
+      :upload-url="uploadRelateUrl"
+      :upload-data="uploadData"
+      :download-url="downloadRelateTemplateUrl"
+      :download-filename="downloadRelateTemplateFilename"
+      :headers="headers"
+      :format="['xls', 'xlsx']"
+      ref="ExportRelate"
+    >
+    </import-file>
+    <!-- modify-student -->
+    <modify-student
+      :cascade-list="cascadeList"
+      :instance="curStudent"
+      @modified="getList"
+      @on-close="getAreaList"
+      ref="ModifyStudent"
+    ></modify-student>
+  </div>
+</template>
+
+<script>
+import {
+  subjectList,
+  studentPageList,
+  deleteStudent,
+  areaSchoolRoomCascadeList,
+} from "@/api";
+import ImportFile from "@/components/common/ImportFile";
+import ModifyStudent from "./components/ModifyStudent";
+import { BOOLEAN_TYPE, PAPER_UPLOAD_TYPE } from "@/constants/enumerate";
+import qs from "qs";
+
+export default {
+  name: "students",
+  components: { ImportFile, ModifyStudent },
+  data() {
+    return {
+      filter: {
+        workId: this.$route.params.workId,
+        subject: null,
+        areaCode: null,
+        school: "",
+        examRoom: "",
+        startNumber: null,
+        endNumber: null,
+        studentName: "",
+        upload: null,
+        isAbsent: null,
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      students: [],
+      curStudent: {},
+      subjects: [],
+      cascadeList: [],
+      schools: [],
+      rooms: [],
+      BOOLEAN_TYPE,
+      PAPER_UPLOAD_TYPE,
+      columns: [
+        {
+          type: "index",
+          title: "序号",
+          width: 80,
+          align: "center",
+          indexMethod: (row) => {
+            return (this.current - 1) * this.size + row._index + 1;
+          },
+        },
+        {
+          title: "姓名",
+          key: "name",
+          width: 100,
+        },
+        {
+          title: "考号",
+          key: "examNumber",
+          minWidth: 120,
+        },
+        // {
+        //   title: "关联考号",
+        //   key: "relateExamNumber",
+        //   minWidth: 120
+        // },
+        {
+          title: "考区",
+          key: "areaName",
+          minWidth: 120,
+        },
+        {
+          title: "学校",
+          key: "school",
+          minWidth: 150,
+        },
+        {
+          title: "考场",
+          key: "examRoom",
+          minWidth: 100,
+        },
+        {
+          title: "操作",
+          key: "action",
+          width: 100,
+          align: "center",
+          className: "table-action",
+          render: (h, param) => {
+            let actions = [];
+
+            if (param.row.canEdit) {
+              actions.push({
+                icon: "md-create",
+                attrs: {
+                  title: "编辑",
+                },
+                action: () => {
+                  this.toEdit(param.row);
+                },
+              });
+            }
+            if (param.row.canDelete) {
+              actions.push({
+                icon: "md-trash",
+                classes: ["icon-danger"],
+                attrs: {
+                  title: "删除",
+                },
+                action: () => {
+                  this.toDelete(param.row);
+                },
+              });
+            }
+
+            return h("div", this.$tableIconAction(h, actions));
+          },
+        },
+      ],
+      // upload
+      headers: {
+        Authorization: this.$ls.get("user", { token: "" }).token,
+        workId: this.$route.params.workId,
+        userId: this.$ls.get("user", { id: "" }).id,
+      },
+      uploadData: {
+        workId: this.$route.params.workId,
+      },
+      uploadStudentUrl: this.GLOBAL.domain + "/api/import/students",
+      downloadStudentTemplateUrl: "/templates/考生信息表-模板.xlsx",
+      downloadStudentTemplateFilename: "考生信息表-模板.xlsx",
+      uploadRelateUrl: "/api/import/students/relateStudent",
+      downloadRelateTemplateUrl: "/templates/关联考生信息表-模板.xlsx",
+      downloadRelateTemplateFilename: "关联考生信息表-模板.xlsx",
+    };
+  },
+  mounted() {
+    this.iniData();
+  },
+  methods: {
+    async iniData() {
+      await this.getSubjects();
+      this.getAreaList();
+      this.getList();
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        page: this.current - 1,
+        size: this.size,
+      };
+      // if (
+      //   ((datas.upload || datas.upload === 0) && !datas.subject) ||
+      //   (!datas.upload && datas.upload !== 0 && datas.subject)
+      // ) {
+      //   this.$Message.error("上传状态和科目必须同时选择!");
+      //   return;
+      // }
+      // if (datas.subject === "ONE") datas.subject = null;
+      const data = await studentPageList(datas);
+      this.students = data.data.map((student) => {
+        student.uploadStatus.split(",").map((status) => {
+          const [subjectCode, subjectUploadStatus] = status.split(":");
+          student[subjectCode] = subjectUploadStatus * 1;
+        });
+        student.canEdit = !student.uploadStatus.includes("1");
+        student.canDelete = !student.uploadStatus.includes("1");
+        student.uploadStatus.split(",").map((status) => {
+          const [subject, hasScan] = status.split(":");
+          student[subject] = hasScan;
+        });
+        student.workId = this.filter.workId;
+        student.relateExamNumber =
+          student.relateExamNumber === student.examNumber
+            ? "--"
+            : student.relateExamNumber;
+        return student;
+      });
+      this.total = data.totalCount;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    async getAreaList() {
+      this.cascadeList = await areaSchoolRoomCascadeList(this.filter.workId);
+    },
+    async getSubjects() {
+      const data = await subjectList(this.filter.workId);
+      this.subjects = data.filter((item) => item.enable);
+      this.subjects.map((item) => {
+        const column = {
+          title: item.name,
+          key: item.subject,
+          minWidth: 80,
+          render: (h, param) => {
+            return h("Icon", {
+              class: [{ "color-success": param.row[item.subject] == "1" }],
+              props: {
+                size: 18,
+                type:
+                  param.row[item.subject] == "1"
+                    ? "ios-checkmark-circle"
+                    : "ios-radio-button-off",
+              },
+            });
+          },
+        };
+        this.columns.splice(this.columns.length - 1, 0, column);
+      });
+      this.subjects.unshift({
+        subject: "ONE",
+        name: "查漏",
+      });
+    },
+    areaChange() {
+      const curArea = this.cascadeList.find(
+        (item) => item.areaCode === this.filter.areaCode
+      );
+      this.schools = curArea ? curArea.schools : [];
+      this.rooms = [];
+      this.filter.school = null;
+      this.filter.examRoom = null;
+      if (curArea.schools.length === 1) {
+        this.filter.school = curArea.schools[0].school;
+        this.schoolChange();
+      }
+    },
+    schoolChange() {
+      const curSchool = this.schools.find(
+        (item) => item.school === this.filter.school
+      );
+      this.rooms = curSchool ? curSchool.rooms : [];
+      this.filter.examRoom = null;
+    },
+    uploadSuccess() {
+      this.getList();
+      this.getAreaList();
+      this.$Notice.success({
+        title: "导入提示",
+        desc: "考生信息导入成功!",
+        duration: 0,
+      });
+    },
+    toAdd() {
+      this.curStudent = { workId: this.filter.workId };
+      this.$refs.ModifyStudent.open();
+    },
+    toEdit(row) {
+      this.curStudent = row;
+      this.$refs.ModifyStudent.open();
+    },
+    toDelete(row) {
+      this.$Modal.confirm({
+        width: 340,
+        content: "确定要删除该考生吗?",
+        onOk: () => {
+          this.toDel(row.id);
+        },
+      });
+    },
+    async toDel(id) {
+      await deleteStudent(id);
+      this.$Message.success("删除成功!");
+      this.deletePageLastItem();
+    },
+    toExport() {
+      const sqDatas = qs.stringify(this.filter, {
+        arrayFormat: "brackets",
+      });
+      window.open(
+        this.urlAddAuthor(`${this.GLOBAL.domain}/api/export/student?${sqDatas}`)
+      );
+    },
+  },
+};
+</script>

+ 330 - 330
src/modules/main/StudentScore.vue

@@ -1,330 +1,330 @@
-<template>
-  <div class="student-score">
-    <div class="part-box part-box-filter">
-      <Form ref="FilterForm" label-position="left" inline>
-        <FormItem v-if="IS_INSPECTION">
-          <Select
-            v-model="filter.workId"
-            @on-change="workChange"
-            placeholder="工作文件夹"
-            style="width: 150px"
-          >
-            <Option
-              v-for="(work, windex) in works"
-              :key="windex"
-              :value="work.id"
-              :label="work.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="filter.subject"
-            @on-change="subjecChange"
-            placeholder="科目"
-            style="width: 100px;"
-            clearable
-          >
-            <Option
-              v-for="(item, index) in subjects"
-              :key="index"
-              :value="item.subject"
-              :label="item.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem v-if="IS_INSPECTION">
-          <Select v-model="filter.questionId" placeholder="考区">
-            <Option
-              v-for="area in areas"
-              :key="area.id"
-              :value="area.id"
-              :label="area.areaName"
-            ></Option>
-          </Select>
-        </FormItem>
-
-        <FormItem>
-          <Select
-            v-model="filter.type"
-            placeholder="号码类型"
-            style="width: 100px"
-          >
-            <Option
-              v-for="(val, key) in CODE_TYPE"
-              :key="key"
-              :value="key"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model.trim="filter.number"
-            placeholder="输入号码"
-            clearable
-          ></Input>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model.trim="filter.studentName"
-            placeholder="输入姓名"
-            clearable
-          ></Input>
-        </FormItem>
-        <FormItem>
-          <Button
-            class="btn-form-search"
-            size="small"
-            type="primary"
-            @click="toSearch"
-            >查询</Button
-          >
-        </FormItem>
-      </Form>
-    </div>
-
-    <div class="student-score-content" v-if="curStudent.name">
-      <div class="score-content-head">
-        <h1 class="score-content-title">{{ curStudent.name }}</h1>
-        <p class="score-content-info">
-          <span>考号:</span><span>{{ curStudent.examNumber }}</span>
-        </p>
-        <p class="score-content-tscore">
-          <span>总分:</span><span>{{ curStudent.sumScore }}</span>
-        </p>
-      </div>
-      <div class="score-content-body">
-        <image-action-list
-          :data="papers"
-          :column-number="papers.length"
-          @on-review="toReview"
-          ref="ImageActionList"
-        ></image-action-list>
-
-        <table :class="['table', `table-column-${papers.length}`]">
-          <tr>
-            <td v-for="(paper, sindex) in papers" :key="sindex">
-              <div class="score-content-task">
-                <div class="task-list">
-                  <div class="task-item">
-                    <div class="task-item-label">试卷密号:</div>
-                    <div class="task-item-content">
-                      {{ paper.secretNumber }}
-                    </div>
-                  </div>
-                  <div class="task-item">
-                    <div class="task-item-label">任务密号:</div>
-                    <div class="task-item-content">
-                      <p v-for="task in paper.taskList" :key="task.id">
-                        {{ task.secretNumber }}({{ task.markerName }})
-                      </p>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </td>
-          </tr>
-          <tr>
-            <td
-              class="color-dark"
-              v-for="(paper, sindex) in papers"
-              :key="sindex"
-            >
-              {{ paper.level || "空" }}
-            </td>
-          </tr>
-          <tr>
-            <td
-              class="color-error"
-              v-for="(paper, sindex) in papers"
-              :key="sindex"
-            >
-              {{ paper.score ? paper.score + "分" : "空" }}
-            </td>
-          </tr>
-        </table>
-      </div>
-    </div>
-
-    <div class="part-page" v-if="total > size">
-      <Page
-        :current="current"
-        :total="total"
-        :page-size="size"
-        show-total
-        show-elevator
-        @on-change="toPage"
-      ></Page>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import { studentScoreList, workList, subjectList, areaList } from "@/api";
-import { CODE_TYPE } from "@/constants/enumerate";
-import ImageActionList from "./components/ImageActionList";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-
-export default {
-  name: "student-score",
-  components: { ImageActionList, SimpleImagePreview },
-  data() {
-    return {
-      filter: {
-        workId: this.$route.params && this.$route.params.workId,
-        subject: "",
-        questionId: "",
-        type: "examNumber",
-        number: "",
-        studentName: ""
-      },
-      CODE_TYPE,
-      IS_INSPECTION: false,
-      works: [],
-      subjects: [],
-      areas: [],
-      current: 1,
-      total: 0,
-      size: 1,
-      curStudent: { name: "" },
-      students: [],
-      // image preview
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0
-    };
-  },
-  mounted() {
-    this.initData();
-  },
-  methods: {
-    async initData() {
-      this.IS_INSPECTION =
-        this.$ls.get("user", { role: "" }).role === "INSPECTION";
-      if (this.IS_INSPECTION) {
-        await this.getWorkList();
-        this.filter.workId = this.works[0].id;
-        this.workChange();
-        this.getAreaList();
-      } else {
-        await this.getSubjects();
-        // this.filter.subject = this.subjects[0].subject;
-        if (this.$route.query && this.$route.query.examNumber) {
-          this.filter.number = this.$route.query.examNumber;
-          this.toSearch();
-        }
-      }
-    },
-    async getWorkList() {
-      this.works = await workList();
-    },
-    async getSubjects() {
-      const data = await subjectList(this.filter.workId);
-      this.subjects = data.filter(item => item.enable);
-    },
-    async getAreaList() {
-      const data = await areaList({
-        workId: this.filter.workId,
-        subject: this.filter.subject
-      });
-      this.areas = data.map(item => {
-        return {
-          id: item.id,
-          areaName: item.areaName,
-          areaCode: item.areaCode
-        };
-      });
-    },
-    async toSearch() {
-      if (!this.filter.number && !this.filter.studentName) {
-        this.$Message.error("号码和姓名必须填写一个");
-        return;
-      }
-      const data = await studentScoreList(this.filter);
-      if (!data.length) {
-        this.$Message.error("无此考生");
-        return;
-      }
-      this.students = data;
-      this.total = this.students.length;
-      this.toPage(1);
-    },
-    toPage(page) {
-      if (!this.students[page - 1]) return;
-      this.current = page;
-      this.curStudent = this.students[page - 1];
-      this.papers = this.curStudent.papers.map(item => {
-        let nitem = { ...item };
-        nitem.key = this.$randomCode();
-        nitem.imgSrc = item.sheetSrc;
-        nitem.thumbSrc = item.sheetSrc;
-        const fields = ["taskScores", "taskLevels"];
-        const validField = fields.find(
-          field => item[field] && item[field].length
-        );
-        nitem.taskList = validField ? item[validField] : [];
-        return nitem;
-      });
-    },
-    workChange() {
-      this.filter.subject = null;
-      this.filter.questionId = null;
-      const curWork = this.works.find(item => item.id === this.filter.workId);
-      this.subjects = curWork.subjects;
-      this.filter.subject = this.subjects[0].subject;
-    },
-    subjecChange() {
-      if (this.IS_INSPECTION) {
-        this.filter.questionId = null;
-        this.getAreaList();
-      }
-    },
-    // paper view
-    toReview(index) {
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        this.$Message.warning("当前已经是第一条数据了");
-        return;
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        this.$Message.warning("当前已经是最后一条数据了");
-        return;
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="student-score">
+    <div class="part-box part-box-filter">
+      <Form ref="FilterForm" label-position="left" inline>
+        <FormItem v-if="IS_INSPECTION">
+          <Select
+            v-model="filter.workId"
+            @on-change="workChange"
+            placeholder="工作文件夹"
+            style="width: 150px"
+          >
+            <Option
+              v-for="(work, windex) in works"
+              :key="windex"
+              :value="work.id"
+              :label="work.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="filter.subject"
+            @on-change="subjecChange"
+            placeholder="科目"
+            style="width: 100px"
+            clearable
+          >
+            <Option
+              v-for="(item, index) in subjects"
+              :key="index"
+              :value="item.subject"
+              :label="item.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem v-if="IS_INSPECTION">
+          <Select v-model="filter.questionId" placeholder="考区">
+            <Option
+              v-for="area in areas"
+              :key="area.id"
+              :value="area.id"
+              :label="area.areaName"
+            ></Option>
+          </Select>
+        </FormItem>
+
+        <FormItem>
+          <Select
+            v-model="filter.type"
+            placeholder="号码类型"
+            style="width: 100px"
+          >
+            <Option
+              v-for="(val, key) in CODE_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model.trim="filter.number"
+            placeholder="输入号码"
+            clearable
+          ></Input>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model.trim="filter.studentName"
+            placeholder="输入姓名"
+            clearable
+          ></Input>
+        </FormItem>
+        <FormItem>
+          <Button
+            class="btn-form-search"
+            size="small"
+            type="primary"
+            @click="toSearch"
+            >查询</Button
+          >
+        </FormItem>
+      </Form>
+    </div>
+
+    <div class="student-score-content" v-if="curStudent.name">
+      <div class="score-content-head">
+        <h1 class="score-content-title">{{ curStudent.name }}</h1>
+        <p class="score-content-info">
+          <span>考号:</span><span>{{ curStudent.examNumber }}</span>
+        </p>
+        <p class="score-content-tscore">
+          <span>总分:</span><span>{{ curStudent.sumScore }}</span>
+        </p>
+      </div>
+      <div class="score-content-body">
+        <image-action-list
+          :data="papers"
+          :column-number="papers.length"
+          @on-review="toReview"
+          ref="ImageActionList"
+        ></image-action-list>
+
+        <table :class="['table', `table-column-${papers.length}`]">
+          <tr>
+            <td v-for="(paper, sindex) in papers" :key="sindex">
+              <div class="score-content-task">
+                <div class="task-list">
+                  <div class="task-item">
+                    <div class="task-item-label">试卷密号:</div>
+                    <div class="task-item-content">
+                      {{ paper.secretNumber }}
+                    </div>
+                  </div>
+                  <div class="task-item">
+                    <div class="task-item-label">任务密号:</div>
+                    <div class="task-item-content">
+                      <p v-for="task in paper.taskList" :key="task.id">
+                        {{ task.secretNumber }}({{ task.markerName }})
+                      </p>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <td
+              class="color-dark"
+              v-for="(paper, sindex) in papers"
+              :key="sindex"
+            >
+              {{ paper.level || "空" }}
+            </td>
+          </tr>
+          <tr>
+            <td
+              class="color-error"
+              v-for="(paper, sindex) in papers"
+              :key="sindex"
+            >
+              {{ paper.score ? paper.score + "分" : "空" }}
+            </td>
+          </tr>
+        </table>
+      </div>
+    </div>
+
+    <div class="part-page" v-if="total > size">
+      <Page
+        :current="current"
+        :total="total"
+        :page-size="size"
+        show-total
+        show-elevator
+        @on-change="toPage"
+      ></Page>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import { studentScoreList, workList, subjectList, areaList } from "@/api";
+import { CODE_TYPE } from "@/constants/enumerate";
+import ImageActionList from "./components/ImageActionList";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "student-score",
+  components: { ImageActionList, SimpleImagePreview },
+  data() {
+    return {
+      filter: {
+        workId: this.$route.params && this.$route.params.workId,
+        subject: "",
+        questionId: "",
+        type: "examNumber",
+        number: "",
+        studentName: "",
+      },
+      CODE_TYPE,
+      IS_INSPECTION: false,
+      works: [],
+      subjects: [],
+      areas: [],
+      current: 1,
+      total: 0,
+      size: 1,
+      curStudent: { name: "" },
+      students: [],
+      // image preview
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+    };
+  },
+  mounted() {
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      this.IS_INSPECTION =
+        this.$ls.get("user", { role: "" }).role === "INSPECTION";
+      if (this.IS_INSPECTION) {
+        await this.getWorkList();
+        this.filter.workId = this.works[0].id;
+        this.workChange();
+        this.getAreaList();
+      } else {
+        await this.getSubjects();
+        // this.filter.subject = this.subjects[0].subject;
+        if (this.$route.query && this.$route.query.examNumber) {
+          this.filter.number = this.$route.query.examNumber;
+          this.toSearch();
+        }
+      }
+    },
+    async getWorkList() {
+      this.works = await workList();
+    },
+    async getSubjects() {
+      const data = await subjectList(this.filter.workId);
+      this.subjects = data.filter((item) => item.enable);
+    },
+    async getAreaList() {
+      const data = await areaList({
+        workId: this.filter.workId,
+        subject: this.filter.subject,
+      });
+      this.areas = data.map((item) => {
+        return {
+          id: item.id,
+          areaName: item.areaName,
+          areaCode: item.areaCode,
+        };
+      });
+    },
+    async toSearch() {
+      if (!this.filter.number && !this.filter.studentName) {
+        this.$Message.error("号码和姓名必须填写一个");
+        return;
+      }
+      const data = await studentScoreList(this.filter);
+      if (!data.length) {
+        this.$Message.error("无此考生");
+        return;
+      }
+      this.students = data;
+      this.total = this.students.length;
+      this.toPage(1);
+    },
+    toPage(page) {
+      if (!this.students[page - 1]) return;
+      this.current = page;
+      this.curStudent = this.students[page - 1];
+      this.papers = this.curStudent.papers.map((item) => {
+        let nitem = { ...item };
+        nitem.key = this.$randomCode();
+        nitem.imgSrc = item.sheetSrc;
+        nitem.thumbSrc = item.sheetSrc;
+        const fields = ["taskScores", "taskLevels"];
+        const validField = fields.find(
+          (field) => item[field] && item[field].length
+        );
+        nitem.taskList = validField ? item[validField] : [];
+        return nitem;
+      });
+    },
+    workChange() {
+      this.filter.subject = null;
+      this.filter.questionId = null;
+      const curWork = this.works.find((item) => item.id === this.filter.workId);
+      this.subjects = curWork.subjects;
+      this.filter.subject = this.subjects[0].subject;
+    },
+    subjecChange() {
+      if (this.IS_INSPECTION) {
+        this.filter.questionId = null;
+        this.getAreaList();
+      }
+    },
+    // paper view
+    toReview(index) {
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        this.$Message.warning("当前已经是第一条数据了");
+        return;
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        this.$Message.warning("当前已经是最后一条数据了");
+        return;
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

+ 174 - 174
src/modules/main/WorkManage.vue

@@ -1,174 +1,174 @@
-<template>
-  <div class="home">
-    <view-header class="home-header" :show-reset-pwd="false"></view-header>
-
-    <div class="home-body">
-      <div class="home-main">
-        <div class="work-manage">
-          <div class="part-box-head">
-            <Form label-position="left" inline>
-              <FormItem>
-                <Input
-                  v-model.trim="modalForm.name"
-                  placeholder="工作名称"
-                  clearable
-                ></Input>
-              </FormItem>
-              <FormItem :label-width="0">
-                <Button
-                  size="small"
-                  type="success"
-                  icon="recode-white icon"
-                  shape="circle"
-                  @click="toAdd"
-                  >新增工作文件</Button
-                >
-              </FormItem>
-            </Form>
-          </div>
-          <Table
-            ref="TableList"
-            :columns="columns"
-            :data="works"
-            :row-class-name="rowClassName"
-            disabled-hover
-            border
-          ></Table>
-        </div>
-
-        <!-- <view-footer></view-footer> -->
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { workList, createWork, deleteWork } from "@/api";
-
-export default {
-  name: "work-manage",
-  data() {
-    return {
-      modalForm: {
-        name: ""
-      },
-      works: [],
-      columns: [
-        {
-          title: "序号",
-          width: 80,
-          render: (h, param) => {
-            return h("div", param.index + 1 + "");
-          }
-        },
-        {
-          title: "ID",
-          key: "id",
-          minWidth: 100
-        },
-        {
-          title: "名称",
-          key: "name",
-          minWidth: 200
-        },
-        {
-          title: "创建时间",
-          key: "createdOn",
-          minWidth: 160
-        },
-        {
-          title: "操作",
-          key: "action",
-          width: 140,
-          align: "center",
-          className: "table-action",
-          render: (h, param) => {
-            const actions = [
-              {
-                icon: "md-trash",
-                classes: ["icon-danger"],
-                attrs: {
-                  title: "删除"
-                },
-                action: () => {
-                  this.toDelete(param.row);
-                }
-              },
-              {
-                icon: "md-arrow-round-forward",
-                attrs: {
-                  title: "进入"
-                },
-                action: () => {
-                  this.toDetail(param.row);
-                }
-              }
-            ];
-
-            return h("div", this.$tableIconAction(h, actions));
-          }
-        }
-      ]
-    };
-  },
-  mounted() {
-    this.getList();
-  },
-  methods: {
-    async getList() {
-      const data = await workList();
-      this.works = data.map(item => {
-        return {
-          id: item.id,
-          name: item.name,
-          active: item.active,
-          createdOn: item.createdOn
-        };
-      });
-    },
-    rowClassName(row) {
-      return row.active ? "row-active" : "";
-    },
-    async toAdd() {
-      if (!this.modalForm.name) {
-        this.$Message.error("请输入工作名称!");
-        return;
-      }
-      if (this.modalForm.name.length > 100) {
-        this.$Message.error("工作名称长度不能超过100个字符!");
-        return;
-      }
-
-      await createWork(this.modalForm);
-      this.$Message.success("创建工作成功!");
-      this.getList();
-    },
-    toDetail(row) {
-      const user = this.$ls.get("user", {});
-      user.workId = row.id;
-      this.$ls.set("user", user);
-
-      this.$router.push({
-        name: "WorkOverview",
-        params: {
-          workId: row.id
-        }
-      });
-    },
-    toDelete(row) {
-      this.$Modal.confirm({
-        title: "删除警告",
-        content: "确定要删除当前工作吗?",
-        onOk: () => {
-          this.toDel(row.id);
-        }
-      });
-    },
-    async toDel(id) {
-      await deleteWork(id);
-      this.$Message.success("删除成功!");
-      this.getList();
-    }
-  }
-};
-</script>
+<template>
+  <div class="home">
+    <view-header class="home-header" :show-reset-pwd="false"></view-header>
+
+    <div class="home-body">
+      <div class="home-main">
+        <div class="work-manage">
+          <div class="part-box-head">
+            <Form label-position="left" inline>
+              <FormItem>
+                <Input
+                  v-model.trim="modalForm.name"
+                  placeholder="工作名称"
+                  clearable
+                ></Input>
+              </FormItem>
+              <FormItem :label-width="0">
+                <Button
+                  size="small"
+                  type="success"
+                  icon="recode-white icon"
+                  shape="circle"
+                  @click="toAdd"
+                  >新增工作文件</Button
+                >
+              </FormItem>
+            </Form>
+          </div>
+          <Table
+            ref="TableList"
+            :columns="columns"
+            :data="works"
+            :row-class-name="rowClassName"
+            disabled-hover
+            border
+          ></Table>
+        </div>
+
+        <!-- <view-footer></view-footer> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { workList, createWork, deleteWork } from "@/api";
+
+export default {
+  name: "work-manage",
+  data() {
+    return {
+      modalForm: {
+        name: "",
+      },
+      works: [],
+      columns: [
+        {
+          title: "序号",
+          width: 80,
+          render: (h, param) => {
+            return h("div", param.index + 1 + "");
+          },
+        },
+        {
+          title: "ID",
+          key: "id",
+          minWidth: 100,
+        },
+        {
+          title: "名称",
+          key: "name",
+          minWidth: 200,
+        },
+        {
+          title: "创建时间",
+          key: "createdOn",
+          minWidth: 160,
+        },
+        {
+          title: "操作",
+          key: "action",
+          width: 140,
+          align: "center",
+          className: "table-action",
+          render: (h, param) => {
+            const actions = [
+              {
+                icon: "md-trash",
+                classes: ["icon-danger"],
+                attrs: {
+                  title: "删除",
+                },
+                action: () => {
+                  this.toDelete(param.row);
+                },
+              },
+              {
+                icon: "md-arrow-round-forward",
+                attrs: {
+                  title: "进入",
+                },
+                action: () => {
+                  this.toDetail(param.row);
+                },
+              },
+            ];
+
+            return h("div", this.$tableIconAction(h, actions));
+          },
+        },
+      ],
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const data = await workList();
+      this.works = data.map((item) => {
+        return {
+          id: item.id,
+          name: item.name,
+          active: item.active,
+          createdOn: item.createdOn,
+        };
+      });
+    },
+    rowClassName(row) {
+      return row.active ? "row-active" : "";
+    },
+    async toAdd() {
+      if (!this.modalForm.name) {
+        this.$Message.error("请输入工作名称!");
+        return;
+      }
+      if (this.modalForm.name.length > 100) {
+        this.$Message.error("工作名称长度不能超过100个字符!");
+        return;
+      }
+
+      await createWork(this.modalForm);
+      this.$Message.success("创建工作成功!");
+      this.getList();
+    },
+    toDetail(row) {
+      const user = this.$ls.get("user", {});
+      user.workId = row.id;
+      this.$ls.set("user", user);
+
+      this.$router.push({
+        name: "WorkOverview",
+        params: {
+          workId: row.id,
+        },
+      });
+    },
+    toDelete(row) {
+      this.$Modal.confirm({
+        title: "删除警告",
+        content: "确定要删除当前工作吗?",
+        onOk: () => {
+          this.toDel(row.id);
+        },
+      });
+    },
+    async toDel(id) {
+      await deleteWork(id);
+      this.$Message.success("删除成功!");
+      this.getList();
+    },
+  },
+};
+</script>

+ 149 - 149
src/modules/main/WorkOverview.vue

@@ -1,149 +1,149 @@
-<template>
-  <div class="overview">
-    <div class="overview-head" v-if="overviewInfo.workName">
-      <div class="overview-bg-person"></div>
-      <h1 class="overview-title">{{ overviewInfo.workName }}</h1>
-      <ul class="overview-infos">
-        <li>
-          <span><i class="icon ivu-icon-student"></i></span>
-          <span>考生总数:</span>
-          <span>{{ overviewInfo.stuTotalCount }}</span>
-        </li>
-        <li>
-          <span><i class="icon ivu-icon-area"></i></span>
-          <span>考区数:</span>
-          <span>{{ overviewInfo.questionCount }}</span>
-        </li>
-      </ul>
-      <div class="overview-actions">
-        <Button
-          v-if="roughLevelEnable"
-          icon="md-download"
-          shape="circle"
-          @click="download(exportRoughGradeScoreUrl)"
-          >导出粗档位成绩</Button
-        >
-        <Button
-          icon="md-download"
-          shape="circle"
-          @click="download(exportGradeScoreUrl)"
-          >导出{{ roughLevelEnable ? "细档位" : "档位" }}成绩</Button
-        >
-        <Button
-          icon="md-download"
-          shape="circle"
-          @click="download(exportScoreUrl)"
-          >导出分数成绩</Button
-        >
-      </div>
-    </div>
-    <div class="overview-body">
-      <div
-        class="overview-subject"
-        v-for="(subject, index) in overviewInfo.subjectOverviews"
-        :key="index"
-      >
-        <div class="subject-content">
-          <h2 class="subject-name">{{ subject.subjectName }}</h2>
-          <ul class="subject-infos">
-            <li>
-              <p>已上传</p>
-              <p>{{ subject.uploadedCount }}</p>
-            </li>
-            <li>
-              <p>未采集</p>
-              <p>{{ subject.leftCount }}</p>
-            </li>
-            <li>
-              <p>进度</p>
-              <p>{{ subject.progress }}</p>
-            </li>
-          </ul>
-          <div class="subject-actions">
-            <p>当前阶段</p>
-            <p>{{ subject.markStageName }}</p>
-            <div class="subject-actions-detail">
-              <Button
-                icon="md-download"
-                shape="circle"
-                @click="download(subject.exportAbsentDataUrl)"
-                >导出缺考名单</Button
-              >
-            </div>
-          </div>
-          <Button
-            type="primary"
-            shape="circle"
-            @click="toCommit(subject)"
-            style="width: 120px;"
-            >评卷管理</Button
-          >
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { workOverviewDetail } from "@/api";
-import { SUBJECT_STAGE } from "@/constants/enumerate";
-
-export default {
-  name: "overview",
-  data() {
-    return {
-      workId: this.$route.params.workId,
-      SUBJECT_STAGE,
-      exportRoughGradeScoreUrl: "",
-      exportGradeScoreUrl: "",
-      exportScoreUrl: "",
-      roughLevelEnable: false,
-      overviewInfo: {
-        subjectOverviews: []
-      }
-    };
-  },
-  mounted() {
-    this.getDetail();
-    this.exportRoughGradeScoreUrl = `${this.GLOBAL.domain}/api/export/score/exportRoughLevelResult?workId=${this.workId}`;
-    this.exportGradeScoreUrl = `${this.GLOBAL.domain}/api/export/score/exportLevelResult?workId=${this.workId}`;
-    this.exportScoreUrl = `${this.GLOBAL.domain}/api/export/score/exportScoreResult?workId=${this.workId}`;
-  },
-  methods: {
-    async getDetail() {
-      const data = await workOverviewDetail(this.workId);
-      this.roughLevelEnable = data.roughLevelEnable;
-      data.subjectOverviews.map(item => {
-        item.markStageName = this.getStageName(
-          item.markStage,
-          this.roughLevelEnable
-        );
-        item.exportAbsentDataUrl = `${this.GLOBAL.domain}/api/export/users/${this.workId}/${item.subject}/export`;
-        item.progress =
-          item.uploadedCount + item.leftCount
-            ? (
-                (100 * item.uploadedCount) /
-                (item.uploadedCount + item.leftCount)
-              ).toFixed(1) + "%"
-            : "0.0%";
-      });
-      this.overviewInfo = data;
-    },
-    getStageName(stage, roughLevelEnable) {
-      let stageName = SUBJECT_STAGE[stage];
-      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档阶段";
-      return stageName;
-    },
-    download(url) {
-      window.open(this.urlAddAuthor(url));
-    },
-    toCommit(subject) {
-      const routerName = subject.markStage === "SCORE" ? "Mark" : "Grading";
-      this.$router.push({
-        name: routerName,
-        params: { workId: this.workId, subjectId: subject.subjectId }
-      });
-    }
-  }
-};
-</script>
+<template>
+  <div class="overview">
+    <div class="overview-head" v-if="overviewInfo.workName">
+      <div class="overview-bg-person"></div>
+      <h1 class="overview-title">{{ overviewInfo.workName }}</h1>
+      <ul class="overview-infos">
+        <li>
+          <span><i class="icon ivu-icon-student"></i></span>
+          <span>考生总数:</span>
+          <span>{{ overviewInfo.stuTotalCount }}</span>
+        </li>
+        <li>
+          <span><i class="icon ivu-icon-area"></i></span>
+          <span>考区数:</span>
+          <span>{{ overviewInfo.questionCount }}</span>
+        </li>
+      </ul>
+      <div class="overview-actions">
+        <Button
+          v-if="roughLevelEnable"
+          icon="md-download"
+          shape="circle"
+          @click="download(exportRoughGradeScoreUrl)"
+          >导出粗档位成绩</Button
+        >
+        <Button
+          icon="md-download"
+          shape="circle"
+          @click="download(exportGradeScoreUrl)"
+          >导出{{ roughLevelEnable ? "细档位" : "档位" }}成绩</Button
+        >
+        <Button
+          icon="md-download"
+          shape="circle"
+          @click="download(exportScoreUrl)"
+          >导出分数成绩</Button
+        >
+      </div>
+    </div>
+    <div class="overview-body">
+      <div
+        class="overview-subject"
+        v-for="(subject, index) in overviewInfo.subjectOverviews"
+        :key="index"
+      >
+        <div class="subject-content">
+          <h2 class="subject-name">{{ subject.subjectName }}</h2>
+          <ul class="subject-infos">
+            <li>
+              <p>已上传</p>
+              <p>{{ subject.uploadedCount }}</p>
+            </li>
+            <li>
+              <p>未采集</p>
+              <p>{{ subject.leftCount }}</p>
+            </li>
+            <li>
+              <p>进度</p>
+              <p>{{ subject.progress }}</p>
+            </li>
+          </ul>
+          <div class="subject-actions">
+            <p>当前阶段</p>
+            <p>{{ subject.markStageName }}</p>
+            <div class="subject-actions-detail">
+              <Button
+                icon="md-download"
+                shape="circle"
+                @click="download(subject.exportAbsentDataUrl)"
+                >导出缺考名单</Button
+              >
+            </div>
+          </div>
+          <Button
+            type="primary"
+            shape="circle"
+            @click="toCommit(subject)"
+            style="width: 120px"
+            >评卷管理</Button
+          >
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { workOverviewDetail } from "@/api";
+import { SUBJECT_STAGE } from "@/constants/enumerate";
+
+export default {
+  name: "overview",
+  data() {
+    return {
+      workId: this.$route.params.workId,
+      SUBJECT_STAGE,
+      exportRoughGradeScoreUrl: "",
+      exportGradeScoreUrl: "",
+      exportScoreUrl: "",
+      roughLevelEnable: false,
+      overviewInfo: {
+        subjectOverviews: [],
+      },
+    };
+  },
+  mounted() {
+    this.getDetail();
+    this.exportRoughGradeScoreUrl = `${this.GLOBAL.domain}/api/export/score/exportRoughLevelResult?workId=${this.workId}`;
+    this.exportGradeScoreUrl = `${this.GLOBAL.domain}/api/export/score/exportLevelResult?workId=${this.workId}`;
+    this.exportScoreUrl = `${this.GLOBAL.domain}/api/export/score/exportScoreResult?workId=${this.workId}`;
+  },
+  methods: {
+    async getDetail() {
+      const data = await workOverviewDetail(this.workId);
+      this.roughLevelEnable = data.roughLevelEnable;
+      data.subjectOverviews.map((item) => {
+        item.markStageName = this.getStageName(
+          item.markStage,
+          this.roughLevelEnable
+        );
+        item.exportAbsentDataUrl = `${this.GLOBAL.domain}/api/export/users/${this.workId}/${item.subject}/export`;
+        item.progress =
+          item.uploadedCount + item.leftCount
+            ? (
+                (100 * item.uploadedCount) /
+                (item.uploadedCount + item.leftCount)
+              ).toFixed(1) + "%"
+            : "0.0%";
+      });
+      this.overviewInfo = data;
+    },
+    getStageName(stage, roughLevelEnable) {
+      let stageName = SUBJECT_STAGE[stage];
+      if (roughLevelEnable && stage === "LEVEL") stageName = "细分档阶段";
+      return stageName;
+    },
+    download(url) {
+      window.open(this.urlAddAuthor(url));
+    },
+    toCommit(subject) {
+      const routerName = subject.markStage === "SCORE" ? "Mark" : "Grading";
+      this.$router.push({
+        name: routerName,
+        params: { workId: this.workId, subjectId: subject.subjectId },
+      });
+    },
+  },
+};
+</script>

+ 139 - 139
src/modules/main/components/CheckDataResult.vue

@@ -1,139 +1,139 @@
-<template>
-  <Modal
-    class="check-data-result"
-    v-model="modalIsShow"
-    title="校验详情"
-    :mask-closable="false"
-    footer-hide
-    width="800"
-    @on-visible-change="visibleChange"
-  >
-    <Table
-      ref="TableList"
-      :columns="columns"
-      :data="students"
-      disabled-hover
-      border
-    ></Table>
-
-    <div class="part-page">
-      <Page
-        :current="current"
-        :total="total"
-        :page-size="size"
-        show-total
-        show-elevator
-        @on-change="toPage"
-      ></Page>
-    </div>
-  </Modal>
-</template>
-
-<script>
-import { checkDataDetailList } from "@/api";
-
-export default {
-  name: "check-data-result",
-  props: {
-    data: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      students: [],
-      columns: [
-        {
-          type: "index",
-          title: "序号",
-          width: 80,
-          align: "center",
-          indexMethod: row => {
-            return (this.current - 1) * this.size + row._index + 1;
-          }
-        },
-        {
-          title: "姓名",
-          key: "studentName",
-          width: 100
-        },
-        {
-          title: "考号",
-          key: "examNumber",
-          width: 120
-        },
-        {
-          title: "错误原因",
-          key: "errorMessage"
-        },
-        {
-          title: "操作",
-          key: "action",
-          width: 100,
-          align: "center",
-          className: "table-action",
-          render: (h, param) => {
-            let actions = [];
-            actions.push({
-              icon: "ios-paper",
-              attrs: {
-                title: "查看"
-              },
-              action: () => {
-                this.toView(param.row);
-              }
-            });
-
-            return h("div", this.$tableIconAction(h, actions));
-          }
-        }
-      ],
-      current: 1,
-      size: this.GLOBAL.pageSize,
-      total: 0
-    };
-  },
-  methods: {
-    async visibleChange(visible) {
-      if (visible) {
-        this.toPage(1);
-      } else {
-        this.$emit("on-close");
-      }
-    },
-    async getList() {
-      const data = await checkDataDetailList({
-        checkDataId: this.data.id,
-        page: this.current - 1,
-        size: this.size
-      });
-      this.total = data.totalCount;
-      this.students = data.data;
-    },
-    toPage(page) {
-      this.current = page;
-      this.getList();
-    },
-    toView(row) {
-      window.open(
-        this.getRouterPath({
-          name: "StudentScore",
-          query: {
-            examNumber: row.examNumber
-          }
-        })
-      );
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    }
-  }
-};
-</script>
+<template>
+  <Modal
+    class="check-data-result"
+    v-model="modalIsShow"
+    title="校验详情"
+    :mask-closable="false"
+    footer-hide
+    width="800"
+    @on-visible-change="visibleChange"
+  >
+    <Table
+      ref="TableList"
+      :columns="columns"
+      :data="students"
+      disabled-hover
+      border
+    ></Table>
+
+    <div class="part-page">
+      <Page
+        :current="current"
+        :total="total"
+        :page-size="size"
+        show-total
+        show-elevator
+        @on-change="toPage"
+      ></Page>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { checkDataDetailList } from "@/api";
+
+export default {
+  name: "check-data-result",
+  props: {
+    data: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      students: [],
+      columns: [
+        {
+          type: "index",
+          title: "序号",
+          width: 80,
+          align: "center",
+          indexMethod: (row) => {
+            return (this.current - 1) * this.size + row._index + 1;
+          },
+        },
+        {
+          title: "姓名",
+          key: "studentName",
+          width: 100,
+        },
+        {
+          title: "考号",
+          key: "examNumber",
+          width: 120,
+        },
+        {
+          title: "错误原因",
+          key: "errorMessage",
+        },
+        {
+          title: "操作",
+          key: "action",
+          width: 100,
+          align: "center",
+          className: "table-action",
+          render: (h, param) => {
+            let actions = [];
+            actions.push({
+              icon: "ios-paper",
+              attrs: {
+                title: "查看",
+              },
+              action: () => {
+                this.toView(param.row);
+              },
+            });
+
+            return h("div", this.$tableIconAction(h, actions));
+          },
+        },
+      ],
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+    };
+  },
+  methods: {
+    async visibleChange(visible) {
+      if (visible) {
+        this.toPage(1);
+      } else {
+        this.$emit("on-close");
+      }
+    },
+    async getList() {
+      const data = await checkDataDetailList({
+        checkDataId: this.data.id,
+        page: this.current - 1,
+        size: this.size,
+      });
+      this.total = data.totalCount;
+      this.students = data.data;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    toView(row) {
+      window.open(
+        this.getRouterPath({
+          name: "StudentScore",
+          query: {
+            examNumber: row.examNumber,
+          },
+        })
+      );
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+  },
+};
+</script>

+ 163 - 163
src/modules/main/components/ImageActionList.vue

@@ -1,163 +1,163 @@
-<template>
-  <div :class="classes">
-    <div class="image-view" v-for="(image, index) in data" :key="image.key">
-      <div class="image-view-container">
-        <h5 class="image-view-title">{{ image.title }}</h5>
-        <image-view-contain
-          v-if="canRotate"
-          :ref="`image${image.id}`"
-          :image="image"
-          @to-review="toReview(index)"
-        ></image-view-contain>
-        <div
-          v-else
-          :class="[
-            'image-view-contain',
-            { 'image-view-none': !image.thumbSrc }
-          ]"
-        >
-          <img
-            v-if="image.thumbSrc"
-            :src="image.thumbSrc"
-            :alt="image.title"
-            :style="image.styles"
-            @click="toReview(index)"
-          />
-        </div>
-        <div class="image-view-actions" v-if="actions.length">
-          <div>
-            <Button
-              class="view-action-rotate"
-              size="small"
-              icon="md-refresh"
-              @click="toRotate(image)"
-              v-if="canRotate"
-            ></Button>
-            <Button
-              class="view-action-save"
-              size="small"
-              type="primary"
-              @click="toSaveRotate(image)"
-              :disabled="saving"
-              v-if="canRotate && image['stepDeg']"
-              >保存</Button
-            >
-          </div>
-          <div>
-            <Button
-              class="view-action-absent"
-              :type="image.missing ? 'error' : 'default'"
-              size="small"
-              @click="toSignAbsent(image)"
-              v-if="canAbsent"
-              >缺考</Button
-            >
-            <Button
-              v-if="canMark"
-              :class="['view-action-mark', { 'mark-act': image.mark }]"
-              size="small"
-              icon="md-bookmark"
-              @click="toMark(image)"
-            ></Button>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { rotatePaper, absentPaper, markPaper } from "@/api";
-import ImageViewContain from "../../../components/ImageViewContain";
-
-export default {
-  name: "image-action-list",
-  components: { ImageViewContain },
-  props: {
-    data: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    actions: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    columnNumber: {
-      type: Number,
-      default: 5
-    }
-  },
-  data() {
-    return {
-      curImageIndex: 0,
-      stepDeg: 0,
-      saving: false,
-      curUserRoleType: this.$ls.get("user", { role: "" }).role
-    };
-  },
-  computed: {
-    classes() {
-      return [
-        "image-action-list",
-        "image-view-list",
-        `image-view-list-${this.columnNumber}`
-      ];
-    },
-    canRotate() {
-      return this.actions.includes("rotate");
-    },
-    canAbsent() {
-      return this.actions.includes("absent");
-    },
-    canMark() {
-      return this.actions.includes("mark");
-    }
-  },
-  methods: {
-    toRotate(image) {
-      if (!image["stepDeg"]) this.$set(image, "stepDeg", 0);
-      image.deg += 90;
-      if (image.deg === 360) image.deg = 0;
-      image.stepDeg += 90;
-      if (image.stepDeg === 360) image.stepDeg = 0;
-      image.styles = {
-        transform: `rotate(${image.deg}deg)`
-      };
-      this.$refs[`image${image.id}`][0].resizeImage(image.deg);
-    },
-    async toSaveRotate(image) {
-      if (this.saving) return;
-      if (!image.stepDeg) return;
-      this.saving = true;
-
-      let result = true;
-      await rotatePaper(image.id, image.stepDeg).catch(() => {
-        result = false;
-      });
-      this.saving = false;
-      if (!result) return;
-      image.stepDeg = 0;
-      this.$Message.success("保存成功!");
-    },
-    async toSignAbsent(image) {
-      await absentPaper(image.id);
-      image.missing = !image.missing;
-    },
-    async toMark(image) {
-      await markPaper({
-        paperId: image.id,
-        isMark: !image.mark,
-        role: this.curUserRoleType
-      });
-      image.mark = !image.mark;
-    },
-    toReview(index) {
-      this.$emit("on-review", index);
-    }
-  }
-};
-</script>
+<template>
+  <div :class="classes">
+    <div class="image-view" v-for="(image, index) in data" :key="image.key">
+      <div class="image-view-container">
+        <h5 class="image-view-title">{{ image.title }}</h5>
+        <image-view-contain
+          v-if="canRotate"
+          :ref="`image${image.id}`"
+          :image="image"
+          @to-review="toReview(index)"
+        ></image-view-contain>
+        <div
+          v-else
+          :class="[
+            'image-view-contain',
+            { 'image-view-none': !image.thumbSrc },
+          ]"
+        >
+          <img
+            v-if="image.thumbSrc"
+            :src="image.thumbSrc"
+            :alt="image.title"
+            :style="image.styles"
+            @click="toReview(index)"
+          />
+        </div>
+        <div class="image-view-actions" v-if="actions.length">
+          <div>
+            <Button
+              class="view-action-rotate"
+              size="small"
+              icon="md-refresh"
+              @click="toRotate(image)"
+              v-if="canRotate"
+            ></Button>
+            <Button
+              class="view-action-save"
+              size="small"
+              type="primary"
+              @click="toSaveRotate(image)"
+              :disabled="saving"
+              v-if="canRotate && image['stepDeg']"
+              >保存</Button
+            >
+          </div>
+          <div>
+            <Button
+              class="view-action-absent"
+              :type="image.missing ? 'error' : 'default'"
+              size="small"
+              @click="toSignAbsent(image)"
+              v-if="canAbsent"
+              >缺考</Button
+            >
+            <Button
+              v-if="canMark"
+              :class="['view-action-mark', { 'mark-act': image.mark }]"
+              size="small"
+              icon="md-bookmark"
+              @click="toMark(image)"
+            ></Button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { rotatePaper, absentPaper, markPaper } from "@/api";
+import ImageViewContain from "../../../components/ImageViewContain";
+
+export default {
+  name: "image-action-list",
+  components: { ImageViewContain },
+  props: {
+    data: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    actions: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    columnNumber: {
+      type: Number,
+      default: 5,
+    },
+  },
+  data() {
+    return {
+      curImageIndex: 0,
+      stepDeg: 0,
+      saving: false,
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+    };
+  },
+  computed: {
+    classes() {
+      return [
+        "image-action-list",
+        "image-view-list",
+        `image-view-list-${this.columnNumber}`,
+      ];
+    },
+    canRotate() {
+      return this.actions.includes("rotate");
+    },
+    canAbsent() {
+      return this.actions.includes("absent");
+    },
+    canMark() {
+      return this.actions.includes("mark");
+    },
+  },
+  methods: {
+    toRotate(image) {
+      if (!image["stepDeg"]) this.$set(image, "stepDeg", 0);
+      image.deg += 90;
+      if (image.deg === 360) image.deg = 0;
+      image.stepDeg += 90;
+      if (image.stepDeg === 360) image.stepDeg = 0;
+      image.styles = {
+        transform: `rotate(${image.deg}deg)`,
+      };
+      this.$refs[`image${image.id}`][0].resizeImage(image.deg);
+    },
+    async toSaveRotate(image) {
+      if (this.saving) return;
+      if (!image.stepDeg) return;
+      this.saving = true;
+
+      let result = true;
+      await rotatePaper(image.id, image.stepDeg).catch(() => {
+        result = false;
+      });
+      this.saving = false;
+      if (!result) return;
+      image.stepDeg = 0;
+      this.$Message.success("保存成功!");
+    },
+    async toSignAbsent(image) {
+      await absentPaper(image.id);
+      image.missing = !image.missing;
+    },
+    async toMark(image) {
+      await markPaper({
+        paperId: image.id,
+        isMark: !image.mark,
+        role: this.curUserRoleType,
+      });
+      image.mark = !image.mark;
+    },
+    toReview(index) {
+      this.$emit("on-review", index);
+    },
+  },
+};
+</script>

+ 26 - 26
src/modules/main/components/ModifyStudent.vue

@@ -14,7 +14,7 @@
       :rules="rules"
       :rules="rules"
       :key="modalForm.id"
       :key="modalForm.id"
       :label-width="100"
       :label-width="100"
-      style="width: 340px;"
+      style="width: 340px"
     >
     >
       <FormItem prop="name" label="姓名">
       <FormItem prop="name" label="姓名">
         <Input
         <Input
@@ -104,7 +104,7 @@ const initModalForm = {
   areaName: "",
   areaName: "",
   areaCode: "",
   areaCode: "",
   school: "",
   school: "",
-  examRoom: ""
+  examRoom: "",
 };
 };
 
 
 export default {
 export default {
@@ -114,14 +114,14 @@ export default {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
+      },
     },
     },
     cascadeList: {
     cascadeList: {
       type: Array,
       type: Array,
       default() {
       default() {
         return [];
         return [];
-      }
-    }
+      },
+    },
   },
   },
   computed: {
   computed: {
     isEdit() {
     isEdit() {
@@ -129,7 +129,7 @@ export default {
     },
     },
     title() {
     title() {
       return (this.isEdit ? "编辑" : "新增") + "考生信息";
       return (this.isEdit ? "编辑" : "新增") + "考生信息";
-    }
+    },
   },
   },
   data() {
   data() {
     return {
     return {
@@ -143,48 +143,48 @@ export default {
           {
           {
             required: true,
             required: true,
             message: "请输入姓名",
             message: "请输入姓名",
-            trigger: "change"
+            trigger: "change",
           },
           },
           {
           {
             min: 2,
             min: 2,
             max: 20,
             max: 20,
-            message: "姓名长度只能介于2到20之间"
-          }
+            message: "姓名长度只能介于2到20之间",
+          },
         ],
         ],
         examNumber: [
         examNumber: [
           {
           {
             required: true,
             required: true,
             message: "请输入考号",
             message: "请输入考号",
-            trigger: "change"
+            trigger: "change",
           },
           },
           {
           {
             min: 2,
             min: 2,
             max: 20,
             max: 20,
-            message: "考号长度只能介于2到20之间"
-          }
+            message: "考号长度只能介于2到20之间",
+          },
         ],
         ],
         areaCode: [
         areaCode: [
           {
           {
             required: true,
             required: true,
             message: "请选择考区",
             message: "请选择考区",
-            trigger: "change"
-          }
+            trigger: "change",
+          },
         ],
         ],
         school: [
         school: [
           {
           {
             required: true,
             required: true,
             message: "请选择学校",
             message: "请选择学校",
-            trigger: "change"
-          }
+            trigger: "change",
+          },
         ],
         ],
         examRoom: [
         examRoom: [
           {
           {
             required: true,
             required: true,
             message: "请选择考场",
             message: "请选择考场",
-            trigger: "change"
-          }
-        ]
-      }
+            trigger: "change",
+          },
+        ],
+      },
     };
     };
   },
   },
   methods: {
   methods: {
@@ -204,17 +204,17 @@ export default {
     },
     },
     reviewInfo() {
     reviewInfo() {
       const curArea = this.cascadeList.find(
       const curArea = this.cascadeList.find(
-        item => item.areaCode === this.modalForm.areaCode
+        (item) => item.areaCode === this.modalForm.areaCode
       );
       );
       this.schools = curArea.schools;
       this.schools = curArea.schools;
       const curSchool = this.schools.find(
       const curSchool = this.schools.find(
-        item => item.school === this.modalForm.school
+        (item) => item.school === this.modalForm.school
       );
       );
       this.rooms = curSchool.rooms;
       this.rooms = curSchool.rooms;
     },
     },
     areaChange() {
     areaChange() {
       const curArea = this.cascadeList.find(
       const curArea = this.cascadeList.find(
-        item => item.areaCode === this.modalForm.areaCode
+        (item) => item.areaCode === this.modalForm.areaCode
       );
       );
       this.schools = curArea ? curArea.schools : [];
       this.schools = curArea ? curArea.schools : [];
       this.modalForm.areaName = curArea.areaName;
       this.modalForm.areaName = curArea.areaName;
@@ -227,7 +227,7 @@ export default {
     },
     },
     schoolChange() {
     schoolChange() {
       const curSchool = this.schools.find(
       const curSchool = this.schools.find(
-        item => item.school === this.modalForm.school
+        (item) => item.school === this.modalForm.school
       );
       );
       this.rooms = curSchool ? curSchool.rooms : [];
       this.rooms = curSchool ? curSchool.rooms : [];
       this.modalForm.examRoom = null;
       this.modalForm.examRoom = null;
@@ -262,7 +262,7 @@ export default {
       this.$Message.success(this.title + "成功!");
       this.$Message.success(this.title + "成功!");
       this.$emit("modified");
       this.$emit("modified");
       this.cancel();
       this.cancel();
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 18 - 20
src/modules/main/components/QualityAnalysisExport.vue

@@ -1,9 +1,7 @@
 <template>
 <template>
   <div class="quality-analysis-export analysis-export-modal">
   <div class="quality-analysis-export analysis-export-modal">
     <div class="print-box">
     <div class="print-box">
-      <h1>
-        阅卷质量分析
-      </h1>
+      <h1>阅卷质量分析</h1>
       <div class="quality-info">
       <div class="quality-info">
         <p>科目:{{ pageInfo.subjectName }}</p>
         <p>科目:{{ pageInfo.subjectName }}</p>
         <p>考区:{{ pageInfo.areaName }}</p>
         <p>考区:{{ pageInfo.areaName }}</p>
@@ -125,41 +123,41 @@ export default {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
+      },
     },
     },
     pageInfo: {
     pageInfo: {
       type: Object,
       type: Object,
       default() {
       default() {
         return {};
         return {};
-      }
-    }
+      },
+    },
   },
   },
   data() {
   data() {
     return {
     return {
-      showImg: false
+      showImg: false,
     };
     };
   },
   },
   mounted() {
   mounted() {
     this.$nextTick(() => {
     this.$nextTick(() => {
       this.$refs.levelsPropImg.src = this.$refs.levelsPropChart.getDataURL({
       this.$refs.levelsPropImg.src = this.$refs.levelsPropChart.getDataURL({
         backgroundColor: "#fff",
         backgroundColor: "#fff",
-        excludeComponents: ["toolbox"]
+        excludeComponents: ["toolbox"],
       });
       });
       this.$refs.deviationImg.src = this.$refs.deviationChart.getDataURL({
       this.$refs.deviationImg.src = this.$refs.deviationChart.getDataURL({
         backgroundColor: "#fff",
         backgroundColor: "#fff",
-        excludeComponents: ["toolbox"]
+        excludeComponents: ["toolbox"],
       });
       });
       this.$refs.distanceImg.src = this.$refs.distanceChart.getDataURL({
       this.$refs.distanceImg.src = this.$refs.distanceChart.getDataURL({
         backgroundColor: "#fff",
         backgroundColor: "#fff",
-        excludeComponents: ["toolbox"]
+        excludeComponents: ["toolbox"],
       });
       });
       this.$refs.callbackImg.src = this.$refs.callbackChart.getDataURL({
       this.$refs.callbackImg.src = this.$refs.callbackChart.getDataURL({
         backgroundColor: "#fff",
         backgroundColor: "#fff",
-        excludeComponents: ["toolbox"]
+        excludeComponents: ["toolbox"],
       });
       });
       this.$refs.selfCheckImg.src = this.$refs.selfCheckChart.getDataURL({
       this.$refs.selfCheckImg.src = this.$refs.selfCheckChart.getDataURL({
         backgroundColor: "#fff",
         backgroundColor: "#fff",
-        excludeComponents: ["toolbox"]
+        excludeComponents: ["toolbox"],
       });
       });
 
 
       this.showImg = true;
       this.showImg = true;
@@ -171,17 +169,17 @@ export default {
   methods: {
   methods: {
     async toExport() {
     async toExport() {
       let fetchAll = [];
       let fetchAll = [];
-      this.$el.childNodes.forEach(item => {
+      this.$el.childNodes.forEach((item) => {
         fetchAll.push(
         fetchAll.push(
           html2canvas(item, {
           html2canvas(item, {
-            allowTaint: true
+            allowTaint: true,
           })
           })
         );
         );
       });
       });
       const canvasList = await Promise.all(fetchAll).catch(() => {});
       const canvasList = await Promise.all(fetchAll).catch(() => {});
       const contents = canvasList
       const contents = canvasList
-        .filter(canvas => canvas)
-        .map(canvas => canvas.toDataURL().split(",")[1]);
+        .filter((canvas) => canvas)
+        .map((canvas) => canvas.toDataURL().split(",")[1]);
 
 
       if (!contents.length) {
       if (!contents.length) {
         this.$emit("on-exported", false);
         this.$emit("on-exported", false);
@@ -195,15 +193,15 @@ export default {
         url: `${this.GLOBAL.domain}/api/exportPdf`,
         url: `${this.GLOBAL.domain}/api/exportPdf`,
         header: { Authorization: user.token, userId: user.id },
         header: { Authorization: user.token, userId: user.id },
         data: {
         data: {
-          content: contents
+          content: contents,
         },
         },
-        fileName: `${this.pageInfo.subjectName}-${this.pageInfo.areaName}-阅卷质量分析.pdf`
+        fileName: `${this.pageInfo.subjectName}-${this.pageInfo.areaName}-阅卷质量分析.pdf`,
       }).catch(() => {
       }).catch(() => {
         result = false;
         result = false;
       });
       });
 
 
       this.$emit("on-exported", result);
       this.$emit("on-exported", result);
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 1 - 1
src/modules/main/components/UploadStudentPaper.vue

@@ -36,6 +36,6 @@ export default {
   data() {
   data() {
     return {};
     return {};
   },
   },
-  methods: {}
+  methods: {},
 };
 };
 </script>
 </script>

+ 8 - 8
src/modules/mark-set/ExportPaper.vue

@@ -58,7 +58,7 @@
 import {
 import {
   subjectList,
   subjectList,
   areaSchoolRoomCascadeList,
   areaSchoolRoomCascadeList,
-  exportDecryptPictures
+  exportDecryptPictures,
 } from "@/api";
 } from "@/api";
 import { IMAGE_TYPE } from "@/constants/enumerate";
 import { IMAGE_TYPE } from "@/constants/enumerate";
 import { requiredValid } from "@/plugins/formRules";
 import { requiredValid } from "@/plugins/formRules";
@@ -71,18 +71,18 @@ export default {
       decryptFilter: {
       decryptFilter: {
         imageType: "",
         imageType: "",
         areaId: "",
         areaId: "",
-        subject: ""
+        subject: "",
       },
       },
       decryptRules: {
       decryptRules: {
         imageType: requiredValid("请选择图片类型"),
         imageType: requiredValid("请选择图片类型"),
         areaId: requiredValid("请选择考区"),
         areaId: requiredValid("请选择考区"),
-        subject: requiredValid("请选择科目")
+        subject: requiredValid("请选择科目"),
       },
       },
       IMAGE_TYPE,
       IMAGE_TYPE,
       subjects: [],
       subjects: [],
       cascadeList: [],
       cascadeList: [],
       schools: [],
       schools: [],
-      rooms: []
+      rooms: [],
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -95,7 +95,7 @@ export default {
     },
     },
     async getSubjects() {
     async getSubjects() {
       const data = await subjectList(this.workId);
       const data = await subjectList(this.workId);
-      this.subjects = data.filter(item => item.enable);
+      this.subjects = data.filter((item) => item.enable);
     },
     },
     async toExportDecrypt() {
     async toExportDecrypt() {
       const valid = await this.$refs.decryptForm.validate();
       const valid = await this.$refs.decryptForm.validate();
@@ -103,10 +103,10 @@ export default {
 
 
       await exportDecryptPictures({
       await exportDecryptPictures({
         ...this.decryptFilter,
         ...this.decryptFilter,
-        workId: this.workId
+        workId: this.workId,
       });
       });
       this.$Message.success("操作成功,后台正在导出!");
       this.$Message.success("操作成功,后台正在导出!");
-    }
-  }
+    },
+  },
 };
 };
 </script>
 </script>

+ 137 - 137
src/modules/mark-set/MarkRuleSet.vue

@@ -1,137 +1,137 @@
-<template>
-  <div class="mark-rule-set part-box">
-    <Form
-      ref="modalFormComp"
-      :model="modalForm"
-      :label-width="230"
-      style="width: 400px"
-    >
-      <FormItem label="分数计算方式:">
-        <Select
-          v-model="modalForm.removeHighAndLow"
-          :disabled="!modalFormCanEdit"
-          placeholder="选择"
-        >
-          <Option
-            v-for="(val, key) in SCORE_CALC_TYPE"
-            :key="key"
-            :value="key * 1"
-            >{{ val }}</Option
-          >
-        </Select>
-      </FormItem>
-      <FormItem label="分数处理方式:">
-        <Select
-          v-model="modalForm.roundUp"
-          :disabled="!modalFormCanEdit"
-          placeholder="选择"
-        >
-          <Option
-            v-for="(val, key) in SCORE_HANDLE_TYPE"
-            :key="key"
-            :value="key * 1"
-            >{{ val }}</Option
-          >
-        </Select>
-      </FormItem>
-      <FormItem label="阅卷员是否显示改档及改档打分:">
-        <Select
-          v-model="modalForm.changeStage"
-          :disabled="!modalFormCanEdit"
-          placeholder="选择"
-        >
-          <Option
-            v-for="(val, key) in BOOLEAN_TYPE"
-            :key="key"
-            :value="key * 1"
-            :label="val"
-          ></Option>
-        </Select>
-      </FormItem>
-      <FormItem label="阅卷员是否显示所有试卷:">
-        <Select
-          v-model="modalForm.scoreShowAllPaper"
-          :disabled="!modalFormCanEdit"
-          placeholder="选择"
-        >
-          <Option
-            v-for="(val, key) in BOOLEAN_TYPE"
-            :key="key"
-            :value="key * 1"
-            :label="val"
-          ></Option>
-        </Select>
-      </FormItem>
-      <FormItem>
-        <Button
-          shape="circle"
-          style="width: 80px;"
-          @click="modalFormCanEdit = true"
-          >编辑</Button
-        >
-        <Button
-          type="primary"
-          shape="circle"
-          style="width: 80px;"
-          :disabled="isSubmit"
-          @click="submit"
-          >保存</Button
-        >
-      </FormItem>
-    </Form>
-  </div>
-</template>
-
-<script>
-import { getParamsSet, updateScoreParams } from "@/api";
-import {
-  BOOLEAN_TYPE,
-  SCORE_HANDLE_TYPE,
-  SCORE_CALC_TYPE
-} from "@/constants/enumerate";
-
-export default {
-  name: "mark-rule-set",
-  data() {
-    return {
-      isSubmit: false,
-      workId: this.$route.params.workId,
-      BOOLEAN_TYPE,
-      SCORE_HANDLE_TYPE,
-      SCORE_CALC_TYPE,
-      initModalForm: {
-        workId: "",
-        removeHighAndLow: 0,
-        roundUp: 0,
-        changeStage: 0,
-        scoreShowAllPaper: 0
-      },
-      modalFormCanEdit: false,
-      modalForm: {}
-    };
-  },
-  mounted() {
-    this.modalForm = { ...this.initModalForm };
-    this.getParamsSetInfo();
-  },
-  methods: {
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.modalForm = this.$objAssign(this.modalForm, data.scoreConfig);
-    },
-    async submit() {
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      let result = true;
-      await updateScoreParams(this.modalForm).catch(() => {
-        result = false;
-      });
-      this.isSubmit = false;
-
-      if (!result) return;
-      this.modalFormCanEdit = false;
-      this.$Message.success("保存成功!");
-    }
-  }
-};
-</script>
+<template>
+  <div class="mark-rule-set part-box">
+    <Form
+      ref="modalFormComp"
+      :model="modalForm"
+      :label-width="230"
+      style="width: 400px"
+    >
+      <FormItem label="分数计算方式:">
+        <Select
+          v-model="modalForm.removeHighAndLow"
+          :disabled="!modalFormCanEdit"
+          placeholder="选择"
+        >
+          <Option
+            v-for="(val, key) in SCORE_CALC_TYPE"
+            :key="key"
+            :value="key * 1"
+            >{{ val }}</Option
+          >
+        </Select>
+      </FormItem>
+      <FormItem label="分数处理方式:">
+        <Select
+          v-model="modalForm.roundUp"
+          :disabled="!modalFormCanEdit"
+          placeholder="选择"
+        >
+          <Option
+            v-for="(val, key) in SCORE_HANDLE_TYPE"
+            :key="key"
+            :value="key * 1"
+            >{{ val }}</Option
+          >
+        </Select>
+      </FormItem>
+      <FormItem label="阅卷员是否显示改档及改档打分:">
+        <Select
+          v-model="modalForm.changeStage"
+          :disabled="!modalFormCanEdit"
+          placeholder="选择"
+        >
+          <Option
+            v-for="(val, key) in BOOLEAN_TYPE"
+            :key="key"
+            :value="key * 1"
+            :label="val"
+          ></Option>
+        </Select>
+      </FormItem>
+      <FormItem label="阅卷员是否显示所有试卷:">
+        <Select
+          v-model="modalForm.scoreShowAllPaper"
+          :disabled="!modalFormCanEdit"
+          placeholder="选择"
+        >
+          <Option
+            v-for="(val, key) in BOOLEAN_TYPE"
+            :key="key"
+            :value="key * 1"
+            :label="val"
+          ></Option>
+        </Select>
+      </FormItem>
+      <FormItem>
+        <Button
+          shape="circle"
+          style="width: 80px"
+          @click="modalFormCanEdit = true"
+          >编辑</Button
+        >
+        <Button
+          type="primary"
+          shape="circle"
+          style="width: 80px"
+          :disabled="isSubmit"
+          @click="submit"
+          >保存</Button
+        >
+      </FormItem>
+    </Form>
+  </div>
+</template>
+
+<script>
+import { getParamsSet, updateScoreParams } from "@/api";
+import {
+  BOOLEAN_TYPE,
+  SCORE_HANDLE_TYPE,
+  SCORE_CALC_TYPE,
+} from "@/constants/enumerate";
+
+export default {
+  name: "mark-rule-set",
+  data() {
+    return {
+      isSubmit: false,
+      workId: this.$route.params.workId,
+      BOOLEAN_TYPE,
+      SCORE_HANDLE_TYPE,
+      SCORE_CALC_TYPE,
+      initModalForm: {
+        workId: "",
+        removeHighAndLow: 0,
+        roundUp: 0,
+        changeStage: 0,
+        scoreShowAllPaper: 0,
+      },
+      modalFormCanEdit: false,
+      modalForm: {},
+    };
+  },
+  mounted() {
+    this.modalForm = { ...this.initModalForm };
+    this.getParamsSetInfo();
+  },
+  methods: {
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.modalForm = this.$objAssign(this.modalForm, data.scoreConfig);
+    },
+    async submit() {
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      let result = true;
+      await updateScoreParams(this.modalForm).catch(() => {
+        result = false;
+      });
+      this.isSubmit = false;
+
+      if (!result) return;
+      this.modalFormCanEdit = false;
+      this.$Message.success("保存成功!");
+    },
+  },
+};
+</script>

+ 5 - 5
src/modules/mark-set/MarkSet.vue

@@ -4,7 +4,7 @@
       <div
       <div
         :class="[
         :class="[
           'set-navs-item',
           'set-navs-item',
-          { 'set-navs-item-act': curNav.name === nav.name }
+          { 'set-navs-item-act': curNav.name === nav.name },
         ]"
         ]"
         v-for="(nav, index) in navs"
         v-for="(nav, index) in navs"
         :key="index"
         :key="index"
@@ -28,18 +28,18 @@ export default {
   data() {
   data() {
     return {
     return {
       navs: markSet,
       navs: markSet,
-      curNav: {}
+      curNav: {},
     };
     };
   },
   },
   watch: {
   watch: {
     $route: {
     $route: {
       handler(val) {
       handler(val) {
         this.actCurNav(val);
         this.actCurNav(val);
-      }
-    }
+      },
+    },
   },
   },
   mounted() {
   mounted() {
     this.actCurNav(this.$route);
     this.actCurNav(this.$route);
-  }
+  },
 };
 };
 </script>
 </script>

+ 462 - 462
src/modules/mark/MarkDetail.vue

@@ -1,462 +1,462 @@
-<template>
-  <div :class="compClasses">
-    <grade-filter
-      ref="GradeFilter"
-      :data="workSubject"
-      @change="areaChange"
-    ></grade-filter>
-    <mark-step
-      :steps="steps"
-      :init-step="curStep"
-      :show-top-number="false"
-      @on-change="stepChange"
-      ref="MarkStep"
-      v-if="steps.levelStep"
-    ></mark-step>
-    <div class="detail-body clear-float">
-      <!-- detail-papers -->
-      <div :class="detailPapersClasses">
-        <div class="detail-papers-carousel" v-if="!IS_ADMIN">
-          <grade-history-paper
-            :question-id="filter.questionId"
-            stage="SCORE"
-            @on-paper-click="toViewCarouselPaper"
-            v-if="filter.questionId"
-            ref="GradeHistoryPaper"
-          ></grade-history-paper>
-        </div>
-        <div class="detail-papers-list" v-if="papers.length">
-          <div :class="imageViewClasses">
-            <div
-              :class="[
-                'image-view',
-                { 'image-view-act': curPaperIndex === index }
-              ]"
-              v-for="(image, index) in papers"
-              :key="index"
-            >
-              <div class="image-view-container">
-                <h5 class="image-view-title">{{ image.title }}</h5>
-                <div class="image-view-contain">
-                  <img
-                    :src="image.thumbSrc"
-                    :alt="image.title"
-                    @click="toReview(index)"
-                  />
-                  <span
-                    class="image-info"
-                    v-if="image.score || image.score === 0"
-                    >{{ image.score }}分</span
-                  >
-                </div>
-              </div>
-            </div>
-          </div>
-          <div class="part-page">
-            <Page
-              :current="current"
-              :total="total"
-              :page-size="size"
-              show-total
-              show-elevator
-              @on-change="toPage"
-            ></Page>
-          </div>
-        </div>
-        <div class="detail-papers-list" v-else>
-          <p class="detail-papers-none">暂无数据</p>
-        </div>
-      </div>
-      <!-- detail-aciton -->
-      <div
-        :class="[
-          'detail-action',
-          { 'detail-action-fullscreen': isFullscreenMarking }
-        ]"
-      >
-        <mark-action
-          :key="paperKey"
-          :cur-paper-or-task="curPaper"
-          :levels="levels"
-          @on-leader-level="leaderSelectLevel"
-          @on-code-search="serachPaperByCode"
-          @on-grade-change-search="searchGradeChangeList"
-          v-if="curPaper.id"
-          ref="MarkAction"
-        ></mark-action>
-      </div>
-      <!-- 占位 -->
-      <div class="detail-action" v-if="isFullscreenMarking"></div>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :class="imagePreviewClasses"
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      @on-close="isFullscreenMarking = false"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-    <!-- carousel paper review -->
-    <simple-image-preview
-      :class="imagePreviewClasses"
-      :cur-image="curPaper"
-      @on-prev="toCarousePaper('prev')"
-      @on-next="toCarousePaper('next')"
-      @on-close="carouseImagePreviewClose"
-      ref="CarouselPapersPreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import {
-  paperList,
-  changeLevelPaperList,
-  scoreStatData,
-  workLevelList,
-  taskSnSearch,
-  markStepChangeLevel
-} from "@/api";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import MarkStep from "./components/MarkStep";
-import GradeFilter from "../grading/components/GradeFilter";
-import GradeHistoryPaper from "../grading/components/GradeHistoryPaper";
-import MarkAction from "./components/MarkAction";
-// 三种情况:
-// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
-// 管理员:试卷列表,操作盘
-// 科组长:操作记录,试卷列表,操作盘(改档)
-
-// TIP:不考虑评卷员的情况
-// 评卷员:操作记录,试卷列表,操作盘(打分)
-
-export default {
-  name: "mark-detail",
-  components: {
-    SimpleImagePreview,
-    MarkStep,
-    GradeFilter,
-    GradeHistoryPaper,
-    MarkAction
-  },
-  data() {
-    return {
-      filter: {
-        questionId: "",
-        sort: "score,desc"
-      },
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      workSubject: {},
-      curUserRoleType: "",
-      applyChangeLevelStatus: 1, // 改档申请处理状态
-      current: 1,
-      size: 6,
-      total: 0,
-      totalPage: 1,
-      curStep: { type: "", name: "" },
-      steps: [],
-      levels: [],
-      curArea: {},
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      paperKey: "",
-      // carousel paper review,
-      carouselPapers: [],
-      curCarouselPaperIndex: 0,
-      isFullscreenMarking: false
-    };
-  },
-  computed: {
-    compClasses() {
-      return [
-        "page-container-flex",
-        "mark-detail",
-        "grading-detail",
-        { "grading-operation": this.IS_MARK_LEADER }
-      ];
-    },
-    bodyClasses() {
-      return [
-        "detail-body",
-        { "detail-body-2": this.curUserRoleType === "ADMIN" }
-      ];
-    },
-    detailPapersClasses() {
-      return [
-        "detail-papers",
-        {
-          [`detail-papers-col-${1 + this.size / 2}`]:
-            this.curUserRoleType !== "ADMIN"
-        }
-      ];
-    },
-    imageViewClasses() {
-      return ["image-view-list", `image-view-list-${this.size / 2}`];
-    },
-    IS_ADMIN() {
-      return this.curUserRoleType === "ADMIN";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    },
-    imagePreviewClasses() {
-      return this.IS_ADMIN
-        ? "grading-detail-image-preview"
-        : "grading-operation-image-preview";
-    }
-  },
-  created() {
-    this.subject = this.subjectId.split("-")[1];
-    this.workSubject = {
-      workId: this.workId,
-      subject: this.subject
-    };
-    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    if (this.curUserRoleType === "ADMIN") this.size = 8;
-    this.initData();
-  },
-  methods: {
-    initData() {
-      this.getWorkLevels();
-    },
-    async getList() {
-      let data = [];
-      if (this.curStep.type === "shift") {
-        const datas = {
-          workId: this.workId,
-          subject: this.subject,
-          questionId: this.filter.questionId,
-          status: this.applyChangeLevelStatus,
-          page: this.current - 1,
-          size: this.size
-        };
-        data = await changeLevelPaperList(datas);
-      } else {
-        const datas = {
-          ...this.filter,
-          isScore: true,
-          page: this.current - 1,
-          size: this.size
-        };
-        if (this.curStep.type === "done") datas.level = this.curStep.name;
-
-        data = await paperList(datas);
-      }
-      this.papers = data.data.map(paper => {
-        paper.title = `NO.${paper.sn}`;
-        // paper.title = this.IS_ADMIN ? paper.examNumber : `NO.${paper.sn}`;
-        return paper;
-      });
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-    },
-    async toPage(page) {
-      this.current = page;
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async getStepLevels() {
-      const data = await scoreStatData(this.subjectId, this.filter.questionId);
-      const undoIndex = data.findIndex(item => item.id === null);
-      let otherStep = [];
-      let undo = {
-        count: 0,
-        shift: 0
-      };
-      if (undoIndex !== -1) {
-        undo = { ...data[undoIndex] };
-        data.splice(undoIndex, 1);
-      }
-      otherStep.push({
-        name: "待评",
-        count: undo.count,
-        type: "undo"
-      });
-      otherStep.push({
-        name: "改档",
-        count: undo.shift,
-        type: "shift"
-      });
-      let levelStep = data.map(item => {
-        return {
-          ...item,
-          name: item.id,
-          type: "done"
-        };
-      });
-      this.steps = { levelStep, otherStep };
-      if (!this.curStep.type) {
-        this.curStep = levelStep[0];
-      }
-    },
-    async getWorkLevels() {
-      const data = await workLevelList(this.workId);
-      this.levels = data || [];
-    },
-    async stepChange(step) {
-      this.applyChangeLevelStatus = 1;
-      this.curStep = step;
-      this.current = 1;
-      await this.getList();
-      if (this.papers.length) {
-        this.selectPaper(0);
-      } else {
-        this.curPaper = {};
-      }
-    },
-    async areaChange(curArea) {
-      this.curArea = curArea;
-      this.filter.questionId = curArea.id;
-      await this.getStepLevels();
-      this.toPage(1);
-    },
-    toReview(index) {
-      this.isFullscreenMarking = true;
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    toExport() {
-      window.open(
-        this.urlAddAuthor(
-          `${this.GLOBAL.domain}/api/export/paper/${this.workId}/${this.subject}/changeLevel`
-        )
-      );
-    },
-    selectPaper(index) {
-      this.paperKey = this.$randomCode();
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toActionNextPaper() {
-      if (this.current > 1 && this.papers.length === 1) {
-        this.current--;
-        this.curPaperIndex = this.size;
-      }
-
-      await this.getList();
-      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
-      this.selectPaper(this.curPaperIndex);
-    },
-    updateHistory() {
-      this.$refs.GradeHistoryPaper.updatePapers();
-    },
-    async serachPaperByCode(params) {
-      const data = await taskSnSearch(
-        params.codeType,
-        params.code,
-        this.filter.questionId,
-        "SCORE"
-      );
-      if (!data) {
-        this.$Message.error("没有查找到结果!");
-        return;
-      }
-      data.title = `NO.${data.sn}`;
-      data.key = this.$randomCode();
-      // data.title = this.IS_ADMIN ? data.examNumber : `NO.${data.sn}`;
-      this.papers = [data];
-      this.total = 1;
-      this.selectPaper(0);
-    },
-    searchGradeChangeList(applyChangeLevelStatus) {
-      this.applyChangeLevelStatus = applyChangeLevelStatus;
-      this.toPage(1);
-    },
-    leaderSelectLevel(levelInfo) {
-      const content = `确定申请由${levelInfo.curLevel}档改为${levelInfo.selectedLevel}并打回给所有老师吗?`;
-      this.$Modal.confirm({
-        content,
-        onOk: async () => {
-          await markStepChangeLevel({
-            subjectId: this.subjectId,
-            paperId: levelInfo.paperId,
-            level: levelInfo.selectedLevel,
-            userId: this.$ls.get("user", { id: "" }).id
-          });
-          this.$Message.success("申请改档成功!");
-          this.getStepLevels();
-          // this.updateHistory();
-          this.toActionNextPaper();
-        },
-        onCancel: () => {
-          this.$refs.MarkAction.btnClicked = false;
-        }
-      });
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers) {
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-      });
-    },
-    selectCarouselPaper(index) {
-      this.paperKey = this.$randomCode();
-      this.curCarouselPaperIndex = index;
-      this.curPaper = { ...this.carouselPapers[index] };
-    },
-    toCarousePaper(type) {
-      if (type === "prev" && this.curCarouselPaperIndex > 0) {
-        this.curCarouselPaperIndex--;
-      } else if (
-        type === "next" &&
-        this.curCarouselPaperIndex < this.carouselPapers.length - 1
-      ) {
-        this.curCarouselPaperIndex++;
-      }
-      this.selectCarouselPaper(this.curCarouselPaperIndex);
-    },
-    carouseImagePreviewClose() {
-      this.isFullscreenMarking = false;
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div :class="compClasses">
+    <grade-filter
+      ref="GradeFilter"
+      :data="workSubject"
+      @change="areaChange"
+    ></grade-filter>
+    <mark-step
+      :steps="steps"
+      :init-step="curStep"
+      :show-top-number="false"
+      @on-change="stepChange"
+      ref="MarkStep"
+      v-if="steps.levelStep"
+    ></mark-step>
+    <div class="detail-body clear-float">
+      <!-- detail-papers -->
+      <div :class="detailPapersClasses">
+        <div class="detail-papers-carousel" v-if="!IS_ADMIN">
+          <grade-history-paper
+            :question-id="filter.questionId"
+            stage="SCORE"
+            @on-paper-click="toViewCarouselPaper"
+            v-if="filter.questionId"
+            ref="GradeHistoryPaper"
+          ></grade-history-paper>
+        </div>
+        <div class="detail-papers-list" v-if="papers.length">
+          <div :class="imageViewClasses">
+            <div
+              :class="[
+                'image-view',
+                { 'image-view-act': curPaperIndex === index },
+              ]"
+              v-for="(image, index) in papers"
+              :key="index"
+            >
+              <div class="image-view-container">
+                <h5 class="image-view-title">{{ image.title }}</h5>
+                <div class="image-view-contain">
+                  <img
+                    :src="image.thumbSrc"
+                    :alt="image.title"
+                    @click="toReview(index)"
+                  />
+                  <span
+                    class="image-info"
+                    v-if="image.score || image.score === 0"
+                    >{{ image.score }}分</span
+                  >
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="part-page">
+            <Page
+              :current="current"
+              :total="total"
+              :page-size="size"
+              show-total
+              show-elevator
+              @on-change="toPage"
+            ></Page>
+          </div>
+        </div>
+        <div class="detail-papers-list" v-else>
+          <p class="detail-papers-none">暂无数据</p>
+        </div>
+      </div>
+      <!-- detail-aciton -->
+      <div
+        :class="[
+          'detail-action',
+          { 'detail-action-fullscreen': isFullscreenMarking },
+        ]"
+      >
+        <mark-action
+          :key="paperKey"
+          :cur-paper-or-task="curPaper"
+          :levels="levels"
+          @on-leader-level="leaderSelectLevel"
+          @on-code-search="serachPaperByCode"
+          @on-grade-change-search="searchGradeChangeList"
+          v-if="curPaper.id"
+          ref="MarkAction"
+        ></mark-action>
+      </div>
+      <!-- 占位 -->
+      <div class="detail-action" v-if="isFullscreenMarking"></div>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :class="imagePreviewClasses"
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      @on-close="isFullscreenMarking = false"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+    <!-- carousel paper review -->
+    <simple-image-preview
+      :class="imagePreviewClasses"
+      :cur-image="curPaper"
+      @on-prev="toCarousePaper('prev')"
+      @on-next="toCarousePaper('next')"
+      @on-close="carouseImagePreviewClose"
+      ref="CarouselPapersPreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import {
+  paperList,
+  changeLevelPaperList,
+  scoreStatData,
+  workLevelList,
+  taskSnSearch,
+  markStepChangeLevel,
+} from "@/api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import MarkStep from "./components/MarkStep";
+import GradeFilter from "../grading/components/GradeFilter";
+import GradeHistoryPaper from "../grading/components/GradeHistoryPaper";
+import MarkAction from "./components/MarkAction";
+// 三种情况:
+// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
+// 管理员:试卷列表,操作盘
+// 科组长:操作记录,试卷列表,操作盘(改档)
+
+// TIP:不考虑评卷员的情况
+// 评卷员:操作记录,试卷列表,操作盘(打分)
+
+export default {
+  name: "mark-detail",
+  components: {
+    SimpleImagePreview,
+    MarkStep,
+    GradeFilter,
+    GradeHistoryPaper,
+    MarkAction,
+  },
+  data() {
+    return {
+      filter: {
+        questionId: "",
+        sort: "score,desc",
+      },
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      workSubject: {},
+      curUserRoleType: "",
+      applyChangeLevelStatus: 1, // 改档申请处理状态
+      current: 1,
+      size: 6,
+      total: 0,
+      totalPage: 1,
+      curStep: { type: "", name: "" },
+      steps: [],
+      levels: [],
+      curArea: {},
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      paperKey: "",
+      // carousel paper review,
+      carouselPapers: [],
+      curCarouselPaperIndex: 0,
+      isFullscreenMarking: false,
+    };
+  },
+  computed: {
+    compClasses() {
+      return [
+        "page-container-flex",
+        "mark-detail",
+        "grading-detail",
+        { "grading-operation": this.IS_MARK_LEADER },
+      ];
+    },
+    bodyClasses() {
+      return [
+        "detail-body",
+        { "detail-body-2": this.curUserRoleType === "ADMIN" },
+      ];
+    },
+    detailPapersClasses() {
+      return [
+        "detail-papers",
+        {
+          [`detail-papers-col-${1 + this.size / 2}`]:
+            this.curUserRoleType !== "ADMIN",
+        },
+      ];
+    },
+    imageViewClasses() {
+      return ["image-view-list", `image-view-list-${this.size / 2}`];
+    },
+    IS_ADMIN() {
+      return this.curUserRoleType === "ADMIN";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    },
+    imagePreviewClasses() {
+      return this.IS_ADMIN
+        ? "grading-detail-image-preview"
+        : "grading-operation-image-preview";
+    },
+  },
+  created() {
+    this.subject = this.subjectId.split("-")[1];
+    this.workSubject = {
+      workId: this.workId,
+      subject: this.subject,
+    };
+    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    if (this.curUserRoleType === "ADMIN") this.size = 8;
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.getWorkLevels();
+    },
+    async getList() {
+      let data = [];
+      if (this.curStep.type === "shift") {
+        const datas = {
+          workId: this.workId,
+          subject: this.subject,
+          questionId: this.filter.questionId,
+          status: this.applyChangeLevelStatus,
+          page: this.current - 1,
+          size: this.size,
+        };
+        data = await changeLevelPaperList(datas);
+      } else {
+        const datas = {
+          ...this.filter,
+          isScore: true,
+          page: this.current - 1,
+          size: this.size,
+        };
+        if (this.curStep.type === "done") datas.level = this.curStep.name;
+
+        data = await paperList(datas);
+      }
+      this.papers = data.data.map((paper) => {
+        paper.title = `NO.${paper.sn}`;
+        // paper.title = this.IS_ADMIN ? paper.examNumber : `NO.${paper.sn}`;
+        return paper;
+      });
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+    },
+    async toPage(page) {
+      this.current = page;
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async getStepLevels() {
+      const data = await scoreStatData(this.subjectId, this.filter.questionId);
+      const undoIndex = data.findIndex((item) => item.id === null);
+      let otherStep = [];
+      let undo = {
+        count: 0,
+        shift: 0,
+      };
+      if (undoIndex !== -1) {
+        undo = { ...data[undoIndex] };
+        data.splice(undoIndex, 1);
+      }
+      otherStep.push({
+        name: "待评",
+        count: undo.count,
+        type: "undo",
+      });
+      otherStep.push({
+        name: "改档",
+        count: undo.shift,
+        type: "shift",
+      });
+      let levelStep = data.map((item) => {
+        return {
+          ...item,
+          name: item.id,
+          type: "done",
+        };
+      });
+      this.steps = { levelStep, otherStep };
+      if (!this.curStep.type) {
+        this.curStep = levelStep[0];
+      }
+    },
+    async getWorkLevels() {
+      const data = await workLevelList(this.workId);
+      this.levels = data || [];
+    },
+    async stepChange(step) {
+      this.applyChangeLevelStatus = 1;
+      this.curStep = step;
+      this.current = 1;
+      await this.getList();
+      if (this.papers.length) {
+        this.selectPaper(0);
+      } else {
+        this.curPaper = {};
+      }
+    },
+    async areaChange(curArea) {
+      this.curArea = curArea;
+      this.filter.questionId = curArea.id;
+      await this.getStepLevels();
+      this.toPage(1);
+    },
+    toReview(index) {
+      this.isFullscreenMarking = true;
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    toExport() {
+      window.open(
+        this.urlAddAuthor(
+          `${this.GLOBAL.domain}/api/export/paper/${this.workId}/${this.subject}/changeLevel`
+        )
+      );
+    },
+    selectPaper(index) {
+      this.paperKey = this.$randomCode();
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toActionNextPaper() {
+      if (this.current > 1 && this.papers.length === 1) {
+        this.current--;
+        this.curPaperIndex = this.size;
+      }
+
+      await this.getList();
+      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
+      this.selectPaper(this.curPaperIndex);
+    },
+    updateHistory() {
+      this.$refs.GradeHistoryPaper.updatePapers();
+    },
+    async serachPaperByCode(params) {
+      const data = await taskSnSearch(
+        params.codeType,
+        params.code,
+        this.filter.questionId,
+        "SCORE"
+      );
+      if (!data) {
+        this.$Message.error("没有查找到结果!");
+        return;
+      }
+      data.title = `NO.${data.sn}`;
+      data.key = this.$randomCode();
+      // data.title = this.IS_ADMIN ? data.examNumber : `NO.${data.sn}`;
+      this.papers = [data];
+      this.total = 1;
+      this.selectPaper(0);
+    },
+    searchGradeChangeList(applyChangeLevelStatus) {
+      this.applyChangeLevelStatus = applyChangeLevelStatus;
+      this.toPage(1);
+    },
+    leaderSelectLevel(levelInfo) {
+      const content = `确定申请由${levelInfo.curLevel}档改为${levelInfo.selectedLevel}并打回给所有老师吗?`;
+      this.$Modal.confirm({
+        content,
+        onOk: async () => {
+          await markStepChangeLevel({
+            subjectId: this.subjectId,
+            paperId: levelInfo.paperId,
+            level: levelInfo.selectedLevel,
+            userId: this.$ls.get("user", { id: "" }).id,
+          });
+          this.$Message.success("申请改档成功!");
+          this.getStepLevels();
+          // this.updateHistory();
+          this.toActionNextPaper();
+        },
+        onCancel: () => {
+          this.$refs.MarkAction.btnClicked = false;
+        },
+      });
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers) {
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+      });
+    },
+    selectCarouselPaper(index) {
+      this.paperKey = this.$randomCode();
+      this.curCarouselPaperIndex = index;
+      this.curPaper = { ...this.carouselPapers[index] };
+    },
+    toCarousePaper(type) {
+      if (type === "prev" && this.curCarouselPaperIndex > 0) {
+        this.curCarouselPaperIndex--;
+      } else if (
+        type === "next" &&
+        this.curCarouselPaperIndex < this.carouselPapers.length - 1
+      ) {
+        this.curCarouselPaperIndex++;
+      }
+      this.selectCarouselPaper(this.curCarouselPaperIndex);
+    },
+    carouseImagePreviewClose() {
+      this.isFullscreenMarking = false;
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

+ 1 - 1
src/modules/mark/MarkGroupManage.vue

@@ -13,6 +13,6 @@ export default {
   data() {
   data() {
     return {};
     return {};
   },
   },
-  methods: {}
+  methods: {},
 };
 };
 </script>
 </script>

+ 135 - 135
src/modules/mark/MarkHome.vue

@@ -1,135 +1,135 @@
-<template>
-  <div class="mark-home home">
-    <view-header key="1" :show-reset-pwd="false" v-if="IS_ADMIN">
-      <div class="grading-subnav" slot="navSub">
-        <div class="grading-title">
-          <h1>{{ curSubject.name }}</h1>
-          <span>当前阶段:打分阶段</span>
-        </div>
-        <div class="home-navs">
-          <ul>
-            <li
-              :class="{ act: curNav.name === nav.name }"
-              v-for="(nav, index) in navs"
-              :key="index"
-              @click="switchNav(nav)"
-            >
-              <i
-                :class="[
-                  'icon',
-                  curNav.name === nav.name ? `${nav.icon}-act` : nav.icon
-                ]"
-                v-if="nav.icon"
-              ></i>
-              <span class="nav-item-cont">{{ nav.title }}</span>
-            </li>
-          </ul>
-        </div>
-      </div>
-    </view-header>
-    <view-header key="2" v-else>
-      <div class="home-navs" slot="navSub">
-        <ul>
-          <li
-            :class="{ act: curNav.name === nav.name }"
-            v-for="(nav, index) in navs"
-            :key="index"
-            @click="switchNav(nav)"
-          >
-            <i
-              :class="[
-                'icon',
-                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon
-              ]"
-              v-if="nav.icon"
-            ></i>
-            <span class="nav-item-cont">{{ nav.title }}</span>
-          </li>
-        </ul>
-      </div>
-    </view-header>
-
-    <div class="home-body">
-      <div class="home-main">
-        <router-view />
-
-        <!-- <view-footer></view-footer> -->
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-import { subjectDetail } from "@/api";
-import { mark, main } from "@/constants/authority";
-import menuMixins from "@/components/homeMenuMixins";
-import { deepCopy } from "@/plugins/utils";
-
-export default {
-  name: "mark-home",
-  mixins: [menuMixins],
-  data() {
-    return {
-      subjectId: this.$route.params.subjectId,
-      navs: [],
-      curNav: {},
-      IS_ADMIN: true
-    };
-  },
-  computed: {
-    ...mapState("marker", ["curSubject"])
-  },
-  watch: {
-    $route: {
-      handler(val) {
-        this.actSubNav();
-      }
-    }
-  },
-  mounted() {
-    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.IS_ADMIN = curUserRoleType === "ADMIN";
-    this.initData();
-  },
-  methods: {
-    ...mapMutations("marker", ["setCurSubject"]),
-    async initData() {
-      const curSubject = await subjectDetail(this.subjectId);
-      this.setCurSubject(curSubject || {});
-
-      if (
-        this.curSubject.stage === "LEVEL" ||
-        this.curSubject.stage === "ROUGH_LEVEL"
-      ) {
-        this.$router.replace({
-          name: "Grading",
-          params: {
-            workId: this.subjectId.split("-")[0],
-            subjectId: this.subjectId
-          }
-        });
-        return;
-      }
-      this.buildNavs();
-      this.actSubNav();
-    },
-    buildNavs() {
-      this.navs = deepCopy(mark);
-      if (this.IS_ADMIN) {
-        this.navs.pop();
-        this.navs = [...main.slice(0, 2), ...this.navs];
-      } else {
-        this.navs.splice(1, 1);
-        this.navs.splice(2, 1);
-      }
-    },
-    actSubNav() {
-      const router = this.$route.matched.filter(
-        item => item.name !== "Mark"
-      )[0];
-      this.actCurNav(router);
-    }
-  }
-};
-</script>
+<template>
+  <div class="mark-home home">
+    <view-header key="1" :show-reset-pwd="false" v-if="IS_ADMIN">
+      <div class="grading-subnav" slot="navSub">
+        <div class="grading-title">
+          <h1>{{ curSubject.name }}</h1>
+          <span>当前阶段:打分阶段</span>
+        </div>
+        <div class="home-navs">
+          <ul>
+            <li
+              :class="{ act: curNav.name === nav.name }"
+              v-for="(nav, index) in navs"
+              :key="index"
+              @click="switchNav(nav)"
+            >
+              <i
+                :class="[
+                  'icon',
+                  curNav.name === nav.name ? `${nav.icon}-act` : nav.icon,
+                ]"
+                v-if="nav.icon"
+              ></i>
+              <span class="nav-item-cont">{{ nav.title }}</span>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </view-header>
+    <view-header key="2" v-else>
+      <div class="home-navs" slot="navSub">
+        <ul>
+          <li
+            :class="{ act: curNav.name === nav.name }"
+            v-for="(nav, index) in navs"
+            :key="index"
+            @click="switchNav(nav)"
+          >
+            <i
+              :class="[
+                'icon',
+                curNav.name === nav.name ? `${nav.icon}-act` : nav.icon,
+              ]"
+              v-if="nav.icon"
+            ></i>
+            <span class="nav-item-cont">{{ nav.title }}</span>
+          </li>
+        </ul>
+      </div>
+    </view-header>
+
+    <div class="home-body">
+      <div class="home-main">
+        <router-view />
+
+        <!-- <view-footer></view-footer> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import { subjectDetail } from "@/api";
+import { mark, main } from "@/constants/authority";
+import menuMixins from "@/components/homeMenuMixins";
+import { deepCopy } from "@/plugins/utils";
+
+export default {
+  name: "mark-home",
+  mixins: [menuMixins],
+  data() {
+    return {
+      subjectId: this.$route.params.subjectId,
+      navs: [],
+      curNav: {},
+      IS_ADMIN: true,
+    };
+  },
+  computed: {
+    ...mapState("marker", ["curSubject"]),
+  },
+  watch: {
+    $route: {
+      handler(val) {
+        this.actSubNav();
+      },
+    },
+  },
+  mounted() {
+    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
+    this.IS_ADMIN = curUserRoleType === "ADMIN";
+    this.initData();
+  },
+  methods: {
+    ...mapMutations("marker", ["setCurSubject"]),
+    async initData() {
+      const curSubject = await subjectDetail(this.subjectId);
+      this.setCurSubject(curSubject || {});
+
+      if (
+        this.curSubject.stage === "LEVEL" ||
+        this.curSubject.stage === "ROUGH_LEVEL"
+      ) {
+        this.$router.replace({
+          name: "Grading",
+          params: {
+            workId: this.subjectId.split("-")[0],
+            subjectId: this.subjectId,
+          },
+        });
+        return;
+      }
+      this.buildNavs();
+      this.actSubNav();
+    },
+    buildNavs() {
+      this.navs = deepCopy(mark);
+      if (this.IS_ADMIN) {
+        this.navs.pop();
+        this.navs = [...main.slice(0, 2), ...this.navs];
+      } else {
+        this.navs.splice(1, 1);
+        this.navs.splice(2, 1);
+      }
+    },
+    actSubNav() {
+      const router = this.$route.matched.filter(
+        (item) => item.name !== "Mark"
+      )[0];
+      this.actCurNav(router);
+    },
+  },
+};
+</script>

+ 492 - 492
src/modules/mark/MarkOperation.vue

@@ -1,492 +1,492 @@
-<template>
-  <div class="mark-operation grading-operation home">
-    <view-header> </view-header>
-    <div class="home-body">
-      <div class="home-main grading-detail">
-        <div class="grading-detail page-container-flex">
-          <grade-filter
-            ref="GradeFilter"
-            :data="workSubject"
-            @change="areaChange"
-          ></grade-filter>
-          <mark-step
-            :steps="steps"
-            :init-step="curStep"
-            :show-top-number="false"
-            @on-change="stepChange"
-            ref="MarkStep"
-            v-if="steps.levelStep"
-          ></mark-step>
-          <div class="detail-body clear-float">
-            <!-- detail-papers -->
-            <div :class="detailPapersClasses">
-              <div class="detail-papers-carousel">
-                <grade-history-paper
-                  :question-id="filter.questionId"
-                  stage="SCORE"
-                  @on-paper-click="toViewCarouselPaper"
-                  v-if="filter.questionId"
-                  ref="GradeHistoryPaper"
-                ></grade-history-paper>
-              </div>
-              <div class="detail-papers-list" v-if="papers.length">
-                <div :class="imageViewClasses">
-                  <div
-                    :class="[
-                      'image-view',
-                      { 'image-view-act': curPaperIndex === index }
-                    ]"
-                    v-for="(image, index) in papers"
-                    :key="index"
-                  >
-                    <div class="image-view-container">
-                      <h5 class="image-view-title">{{ image.title }}</h5>
-                      <div class="image-view-contain">
-                        <img
-                          :src="image.thumbSrc"
-                          :alt="image.title"
-                          @click="toReview(index)"
-                        />
-                        <span
-                          class="image-info"
-                          v-if="image.score || image.score === 0"
-                          >{{ image.score }}分</span
-                        >
-                      </div>
-                    </div>
-                  </div>
-                </div>
-                <div class="part-page">
-                  <Page
-                    :current="current"
-                    :total="total"
-                    :page-size="size"
-                    show-total
-                    show-elevator
-                    :page-size-opts="[4, 6, 8]"
-                    @on-page-size-change="pageSizeChange"
-                    @on-change="toPage"
-                  ></Page>
-                </div>
-              </div>
-              <div class="detail-papers-list" v-else>
-                <p class="detail-papers-none">暂无数据</p>
-              </div>
-            </div>
-            <!-- detail-aciton -->
-            <div
-              :class="[
-                'detail-action',
-                { 'detail-action-fullscreen': isFullscreenMarking }
-              ]"
-            >
-              <mark-action
-                :key="paperKey"
-                :cur-paper-or-task="curPaper"
-                :levels="levels"
-                @on-leader-level="gradingCurPaper"
-                @on-select-score="scoreCurPaper"
-                @on-pass="passCurPaper"
-                ref="GradeAction"
-                v-if="curPaper.id"
-              ></mark-action>
-            </div>
-            <!-- 占位 -->
-            <div class="detail-action" v-if="isFullscreenMarking"></div>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      class="grading-operation-image-preview"
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      @on-close="isFullscreenMarking = false"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-
-    <!-- carousel paper review -->
-    <simple-image-preview
-      class="grading-operation-image-preview"
-      :cur-image="curPaper"
-      @on-prev="toCarousePaper('prev')"
-      @on-next="toCarousePaper('next')"
-      @on-close="carouseImagePreviewClose"
-      ref="CarouselPapersPreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import {
-  getParamsSet,
-  markerTaskList,
-  markerChangeLevelPaperList,
-  markerScoreTotalStatData,
-  workLevelList,
-  paperSelectLevelOrScore,
-  paperTaskPass
-} from "@/api";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import MarkStep from "./components/MarkStep";
-import GradeFilter from "../grading/components/GradeFilter";
-import GradeHistoryPaper from "../grading/components/GradeHistoryPaper";
-import MarkAction from "./components/MarkAction";
-// 三种情况:
-// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
-// 评卷员:操作记录,试卷列表,操作盘(打分)
-
-// TIP:不考虑管理员、科组长的情况
-// 管理员:试卷列表,操作盘
-// 科组长:操作记录,试卷列表,操作盘(改档)
-
-export default {
-  name: "mark-operation",
-  components: {
-    SimpleImagePreview,
-    MarkStep,
-    GradeFilter,
-    GradeHistoryPaper,
-    MarkAction
-  },
-  data() {
-    return {
-      filter: {
-        markerId: this.$ls.get("user").id,
-        questionId: ""
-      },
-      typeFilter: {
-        undo: {
-          sort: "paper.level",
-          stage: "SCORE"
-        },
-        done: {
-          level: "",
-          sort: "updatedOn,desc",
-          stage: "SCORE"
-        },
-        shift: {
-          isShift: true,
-          isShiftScore: false
-        },
-        shiftScore: {
-          isShift: false,
-          isShiftScore: true
-        }
-      },
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      workSubject: {},
-      curSubject: {},
-      curUserRoleType: "MARKER",
-      changeStage: 0, // 是否显示改档及改档打分
-      current: 1,
-      size: 6,
-      total: 0,
-      totalPage: 1,
-      curStep: null,
-      curStandardGradeId: "",
-      steps: [],
-      levels: [],
-      curArea: {},
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      paperKey: "",
-      // carousel paper review,
-      carouselPapers: [],
-      curCarouselPaperIndex: 0,
-      isFullscreenMarking: false
-    };
-  },
-  computed: {
-    detailPapersClasses() {
-      return ["detail-papers", `detail-papers-col-${1 + this.size / 2}`];
-    },
-    imageViewClasses() {
-      return ["image-view-list", `image-view-list-${this.size / 2}`];
-    }
-  },
-  created() {
-    this.subject = this.subjectId.split("-")[1];
-    this.workSubject = {
-      workId: this.workId,
-      subject: this.subject
-    };
-    this.initData();
-  },
-  methods: {
-    initData() {
-      this.getWorkLevels();
-      this.getParamsSetInfo();
-    },
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.changeStage = data.changeStage;
-    },
-    async getList() {
-      const datas = {
-        ...this.filter,
-        ...this.typeFilter[this.curStep.type],
-        workId: this.workId,
-        page: this.current - 1,
-        size: this.size
-      };
-      if (this.curStep.type === "done") {
-        datas.level = this.curStep.name;
-      }
-      const requestAction = this.curStep.type.includes("shift")
-        ? markerChangeLevelPaperList
-        : markerTaskList;
-
-      const data = await requestAction(datas);
-      this.papers = data.data.map(paper => {
-        paper.title = `NO.${paper.sn}`;
-        return paper;
-      });
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-    },
-    async toPage(page) {
-      this.current = page;
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async getStepLevels() {
-      const data = await markerScoreTotalStatData(
-        this.filter.markerId,
-        this.filter.questionId
-      );
-      const undoIndex = data.findIndex(item => item.id === null);
-      let otherStep = [];
-      let undo = {
-        count: 0,
-        shift: 0,
-        shiftScore: 0
-      };
-      if (undoIndex !== -1) {
-        undo = { ...data[undoIndex] };
-        data.splice(undoIndex, 1);
-      }
-      otherStep.push({
-        name: "待评",
-        count: undo.count,
-        type: "undo"
-      });
-
-      if (this.changeStage) {
-        otherStep.push({
-          name: "改档",
-          count: undo.shift,
-          type: "shift"
-        });
-        otherStep.push({
-          name: "改档打分",
-          count: undo.shiftScore,
-          type: "shiftScore"
-        });
-      }
-      let levelStep = data.map(item => {
-        return {
-          ...item,
-          name: item.id,
-          type: "done"
-        };
-      });
-      this.steps = { levelStep, otherStep };
-
-      if (!this.curStep) {
-        let curStep = {};
-        if (undoIndex === -1) {
-          curStep = levelStep[0];
-        } else {
-          curStep = otherStep[0];
-        }
-        this.curStep = curStep;
-      }
-    },
-    updateStepLevel(curStep, curLevel, count = 1) {
-      if (curStep.type === "done") return;
-
-      const opos = this.steps.otherStep.findIndex(
-        item => item.type === curStep.type
-      );
-      this.steps.otherStep[opos].count -= count;
-
-      if (curStep.type === "shift") {
-        const spos = this.steps.otherStep.findIndex(
-          item => item.type === "shiftScore"
-        );
-        this.steps.otherStep[spos].count += count;
-      } else {
-        const pos = this.steps.levelStep.findIndex(
-          item => item.name === curLevel
-        );
-        this.steps.levelStep[pos].count += count;
-      }
-    },
-    async getWorkLevels() {
-      const data = await workLevelList(this.workId);
-      this.levels = data || [];
-    },
-    pageSizeChange(size) {
-      this.size = size;
-      this.toPage(1);
-      this.getStepLevels();
-    },
-    async stepChange(step) {
-      this.curStep = step;
-      this.current = 1;
-      await this.getList();
-      this.getStepLevels();
-      if (this.papers.length) {
-        this.selectPaper(0);
-      } else {
-        this.curPaper = {};
-      }
-    },
-    async areaChange(curArea) {
-      this.curArea = curArea;
-      this.filter.questionId = curArea.id;
-      await this.getStepLevels();
-      this.toPage(1);
-      this.updateHistory();
-    },
-    toReview(index) {
-      this.isFullscreenMarking = true;
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      this.paperKey = this.$randomCode();
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      const lastPaper = { ...this.curPaper };
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-
-      // 待评时,检查当前试卷是否已经切换档位
-      if (
-        this.curStep.type === "undo" &&
-        this.curPaper["level"] &&
-        this.curPaper["level"] !== lastPaper["level"]
-      ) {
-        this.$Modal.info({
-          content: `即将打分档位:${this.curPaper.level}`
-        });
-      }
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toActionNextPaper() {
-      if (this.current > 1 && this.papers.length === 1) {
-        this.current--;
-        this.curPaperIndex = this.size;
-      }
-
-      await this.getList();
-      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async gradingCurPaper({ selectedLevel }) {
-      // 确认改档
-      await paperSelectLevelOrScore(
-        this.curPaper.id, // is taskId
-        selectedLevel,
-        "LEVEL"
-      );
-      this.updateStepLevel(this.curStep, "shiftScore");
-      this.toActionNextPaper();
-    },
-    async scoreCurPaper(score) {
-      const paper = await paperSelectLevelOrScore(
-        this.curPaper.id, // is taskId
-        score,
-        "SCORE"
-      );
-      this.updateStepLevel(this.curStep, this.curPaper.level);
-      this.updateCacheHistory([paper]);
-      this.toActionNextPaper();
-    },
-    async passCurPaper(level) {
-      await paperTaskPass("SCORE", this.curPaper.id);
-      this.toActionNextPaper();
-    },
-    updateHistory() {
-      this.$refs.GradeHistoryPaper.updatePapers();
-    },
-    updateCacheHistory(papers) {
-      this.$refs.GradeHistoryPaper.updateCachePapers(papers);
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers) {
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-      });
-    },
-    selectCarouselPaper(index) {
-      this.paperKey = this.$randomCode();
-      this.curCarouselPaperIndex = index;
-      this.curPaper = { ...this.carouselPapers[index] };
-    },
-    toCarousePaper(type) {
-      if (type === "prev" && this.curCarouselPaperIndex > 0) {
-        this.curCarouselPaperIndex--;
-      } else if (
-        type === "next" &&
-        this.curCarouselPaperIndex < this.carouselPapers.length - 1
-      ) {
-        this.curCarouselPaperIndex++;
-      }
-      this.selectCarouselPaper(this.curCarouselPaperIndex);
-    },
-    carouseImagePreviewClose() {
-      this.isFullscreenMarking = false;
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="mark-operation grading-operation home">
+    <view-header> </view-header>
+    <div class="home-body">
+      <div class="home-main grading-detail">
+        <div class="grading-detail page-container-flex">
+          <grade-filter
+            ref="GradeFilter"
+            :data="workSubject"
+            @change="areaChange"
+          ></grade-filter>
+          <mark-step
+            :steps="steps"
+            :init-step="curStep"
+            :show-top-number="false"
+            @on-change="stepChange"
+            ref="MarkStep"
+            v-if="steps.levelStep"
+          ></mark-step>
+          <div class="detail-body clear-float">
+            <!-- detail-papers -->
+            <div :class="detailPapersClasses">
+              <div class="detail-papers-carousel">
+                <grade-history-paper
+                  :question-id="filter.questionId"
+                  stage="SCORE"
+                  @on-paper-click="toViewCarouselPaper"
+                  v-if="filter.questionId"
+                  ref="GradeHistoryPaper"
+                ></grade-history-paper>
+              </div>
+              <div class="detail-papers-list" v-if="papers.length">
+                <div :class="imageViewClasses">
+                  <div
+                    :class="[
+                      'image-view',
+                      { 'image-view-act': curPaperIndex === index },
+                    ]"
+                    v-for="(image, index) in papers"
+                    :key="index"
+                  >
+                    <div class="image-view-container">
+                      <h5 class="image-view-title">{{ image.title }}</h5>
+                      <div class="image-view-contain">
+                        <img
+                          :src="image.thumbSrc"
+                          :alt="image.title"
+                          @click="toReview(index)"
+                        />
+                        <span
+                          class="image-info"
+                          v-if="image.score || image.score === 0"
+                          >{{ image.score }}分</span
+                        >
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div class="part-page">
+                  <Page
+                    :current="current"
+                    :total="total"
+                    :page-size="size"
+                    show-total
+                    show-elevator
+                    :page-size-opts="[4, 6, 8]"
+                    @on-page-size-change="pageSizeChange"
+                    @on-change="toPage"
+                  ></Page>
+                </div>
+              </div>
+              <div class="detail-papers-list" v-else>
+                <p class="detail-papers-none">暂无数据</p>
+              </div>
+            </div>
+            <!-- detail-aciton -->
+            <div
+              :class="[
+                'detail-action',
+                { 'detail-action-fullscreen': isFullscreenMarking },
+              ]"
+            >
+              <mark-action
+                :key="paperKey"
+                :cur-paper-or-task="curPaper"
+                :levels="levels"
+                @on-leader-level="gradingCurPaper"
+                @on-select-score="scoreCurPaper"
+                @on-pass="passCurPaper"
+                ref="GradeAction"
+                v-if="curPaper.id"
+              ></mark-action>
+            </div>
+            <!-- 占位 -->
+            <div class="detail-action" v-if="isFullscreenMarking"></div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      class="grading-operation-image-preview"
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      @on-close="isFullscreenMarking = false"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+
+    <!-- carousel paper review -->
+    <simple-image-preview
+      class="grading-operation-image-preview"
+      :cur-image="curPaper"
+      @on-prev="toCarousePaper('prev')"
+      @on-next="toCarousePaper('next')"
+      @on-close="carouseImagePreviewClose"
+      ref="CarouselPapersPreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import {
+  getParamsSet,
+  markerTaskList,
+  markerChangeLevelPaperList,
+  markerScoreTotalStatData,
+  workLevelList,
+  paperSelectLevelOrScore,
+  paperTaskPass,
+} from "@/api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import MarkStep from "./components/MarkStep";
+import GradeFilter from "../grading/components/GradeFilter";
+import GradeHistoryPaper from "../grading/components/GradeHistoryPaper";
+import MarkAction from "./components/MarkAction";
+// 三种情况:
+// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
+// 评卷员:操作记录,试卷列表,操作盘(打分)
+
+// TIP:不考虑管理员、科组长的情况
+// 管理员:试卷列表,操作盘
+// 科组长:操作记录,试卷列表,操作盘(改档)
+
+export default {
+  name: "mark-operation",
+  components: {
+    SimpleImagePreview,
+    MarkStep,
+    GradeFilter,
+    GradeHistoryPaper,
+    MarkAction,
+  },
+  data() {
+    return {
+      filter: {
+        markerId: this.$ls.get("user").id,
+        questionId: "",
+      },
+      typeFilter: {
+        undo: {
+          sort: "paper.level",
+          stage: "SCORE",
+        },
+        done: {
+          level: "",
+          sort: "updatedOn,desc",
+          stage: "SCORE",
+        },
+        shift: {
+          isShift: true,
+          isShiftScore: false,
+        },
+        shiftScore: {
+          isShift: false,
+          isShiftScore: true,
+        },
+      },
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      workSubject: {},
+      curSubject: {},
+      curUserRoleType: "MARKER",
+      changeStage: 0, // 是否显示改档及改档打分
+      current: 1,
+      size: 6,
+      total: 0,
+      totalPage: 1,
+      curStep: null,
+      curStandardGradeId: "",
+      steps: [],
+      levels: [],
+      curArea: {},
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      paperKey: "",
+      // carousel paper review,
+      carouselPapers: [],
+      curCarouselPaperIndex: 0,
+      isFullscreenMarking: false,
+    };
+  },
+  computed: {
+    detailPapersClasses() {
+      return ["detail-papers", `detail-papers-col-${1 + this.size / 2}`];
+    },
+    imageViewClasses() {
+      return ["image-view-list", `image-view-list-${this.size / 2}`];
+    },
+  },
+  created() {
+    this.subject = this.subjectId.split("-")[1];
+    this.workSubject = {
+      workId: this.workId,
+      subject: this.subject,
+    };
+    this.initData();
+  },
+  methods: {
+    initData() {
+      this.getWorkLevels();
+      this.getParamsSetInfo();
+    },
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.changeStage = data.changeStage;
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        ...this.typeFilter[this.curStep.type],
+        workId: this.workId,
+        page: this.current - 1,
+        size: this.size,
+      };
+      if (this.curStep.type === "done") {
+        datas.level = this.curStep.name;
+      }
+      const requestAction = this.curStep.type.includes("shift")
+        ? markerChangeLevelPaperList
+        : markerTaskList;
+
+      const data = await requestAction(datas);
+      this.papers = data.data.map((paper) => {
+        paper.title = `NO.${paper.sn}`;
+        return paper;
+      });
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+    },
+    async toPage(page) {
+      this.current = page;
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async getStepLevels() {
+      const data = await markerScoreTotalStatData(
+        this.filter.markerId,
+        this.filter.questionId
+      );
+      const undoIndex = data.findIndex((item) => item.id === null);
+      let otherStep = [];
+      let undo = {
+        count: 0,
+        shift: 0,
+        shiftScore: 0,
+      };
+      if (undoIndex !== -1) {
+        undo = { ...data[undoIndex] };
+        data.splice(undoIndex, 1);
+      }
+      otherStep.push({
+        name: "待评",
+        count: undo.count,
+        type: "undo",
+      });
+
+      if (this.changeStage) {
+        otherStep.push({
+          name: "改档",
+          count: undo.shift,
+          type: "shift",
+        });
+        otherStep.push({
+          name: "改档打分",
+          count: undo.shiftScore,
+          type: "shiftScore",
+        });
+      }
+      let levelStep = data.map((item) => {
+        return {
+          ...item,
+          name: item.id,
+          type: "done",
+        };
+      });
+      this.steps = { levelStep, otherStep };
+
+      if (!this.curStep) {
+        let curStep = {};
+        if (undoIndex === -1) {
+          curStep = levelStep[0];
+        } else {
+          curStep = otherStep[0];
+        }
+        this.curStep = curStep;
+      }
+    },
+    updateStepLevel(curStep, curLevel, count = 1) {
+      if (curStep.type === "done") return;
+
+      const opos = this.steps.otherStep.findIndex(
+        (item) => item.type === curStep.type
+      );
+      this.steps.otherStep[opos].count -= count;
+
+      if (curStep.type === "shift") {
+        const spos = this.steps.otherStep.findIndex(
+          (item) => item.type === "shiftScore"
+        );
+        this.steps.otherStep[spos].count += count;
+      } else {
+        const pos = this.steps.levelStep.findIndex(
+          (item) => item.name === curLevel
+        );
+        this.steps.levelStep[pos].count += count;
+      }
+    },
+    async getWorkLevels() {
+      const data = await workLevelList(this.workId);
+      this.levels = data || [];
+    },
+    pageSizeChange(size) {
+      this.size = size;
+      this.toPage(1);
+      this.getStepLevels();
+    },
+    async stepChange(step) {
+      this.curStep = step;
+      this.current = 1;
+      await this.getList();
+      this.getStepLevels();
+      if (this.papers.length) {
+        this.selectPaper(0);
+      } else {
+        this.curPaper = {};
+      }
+    },
+    async areaChange(curArea) {
+      this.curArea = curArea;
+      this.filter.questionId = curArea.id;
+      await this.getStepLevels();
+      this.toPage(1);
+      this.updateHistory();
+    },
+    toReview(index) {
+      this.isFullscreenMarking = true;
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      this.paperKey = this.$randomCode();
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      const lastPaper = { ...this.curPaper };
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+
+      // 待评时,检查当前试卷是否已经切换档位
+      if (
+        this.curStep.type === "undo" &&
+        this.curPaper["level"] &&
+        this.curPaper["level"] !== lastPaper["level"]
+      ) {
+        this.$Modal.info({
+          content: `即将打分档位:${this.curPaper.level}`,
+        });
+      }
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toActionNextPaper() {
+      if (this.current > 1 && this.papers.length === 1) {
+        this.current--;
+        this.curPaperIndex = this.size;
+      }
+
+      await this.getList();
+      if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async gradingCurPaper({ selectedLevel }) {
+      // 确认改档
+      await paperSelectLevelOrScore(
+        this.curPaper.id, // is taskId
+        selectedLevel,
+        "LEVEL"
+      );
+      this.updateStepLevel(this.curStep, "shiftScore");
+      this.toActionNextPaper();
+    },
+    async scoreCurPaper(score) {
+      const paper = await paperSelectLevelOrScore(
+        this.curPaper.id, // is taskId
+        score,
+        "SCORE"
+      );
+      this.updateStepLevel(this.curStep, this.curPaper.level);
+      this.updateCacheHistory([paper]);
+      this.toActionNextPaper();
+    },
+    async passCurPaper(level) {
+      await paperTaskPass("SCORE", this.curPaper.id);
+      this.toActionNextPaper();
+    },
+    updateHistory() {
+      this.$refs.GradeHistoryPaper.updatePapers();
+    },
+    updateCacheHistory(papers) {
+      this.$refs.GradeHistoryPaper.updateCachePapers(papers);
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers) {
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+      });
+    },
+    selectCarouselPaper(index) {
+      this.paperKey = this.$randomCode();
+      this.curCarouselPaperIndex = index;
+      this.curPaper = { ...this.carouselPapers[index] };
+    },
+    toCarousePaper(type) {
+      if (type === "prev" && this.curCarouselPaperIndex > 0) {
+        this.curCarouselPaperIndex--;
+      } else if (
+        type === "next" &&
+        this.curCarouselPaperIndex < this.carouselPapers.length - 1
+      ) {
+        this.curCarouselPaperIndex++;
+      }
+      this.selectCarouselPaper(this.curCarouselPaperIndex);
+    },
+    carouseImagePreviewClose() {
+      this.isFullscreenMarking = false;
+      this.selectPaper(this.curPaperIndex);
+    },
+  },
+};
+</script>

Some files were not shown because too many files changed in this diff