zhangjie 3 tahun lalu
induk
melakukan
9c37ac3e7f

+ 2 - 2
src/App.vue

@@ -12,8 +12,8 @@ export default {
   mixins: [timeMixin],
   data() {
     return {
-      // unactiveTime: 0,
-      unactiveTime: 10 * 60 * 1000,
+      unactiveTime: 0,
+      // unactiveTime: 10 * 60 * 1000,
       timeIsOut: false
     };
   },

+ 462 - 458
src/api.js

@@ -1,458 +1,462 @@
-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");
-};
-
-// org-manage
-export const orgList = datas => {
-  return $get("/api/admin/organization", datas);
-};
-export const orgDetail = organizationId => {
-  return $get(`/api/admin/organization/${organizationId}`);
-};
-export const createOrg = datas => {
-  return $post(`/api/admin/organization`, datas, "json");
-};
-export const updateOrgUser = datas => {
-  return $put(`/api/admin/organization`, datas, "json");
-};
-export const enableOrgUser = userId => {
-  return $post(`/api/admin/organization/${userId}`, {});
-};
-export const deleteOrg = orgId => {
-  return $del(`/api/admin/organization/${orgId}`);
-};
-
-// 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 }) => {
-  return $post(`/api/papers/mark_paper`, { paperId, isMark });
-};
-
-// 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 absentStudentSubject = datas => {
-  return $post(`/api/students/missing`, datas);
-};
-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 = workId => {
-  return $get("/api/param/getParam", { workId });
-};
-export const updateCollectParams = datas => {
-  return $post("/api/param/collect", datas);
-};
-
-// grading-set -------------------------->
-// grading-level-set
-// TO workDetail and updateWork
-
-// grading-rule-set
-export const updateLevelParams = datas => {
-  return $post("/api/param/level", datas);
-};
-// 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);
-};
-
-// 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`);
-};
-
-// 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}`);
-};
-export const enableGradingUser = ({ userId, enable }) => {
-  return $post(`/api/admin/users/enable`, { userId, enable });
-};
-// 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 markUserList = ({ workId, subjectId }) => {
-  return $get("/api/markers", { workId, subject: subjectId });
-};
-// grading-progress
-export const gradingProgressDetail = ({ workId, subject }) => {
-  return $get("/api/markers/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 gotoScoreStep = subjectId => {
-  return $patch(`/api/marksubjects/${subjectId}`, {}, "json");
-};
-// 打分任务发布
-export const publishScoreTask = ({ subjectId, questionId, taskList }) => {
-  return $post(
-    `/api/marksubjects/${subjectId}/publishScore`,
-    {
-      questionId,
-      taskList
-    },
-    "json"
-  );
-};
-// grading-standard-paper-manage
-export const cancelStandardPaper = paperIds => {
-  return $patch(`/api/papers/batch/cancelSample`, { paperIds }, "json");
-};
-
-// grading-detail ------------------------->
-// grading-analysis
-export const gradingStatData = datas => {
-  return $get("/api/marktasks/levelStatDetail", datas);
-};
-// level relate
-export const workLevelList = workId => {
-  return $get(`/api/admin/works/${workId}/levels`);
-};
-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 markerLevelStatData = (userId, questionId) => {
-  return $get(`/api/markers/${userId}/stat/levels`, { questionId });
-};
-export const markerLevelTotalStatData = (userId, questionId) => {
-  return $get(`/api/markers/${userId}/stat/totalLevels`, { 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 paperManualScoreList = datas => {
-  // ?questionId=64&workId=73&page=0&size=6
-  return $get("/api/papers/manualScore", 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);
-};
-// grading or scoring
-export const paperSelectLevelOrScore = (
-  taskId,
-  result,
-  stage,
-  manualScore = 0
-) => {
-  // stage => LEVEL or SCORE
-  return $patch(
-    `/api/marktasks/${taskId}`,
-    { stage, result, manualScore },
-    "json"
-  );
-};
-export const paperSelectLevelBatch = (taskIds, result, stage) => {
-  return $patch(`/api/marktasks/batch`, { taskIds, result, stage }, "json");
-};
-export const paperTaskPass = taskId => {
-  return $post(`/api/marktasks/${taskId}/skip`, {});
-};
-export const markTask = ({ markTaskId, isMark }) => {
-  return $post(`/api/marktasks/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) => {
-  if (type === "task") {
-    return $get(`/api/papers/search/byTaskSecretNumber`, {
-      sn: code,
-      questionId
-    });
-  } else {
-    const paramName = type === "examNumber" ? "examNumber" : "sn";
-    return $get(`/api/papers/one`, { [paramName]: code, questionId });
-  }
-};
-// 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 markerManualScorePaperList = datas => {
-  // ?markerId=49&workId=22&questionId=10&size=6&page=0
-  return $get(`/api/marktasks/manualScore`, 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`);
-};
+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");
+};
+
+// org-manage
+export const orgList = datas => {
+  return $get("/api/admin/organization", datas);
+};
+export const orgDetail = organizationId => {
+  return $get(`/api/admin/organization/${organizationId}`);
+};
+export const createOrg = datas => {
+  return $post(`/api/admin/organization`, datas, "json");
+};
+export const updateOrgUser = datas => {
+  return $put(`/api/admin/organization`, datas, "json");
+};
+export const enableOrgUser = userId => {
+  return $post(`/api/admin/organization/${userId}`, {});
+};
+export const deleteOrg = orgId => {
+  return $del(`/api/admin/organization/${orgId}`);
+};
+
+// 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 }) => {
+  return $post(`/api/papers/mark_paper`, { paperId, isMark });
+};
+
+// 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 absentStudentSubject = datas => {
+  return $post(`/api/students/missing`, datas);
+};
+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 = workId => {
+  return $get("/api/param/getParam", { workId });
+};
+export const updateCollectParams = datas => {
+  return $post("/api/param/collect", datas);
+};
+
+// grading-set -------------------------->
+// grading-level-set
+// TO workDetail and updateWork
+
+// grading-rule-set
+export const updateLevelParams = datas => {
+  return $post("/api/param/level", datas);
+};
+// 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);
+};
+
+// 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`);
+};
+
+// 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}`);
+};
+export const enableGradingUser = ({ userId, enable }) => {
+  return $post(`/api/admin/users/enable`, { userId, enable });
+};
+// 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 markUserList = ({ workId, subjectId }) => {
+  return $get("/api/markers", { workId, subject: subjectId });
+};
+// grading-progress
+export const gradingProgressDetail = ({ workId, subject }) => {
+  return $get("/api/markers/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 gotoScoreStep = subjectId => {
+  return $patch(`/api/marksubjects/${subjectId}`, {}, "json");
+};
+// 打分任务发布
+export const publishScoreTask = ({ subjectId, questionId, taskList }) => {
+  return $post(
+    `/api/marksubjects/${subjectId}/publishScore`,
+    {
+      questionId,
+      taskList
+    },
+    "json"
+  );
+};
+// grading-standard-paper-manage
+export const cancelStandardPaper = paperIds => {
+  return $patch(`/api/papers/batch/cancelSample`, { paperIds }, "json");
+};
+
+// grading-detail ------------------------->
+// grading-analysis
+export const gradingStatData = datas => {
+  return $get("/api/marktasks/levelStatDetail", datas);
+};
+// level relate
+export const workLevelList = workId => {
+  return $get(`/api/admin/works/${workId}/levels`);
+};
+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 markerLevelStatData = (userId, questionId) => {
+  return $get(`/api/markers/${userId}/stat/levels`, { questionId });
+};
+export const markerLevelTotalStatData = (userId, questionId) => {
+  return $get(`/api/markers/${userId}/stat/totalLevels`, { 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 paperManualScoreList = datas => {
+  // ?questionId=64&workId=73&page=0&size=6
+  return $get("/api/papers/manualScore", 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);
+};
+// grading or scoring
+export const paperSelectLevelOrScore = (
+  taskId,
+  result,
+  stage,
+  manualScore = 0
+) => {
+  // stage => LEVEL or SCORE
+  return $patch(
+    `/api/marktasks/${taskId}`,
+    { stage, result, manualScore },
+    "json"
+  );
+};
+export const paperSelectLevelBatch = (taskIds, result, stage) => {
+  return $patch(`/api/marktasks/batch`, { taskIds, result, stage }, "json");
+};
+export const paperTaskPass = taskId => {
+  return $post(`/api/marktasks/${taskId}/skip`, {});
+};
+export const markTask = ({ markTaskId, isMark }) => {
+  return $post(`/api/marktasks/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) => {
+  if (type === "task") {
+    return $get(`/api/papers/search/byTaskSecretNumber`, {
+      sn: code,
+      questionId
+    });
+  } else {
+    const paramName = type === "examNumber" ? "examNumber" : "sn";
+    return $get(`/api/papers/one`, { [paramName]: code, questionId });
+  }
+};
+// 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 markerManualScorePaperList = datas => {
+  // ?markerId=49&workId=22&questionId=10&size=6&page=0
+  return $get(`/api/marktasks/manualScore`, 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`);
+};

+ 821 - 780
src/assets/styles/marker.less

@@ -1,780 +1,821 @@
-.marker-grading {
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  z-index: auto;
-  color: @color-text;
-}
-// marker-header
-.marker-header {
-  position: fixed;
-  height: 40px;
-  padding: 5px 0;
-  top: 0;
-  left: 0;
-  width: 100%;
-  z-index: 9;
-  background-color: @color-background-light;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  line-height: 30px;
-
-  .header-part {
-    display: inline-block;
-    vertical-align: top;
-    padding: 0 15px;
-    margin-left: 10px;
-    background: @color-background;
-    border-radius: 5px;
-    cursor: pointer;
-    &:hover {
-      background-color: shade(@color-background, 20%);
-      color: @color-text-act;
-    }
-  }
-  .header-page {
-    .page-total {
-      display: inline-block;
-      vertical-align: middle;
-      margin: 0 5px;
-    }
-
-    .page-item {
-      display: inline-block;
-      vertical-align: middle;
-      margin: 0 2px;
-      min-width: 24px;
-      height: 24px;
-      line-height: 24px;
-      text-align: center;
-      background-color: @color-background;
-      border-radius: 2px;
-      cursor: pointer;
-      &:hover {
-        background-color: shade(@color-background, 20%);
-      }
-    }
-    .page-cpage {
-      padding: 0 5px;
-      span {
-        margin: 0 1px;
-      }
-    }
-    .page-size {
-      padding: 0 10px;
-    }
-  }
-  .header-step {
-    color: @color-text-act;
-  }
-  .header-selection {
-    padding: 0;
-    background-color: transparent;
-
-    &:hover {
-      background-color: transparent;
-    }
-
-    .image-checkbox {
-      display: inline-block;
-      vertical-align: middle;
-      height: 20px;
-      width: 20px;
-      margin-right: 2px;
-      border-radius: 5px;
-      background-color: @color-background;
-      color: @color-text-act;
-      font-size: 14px;
-      text-align: center;
-      line-height: 20px;
-      cursor: pointer;
-
-      &:hover,
-      &.image-selected {
-        box-shadow: 0 0 3px inset @color-background-light;
-      }
-    }
-  }
-  .header-history {
-    margin-right: 10px;
-  }
-  .header-user {
-    display: inline-block;
-    vertical-align: top;
-    width: 280px;
-    border-left: 1px solid @color-background;
-    margin: -5px 0;
-    padding: 5px 10px;
-
-    .ivu-dropdown {
-      display: block;
-    }
-
-    .user-name {
-      background: @color-background;
-      border-radius: 15px;
-      padding: 0 15px;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      cursor: pointer;
-      > i {
-        color: #bec3d1;
-        &:last-child {
-          display: block;
-          float: right;
-          margin-top: 8px;
-        }
-      }
-      &:hover {
-        background-color: shade(@color-background, 20%);
-        color: @color-text-act;
-      }
-    }
-  }
-}
-.header-step-dropdown {
-  .header-step-item {
-    > i {
-      color: @color-text-act;
-      &:last-child {
-        color: @color-text;
-      }
-    }
-  }
-}
-// marker-page
-.marker-page {
-  &-set {
-    > * {
-      display: inline-block;
-      vertical-align: middle;
-    }
-    .ivu-input-number {
-      width: 80px;
-      min-width: 0;
-      border-color: @color-text;
-      background-color: @color-text-act;
-      input {
-        box-shadow: none;
-        background-color: @color-text-act;
-      }
-    }
-    > span:first-child {
-      width: 80px;
-      text-align: right;
-    }
-  }
-  &-btn {
-    height: 24px;
-    line-height: 24px;
-    padding: 0 10px;
-    background-color: @color-background-light;
-    border-radius: 5px;
-    margin-left: 5px;
-    cursor: pointer;
-
-    &:hover {
-      background-color: @color-act1;
-      color: @color-text-act;
-    }
-  }
-}
-
-// .marker-body
-.marker-body {
-  position: absolute;
-  left: 0;
-  top: 40px;
-  right: 280px;
-  bottom: 0;
-  overflow: auto;
-  padding: 5px;
-  background: @color-background;
-  z-index: 7;
-}
-.marker-image-list {
-  height: 100%;
-
-  .marker-image-item {
-    display: inline-block;
-    vertical-align: top;
-    width: 25%;
-    height: 50%;
-    padding: 5px;
-    font-size: 0;
-
-    &-act {
-      .marker-image-content::before {
-        content: "";
-        display: block;
-        position: absolute;
-        width: 20px;
-        height: 20px;
-        top: 0;
-        right: 0;
-        border-top-right-radius: 5px;
-        border-bottom-left-radius: 20px;
-        background-color: @color-act1;
-      }
-    }
-  }
-  .marker-image-content {
-    position: relative;
-    background-color: @color-background-light;
-    height: 100%;
-    padding: 10px;
-    border-radius: 5px;
-  }
-
-  &-1 {
-    .marker-image-item {
-      width: 100%;
-      height: 100%;
-    }
-  }
-  &-2 {
-    .marker-image-item {
-      width: 50%;
-      height: 100%;
-    }
-  }
-  &-3 {
-    .marker-image-item {
-      width: 33.33%;
-      height: 100%;
-    }
-  }
-  &-4 {
-    .marker-image-item {
-      width: 50%;
-      height: 50%;
-    }
-  }
-  &-6 {
-    .marker-image-item {
-      width: 33.33%;
-      height: 50%;
-    }
-  }
-  &-8 {
-    .marker-image-item {
-      width: 25%;
-      height: 50%;
-    }
-  }
-  &-9 {
-    .marker-image-item {
-      width: 33.33%;
-      height: 33.33%;
-    }
-  }
-  &-10 {
-    .marker-image-item {
-      width: 20%;
-      height: 50%;
-    }
-  }
-  &-12 {
-    .marker-image-item {
-      width: 25%;
-      height: 33.33%;
-    }
-  }
-  &-15 {
-    .marker-image-item {
-      width: 20%;
-      height: 33.33%;
-    }
-  }
-  &-16 {
-    .marker-image-item {
-      width: 25%;
-      height: 25%;
-    }
-  }
-  &-20 {
-    .marker-image-item {
-      width: 20%;
-      height: 25%;
-    }
-  }
-  &-24 {
-    .marker-image-item {
-      width: 16.66%;
-      height: 25%;
-    }
-  }
-  &-25 {
-    .marker-image-item {
-      width: 20%;
-      height: 20%;
-    }
-  }
-}
-.marker-image-view {
-  position: relative;
-  height: 100%;
-  font-size: 14px;
-
-  .image-view-contain {
-    position: absolute;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 36px;
-  }
-  .image-view-footer {
-    position: absolute;
-    width: 100%;
-    bottom: 0;
-    left: 0;
-    height: 26px;
-    line-height: 26px;
-    padding: 0;
-    display: flex;
-    justify-content: space-between;
-  }
-  .image-info {
-    white-space: nowrap;
-    overflow: hidden;
-    > div {
-      display: inline-block;
-      vertical-align: top;
-    }
-  }
-  .image-sample {
-    height: 26px;
-    width: 26px;
-    border-radius: 5px;
-    background-color: @color-act1;
-    color: @color-text;
-    font-size: 16px;
-    text-align: center;
-    line-height: 26px;
-  }
-  .image-checkbox {
-    height: 26px;
-    width: 26px;
-
-    border-radius: 5px;
-    background-color: @color-background;
-    color: @color-text-act;
-    font-size: 20px;
-    text-align: center;
-    line-height: 26px;
-    cursor: pointer;
-
-    &:hover,
-    &.image-selected {
-      box-shadow: 0 0 3px inset @color-background-light;
-    }
-  }
-  .image-level {
-    height: 26px;
-    min-width: 26px;
-    margin-right: 5px;
-    border-radius: 5px;
-    background-color: @color-background;
-    font-size: 18px;
-    text-align: center;
-  }
-  .image-title {
-    height: 26px;
-    padding-left: 5px;
-    cursor: pointer;
-    &:hover {
-      color: @color-text-act;
-    }
-  }
-  .image-action {
-    .ivu-btn {
-      width: 26px;
-      height: 26px;
-      padding: 0;
-      font-size: 12px;
-      border-radius: 50%;
-      border: 0;
-      .ivu-icon {
-        color: @color-text-act;
-      }
-    }
-
-    &-li {
-      display: inline-block;
-      vertical-align: top;
-      margin-left: 5px;
-      height: 26px;
-      font-size: 26px;
-      cursor: pointer;
-
-      &:hover {
-        color: @color-text-act;
-      }
-    }
-    .mark-act {
-      color: @warning-color;
-    }
-  }
-}
-.marker-image-none {
-  padding-top: 150px;
-  font-size: 16px;
-  text-align: center;
-  color: @color-text;
-}
-
-// marker-action
-.marker-action {
-  position: fixed;
-  width: 280px;
-  right: 0;
-  top: 0;
-  height: 100%;
-  z-index: 8;
-  padding: 60px 10px 20px;
-  background-color: @color-background-light;
-  color: @color-text;
-  overflow-y: auto;
-  overflow-x: hidden;
-
-  &-fullscreen {
-    z-index: 2000;
-  }
-
-  .action-search {
-    border-top: 1px dashed @color-text;
-  }
-  .action-paper-state {
-    color: @color-text;
-    .paper-state-cont {
-      background: @color-background;
-    }
-  }
-
-  .action-paper-info {
-    color: @color-text;
-    span:last-child {
-      color: @color-text-act;
-    }
-  }
-  .action-grade-change {
-    background-color: @color-background;
-    color: @color-text;
-  }
-  .action-grade-info {
-    background-color: @color-act1;
-    color: @color-text;
-    &-title {
-      color: @color-text;
-    }
-    .grade-info-name {
-      color: @color-text-act;
-    }
-  }
-  .action-grade-item {
-    color: @color-text;
-
-    &-content {
-      background: @color-background;
-
-      &:hover {
-        background-color: @color-act1;
-        color: @color-text-act;
-      }
-    }
-  }
-  .action-item-content-disabled {
-    background: shade(@color-background-light, 30%) !important;
-    color: @color-background-light!important;
-  }
-  .action-grade-history {
-    .grade-history-item {
-      background-color: @color-background;
-      color: @color-text;
-
-      p:last-child {
-        background-color: @color-act1;
-        color: @color-text-act;
-      }
-    }
-  }
-  .action-grade-pass {
-    background: @color-background;
-    color: @color-text;
-
-    &:hover {
-      background-color: shade(@color-background, 20%);
-    }
-  }
-
-  // marking
-  .action-mark-item {
-    color: @color-text;
-
-    &-content {
-      background: @color-background;
-
-      &:hover {
-        background-color: @color-act1;
-        color: @color-text-act;
-      }
-    }
-  }
-
-  // iview-ui
-  .ivu-btn-primary {
-    color: @color-text-act;
-    background-color: @color-act1;
-    border-color: @color-act1;
-
-    &:hover {
-      background-color: shade(@color-act1, 10%);
-      border-color: shade(@color-act1, 10%);
-    }
-  }
-  .ivu-input {
-    background-color: @color-background!important;
-    border-color: @color-background;
-    color: @color-text;
-    box-shadow: none !important;
-  }
-  .ivu-select-selection {
-    background-color: @color-background;
-    color: @color-text;
-    border-color: @color-background;
-  }
-  .ivu-select-dropdown {
-    background-color: @color-background;
-    color: @color-text;
-
-    .ivu-select-item {
-      color: @color-text;
-      border-top: 1px solid @color-background-light;
-      &:hover,
-      &-focus {
-        background-color: @color-act1;
-      }
-    }
-  }
-  .ivu-form .ivu-form-item-label {
-    color: @color-text;
-  }
-}
-
-// marker-history
-.marker-history {
-  .image-view-footer {
-    color: @color-text;
-  }
-  .image-action-name {
-    height: 26px;
-    padding-left: 5px;
-  }
-  .ivu-modal {
-    width: 100% !important;
-    top: 0 !important;
-  }
-}
-.history-image-list {
-  height: 360px;
-
-  .marker-image-item {
-    width: 20%;
-    height: 100%;
-  }
-}
-// marker-standard
-.marker-standard {
-  .level-list {
-    text-align: center;
-    margin-bottom: 30px;
-  }
-  .level-item {
-    display: inline-block;
-    vertical-align: top;
-    width: 40px;
-    height: 26px;
-    line-height: 26px;
-    padding: 0 5px;
-    margin: 0 10px;
-    border-radius: 5px;
-    background-color: @color-background-light;
-    color: @color-text;
-    text-align: center;
-    cursor: pointer;
-    &:hover,
-    &-act {
-      color: @color-text-act;
-      background-color: @color-act1;
-    }
-  }
-  .standard-image-list {
-    height: auto;
-  }
-
-  .image-view-footer {
-    color: @color-text;
-  }
-  .marker-image-item {
-    width: 20%;
-    height: 300px;
-  }
-  .standard-image-none {
-    padding-top: 150px;
-    font-size: 16px;
-    text-align: center;
-    color: @color-text;
-  }
-}
-.change-standard {
-  .level-list {
-    margin-bottom: 50px;
-  }
-  .level-item {
-    display: inline-block;
-    vertical-align: top;
-    margin: 5px;
-    height: 30px;
-    line-height: 30px;
-    width: 40px;
-    text-align: center;
-    border-radius: 5px;
-    color: @color-text;
-    background-color: @color-background-light;
-    border-color: @color-background-light;
-    cursor: pointer;
-
-    &:hover,
-    &-act {
-      background-color: @color-act1;
-      border-color: @color-act1;
-    }
-
-    &-disabled {
-      cursor: not-allowed;
-      color: @color-text;
-      background-color: shade(@color-background-light, 20%) !important;
-    }
-  }
-}
-// marker-statistics
-.marker-statistics {
-  color: @color-text;
-  &-chart {
-    > h3 {
-      font-size: 16px;
-    }
-    .chart-box {
-      background-color: @color-background;
-    }
-  }
-}
-
-// leader-progress
-.leader-progress {
-  .ivu-modal {
-    width: 600px !important;
-  }
-  .progress-line {
-    color: @color-text;
-    background-color: tint(@color-background, 5%);
-
-    .progress-rate {
-      background-color: @color-act1;
-      color: @color-text-act;
-    }
-  }
-}
-// modify-leader-grading
-.marker-modal {
-  .leader-grading {
-    color: @color-text;
-    .leader-level {
-      h3 {
-        background-color: @color-background-light;
-        color: @color-text-act;
-      }
-    }
-    .leader-aciton {
-      color: @color-text;
-    }
-    .leader-markers {
-      background-color: @color-background-light;
-    }
-  }
-  .ivu-btn-primary {
-    .marker-btn-primary;
-  }
-  .ivu-radio-inner:after,
-  .ivu-checkbox-checked .ivu-checkbox-inner {
-    background-color: @color-act1;
-  }
-}
-
-// custom iview ui ----------------->
-// marker-modal
-.marker-modal {
-  color: @color-text;
-  .ivu-modal-mask {
-    background-color: rgba(55, 55, 55, 0.7);
-  }
-
-  .ivu-modal-content {
-    background-color: @color-background;
-    border-radius: 0;
-  }
-  .ivu-modal-header {
-    border-color: @color-background-light;
-    &-inner {
-      color: @color-text;
-      text-align: left;
-    }
-  }
-  .ivu-modal-body {
-    padding: 15px;
-  }
-}
-// marker-dropdown
-.marker-dropdown {
-  background-color: @color-background;
-  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
-
-  .ivu-dropdown-item {
-    margin-top: 0;
-    color: @color-text;
-    border-top: 1px solid @color-background-light;
-    &:hover {
-      background-color: @color-act1;
-    }
-  }
-}
-// marker-popper
-.marker-popper {
-  &.ivu-poptip-popper {
-    .ivu-poptip-arrow {
-      border-bottom-color: @color-act1;
-      &::after {
-        border-bottom-color: @color-act1;
-      }
-    }
-  }
-  .ivu-poptip-inner {
-    background-color: @color-background;
-    color: @color-text;
-
-    box-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
-  }
-}
-// btn
-.marker-btn-primary {
-  color: @color-text-act;
-  background-color: @color-act1;
-  border-color: @color-act1;
-
-  &:hover {
-    background-color: shade(@color-act1, 10%);
-    border-color: shade(@color-act1, 10%);
-  }
-}
+.marker-grading {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  z-index: auto;
+  color: @color-text;
+}
+// marker-header
+.marker-header {
+  position: fixed;
+  height: 40px;
+  padding: 5px 0;
+  top: 0;
+  left: 0;
+  width: 100%;
+  z-index: 9;
+  background-color: @color-background-light;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  line-height: 30px;
+
+  .header-part {
+    display: inline-block;
+    vertical-align: top;
+    padding: 0 15px;
+    margin-left: 10px;
+    background: @color-background;
+    border-radius: 5px;
+    cursor: pointer;
+    &:hover {
+      background-color: shade(@color-background, 20%);
+      color: @color-text-act;
+    }
+  }
+  .header-page {
+    .page-total {
+      display: inline-block;
+      vertical-align: middle;
+      margin: 0 5px;
+    }
+
+    .page-item {
+      display: inline-block;
+      vertical-align: middle;
+      margin: 0 2px;
+      min-width: 24px;
+      height: 24px;
+      line-height: 24px;
+      text-align: center;
+      background-color: @color-background;
+      border-radius: 2px;
+      cursor: pointer;
+      &:hover {
+        background-color: shade(@color-background, 20%);
+      }
+    }
+    .page-cpage {
+      padding: 0 5px;
+      span {
+        margin: 0 1px;
+      }
+    }
+    .page-size {
+      padding: 0 10px;
+    }
+  }
+  .header-step {
+    color: @color-text-act;
+  }
+  .header-selection {
+    padding: 0;
+    background-color: transparent;
+
+    &:hover {
+      background-color: transparent;
+    }
+
+    .image-checkbox {
+      display: inline-block;
+      vertical-align: middle;
+      height: 20px;
+      width: 20px;
+      margin-right: 2px;
+      border-radius: 5px;
+      background-color: @color-background;
+      color: @color-text-act;
+      font-size: 14px;
+      text-align: center;
+      line-height: 20px;
+      cursor: pointer;
+
+      &:hover,
+      &.image-selected {
+        box-shadow: 0 0 3px inset @color-background-light;
+      }
+    }
+  }
+  .header-history {
+    margin-right: 10px;
+  }
+  .header-user {
+    display: inline-block;
+    vertical-align: top;
+    width: 280px;
+    border-left: 1px solid @color-background;
+    margin: -5px 0;
+    padding: 5px 10px;
+
+    .ivu-dropdown {
+      display: block;
+    }
+
+    .user-name {
+      background: @color-background;
+      border-radius: 15px;
+      padding: 0 15px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      cursor: pointer;
+      > i {
+        color: #bec3d1;
+        &:last-child {
+          display: block;
+          float: right;
+          margin-top: 8px;
+        }
+      }
+      &:hover {
+        background-color: shade(@color-background, 20%);
+        color: @color-text-act;
+      }
+    }
+  }
+}
+.header-step-dropdown {
+  .header-step-item {
+    > i {
+      color: @color-text-act;
+      &:last-child {
+        color: @color-text;
+      }
+    }
+  }
+}
+.header-filter-body {
+  .filter-part {
+    padding: 15px 0 7px;
+
+    &:not(:last-child) {
+      border-bottom: 1px dashed @color-text;
+    }
+
+    &-title {
+      line-height: 1;
+      margin-bottom: 10px;
+    }
+  }
+
+  .filter-select {
+    display: inline-block;
+    vertical-align: top;
+    width: 100px;
+    min-width: auto;
+    margin-right: 10px;
+    margin-bottom: 8px;
+  }
+  .filter-input {
+    display: inline-block;
+    vertical-align: top;
+    width: 150px;
+    margin-right: 10px;
+    margin-bottom: 8px;
+  }
+  .filter-btn {
+    display: inline-block;
+    vertical-align: top;
+    width: 60px;
+    height: 30px;
+  }
+  .filter-label {
+    display: inline-block;
+    vertical-align: top;
+    line-height: 32px;
+  }
+}
+// marker-page
+.marker-page {
+  &-set {
+    > * {
+      display: inline-block;
+      vertical-align: middle;
+    }
+    .ivu-input-number {
+      width: 80px;
+      min-width: 0;
+      border-color: @color-text;
+      background-color: @color-text-act;
+      input {
+        box-shadow: none;
+        background-color: @color-text-act;
+      }
+    }
+    > span:first-child {
+      width: 80px;
+      text-align: right;
+    }
+  }
+  &-btn {
+    height: 24px;
+    line-height: 24px;
+    padding: 0 10px;
+    background-color: @color-background-light;
+    border-radius: 5px;
+    margin-left: 5px;
+    cursor: pointer;
+
+    &:hover {
+      background-color: @color-act1;
+      color: @color-text-act;
+    }
+  }
+}
+
+// .marker-body
+.marker-body {
+  position: absolute;
+  left: 0;
+  top: 40px;
+  right: 280px;
+  bottom: 0;
+  overflow: auto;
+  padding: 5px;
+  background: @color-background;
+  z-index: 7;
+}
+.marker-image-list {
+  height: 100%;
+
+  .marker-image-item {
+    display: inline-block;
+    vertical-align: top;
+    width: 25%;
+    height: 50%;
+    padding: 5px;
+    font-size: 0;
+
+    &-act {
+      .marker-image-content::before {
+        content: "";
+        display: block;
+        position: absolute;
+        width: 20px;
+        height: 20px;
+        top: 0;
+        right: 0;
+        border-top-right-radius: 5px;
+        border-bottom-left-radius: 20px;
+        background-color: @color-act1;
+      }
+    }
+  }
+  .marker-image-content {
+    position: relative;
+    background-color: @color-background-light;
+    height: 100%;
+    padding: 10px;
+    border-radius: 5px;
+  }
+
+  &-1 {
+    .marker-image-item {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  &-2 {
+    .marker-image-item {
+      width: 50%;
+      height: 100%;
+    }
+  }
+  &-3 {
+    .marker-image-item {
+      width: 33.33%;
+      height: 100%;
+    }
+  }
+  &-4 {
+    .marker-image-item {
+      width: 50%;
+      height: 50%;
+    }
+  }
+  &-6 {
+    .marker-image-item {
+      width: 33.33%;
+      height: 50%;
+    }
+  }
+  &-8 {
+    .marker-image-item {
+      width: 25%;
+      height: 50%;
+    }
+  }
+  &-9 {
+    .marker-image-item {
+      width: 33.33%;
+      height: 33.33%;
+    }
+  }
+  &-10 {
+    .marker-image-item {
+      width: 20%;
+      height: 50%;
+    }
+  }
+  &-12 {
+    .marker-image-item {
+      width: 25%;
+      height: 33.33%;
+    }
+  }
+  &-15 {
+    .marker-image-item {
+      width: 20%;
+      height: 33.33%;
+    }
+  }
+  &-16 {
+    .marker-image-item {
+      width: 25%;
+      height: 25%;
+    }
+  }
+  &-20 {
+    .marker-image-item {
+      width: 20%;
+      height: 25%;
+    }
+  }
+  &-24 {
+    .marker-image-item {
+      width: 16.66%;
+      height: 25%;
+    }
+  }
+  &-25 {
+    .marker-image-item {
+      width: 20%;
+      height: 20%;
+    }
+  }
+}
+.marker-image-view {
+  position: relative;
+  height: 100%;
+  font-size: 14px;
+
+  .image-view-contain {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 36px;
+  }
+  .image-view-footer {
+    position: absolute;
+    width: 100%;
+    bottom: 0;
+    left: 0;
+    height: 26px;
+    line-height: 26px;
+    padding: 0;
+    display: flex;
+    justify-content: space-between;
+  }
+  .image-info {
+    white-space: nowrap;
+    overflow: hidden;
+    > div {
+      display: inline-block;
+      vertical-align: top;
+    }
+  }
+  .image-sample {
+    height: 26px;
+    width: 26px;
+    border-radius: 5px;
+    background-color: @color-act1;
+    color: @color-text;
+    font-size: 16px;
+    text-align: center;
+    line-height: 26px;
+  }
+  .image-checkbox {
+    height: 26px;
+    width: 26px;
+
+    border-radius: 5px;
+    background-color: @color-background;
+    color: @color-text-act;
+    font-size: 20px;
+    text-align: center;
+    line-height: 26px;
+    cursor: pointer;
+
+    &:hover,
+    &.image-selected {
+      box-shadow: 0 0 3px inset @color-background-light;
+    }
+  }
+  .image-level {
+    height: 26px;
+    min-width: 26px;
+    margin-right: 5px;
+    border-radius: 5px;
+    background-color: @color-background;
+    font-size: 18px;
+    text-align: center;
+  }
+  .image-title {
+    height: 26px;
+    padding-left: 5px;
+    cursor: pointer;
+    &:hover {
+      color: @color-text-act;
+    }
+  }
+  .image-action {
+    .ivu-btn {
+      width: 26px;
+      height: 26px;
+      padding: 0;
+      font-size: 12px;
+      border-radius: 50%;
+      border: 0;
+      .ivu-icon {
+        color: @color-text-act;
+      }
+    }
+
+    &-li {
+      display: inline-block;
+      vertical-align: top;
+      margin-left: 5px;
+      height: 26px;
+      font-size: 26px;
+      cursor: pointer;
+
+      &:hover {
+        color: @color-text-act;
+      }
+    }
+    .mark-act {
+      color: @warning-color;
+    }
+  }
+}
+.marker-image-none {
+  padding-top: 150px;
+  font-size: 16px;
+  text-align: center;
+  color: @color-text;
+}
+
+// marker-action
+.marker-action {
+  position: fixed;
+  width: 280px;
+  right: 0;
+  top: 0;
+  height: 100%;
+  z-index: 8;
+  padding: 60px 10px 20px;
+  background-color: @color-background-light;
+  color: @color-text;
+  overflow-y: auto;
+  overflow-x: hidden;
+
+  &-fullscreen {
+    z-index: 2000;
+  }
+
+  .action-search {
+    border-top: 1px dashed @color-text;
+  }
+  .action-paper-state {
+    color: @color-text;
+    .paper-state-cont {
+      background: @color-background;
+    }
+  }
+
+  .action-paper-info {
+    color: @color-text;
+    span:last-child {
+      color: @color-text-act;
+    }
+  }
+  .action-grade-change {
+    background-color: @color-background;
+    color: @color-text;
+  }
+  .action-grade-info {
+    background-color: @color-act1;
+    color: @color-text;
+    &-title {
+      color: @color-text;
+    }
+    .grade-info-name {
+      color: @color-text-act;
+    }
+  }
+  .action-grade-item {
+    color: @color-text;
+
+    &-content {
+      background: @color-background;
+
+      &:hover {
+        background-color: @color-act1;
+        color: @color-text-act;
+      }
+    }
+  }
+  .action-item-content-disabled {
+    background: shade(@color-background-light, 30%) !important;
+    color: @color-background-light!important;
+  }
+  .action-grade-history {
+    .grade-history-item {
+      background-color: @color-background;
+      color: @color-text;
+
+      p:last-child {
+        background-color: @color-act1;
+        color: @color-text-act;
+      }
+    }
+  }
+  .action-grade-pass {
+    background: @color-background;
+    color: @color-text;
+
+    &:hover {
+      background-color: shade(@color-background, 20%);
+    }
+  }
+
+  // marking
+  .action-mark-item {
+    color: @color-text;
+
+    &-content {
+      background: @color-background;
+
+      &:hover {
+        background-color: @color-act1;
+        color: @color-text-act;
+      }
+    }
+  }
+
+  // iview-ui
+  .ivu-btn-primary {
+    color: @color-text-act;
+    background-color: @color-act1;
+    border-color: @color-act1;
+
+    &:hover {
+      background-color: shade(@color-act1, 10%);
+      border-color: shade(@color-act1, 10%);
+    }
+  }
+  .ivu-input {
+    background-color: @color-background!important;
+    border-color: @color-background;
+    color: @color-text;
+    box-shadow: none !important;
+  }
+  .ivu-select-selection {
+    background-color: @color-background;
+    color: @color-text;
+    border-color: @color-background;
+  }
+  .ivu-select-dropdown {
+    background-color: @color-background;
+    color: @color-text;
+
+    .ivu-select-item {
+      color: @color-text;
+      border-top: 1px solid @color-background-light;
+      &:hover,
+      &-focus {
+        background-color: @color-act1;
+      }
+    }
+  }
+  .ivu-form .ivu-form-item-label {
+    color: @color-text;
+  }
+}
+
+// marker-history
+.marker-history {
+  .image-view-footer {
+    color: @color-text;
+  }
+  .image-action-name {
+    height: 26px;
+    padding-left: 5px;
+  }
+  .ivu-modal {
+    width: 100% !important;
+    top: 0 !important;
+  }
+}
+.history-image-list {
+  height: 360px;
+
+  .marker-image-item {
+    width: 20%;
+    height: 100%;
+  }
+}
+// marker-standard
+.marker-standard {
+  .level-list {
+    text-align: center;
+    margin-bottom: 30px;
+  }
+  .level-item {
+    display: inline-block;
+    vertical-align: top;
+    width: 40px;
+    height: 26px;
+    line-height: 26px;
+    padding: 0 5px;
+    margin: 0 10px;
+    border-radius: 5px;
+    background-color: @color-background-light;
+    color: @color-text;
+    text-align: center;
+    cursor: pointer;
+    &:hover,
+    &-act {
+      color: @color-text-act;
+      background-color: @color-act1;
+    }
+  }
+  .standard-image-list {
+    height: auto;
+  }
+
+  .image-view-footer {
+    color: @color-text;
+  }
+  .marker-image-item {
+    width: 20%;
+    height: 300px;
+  }
+  .standard-image-none {
+    padding-top: 150px;
+    font-size: 16px;
+    text-align: center;
+    color: @color-text;
+  }
+}
+.change-standard {
+  .level-list {
+    margin-bottom: 50px;
+  }
+  .level-item {
+    display: inline-block;
+    vertical-align: top;
+    margin: 5px;
+    height: 30px;
+    line-height: 30px;
+    width: 40px;
+    text-align: center;
+    border-radius: 5px;
+    color: @color-text;
+    background-color: @color-background-light;
+    border-color: @color-background-light;
+    cursor: pointer;
+
+    &:hover,
+    &-act {
+      background-color: @color-act1;
+      border-color: @color-act1;
+    }
+
+    &-disabled {
+      cursor: not-allowed;
+      color: @color-text;
+      background-color: shade(@color-background-light, 20%) !important;
+    }
+  }
+}
+// marker-statistics
+.marker-statistics {
+  color: @color-text;
+  &-chart {
+    > h3 {
+      font-size: 16px;
+    }
+    .chart-box {
+      background-color: @color-background;
+    }
+  }
+}
+
+// leader-progress
+.leader-progress {
+  .ivu-modal {
+    width: 600px !important;
+  }
+  .progress-line {
+    color: @color-text;
+    background-color: tint(@color-background, 5%);
+
+    .progress-rate {
+      background-color: @color-act1;
+      color: @color-text-act;
+    }
+  }
+}
+// modify-leader-grading
+.marker-modal {
+  .leader-grading {
+    color: @color-text;
+    .leader-level {
+      h3 {
+        background-color: @color-background-light;
+        color: @color-text-act;
+      }
+    }
+    .leader-aciton {
+      color: @color-text;
+    }
+    .leader-markers {
+      background-color: @color-background-light;
+    }
+  }
+  .ivu-btn-primary {
+    .marker-btn-primary;
+  }
+  .ivu-radio-inner:after,
+  .ivu-checkbox-checked .ivu-checkbox-inner {
+    background-color: @color-act1;
+  }
+}
+
+// custom iview ui ----------------->
+// marker-modal
+.marker-modal {
+  color: @color-text;
+  .ivu-modal-mask {
+    background-color: rgba(55, 55, 55, 0.7);
+  }
+
+  .ivu-modal-content {
+    background-color: @color-background;
+    border-radius: 0;
+  }
+  .ivu-modal-header {
+    border-color: @color-background-light;
+    &-inner {
+      color: @color-text;
+      text-align: left;
+    }
+  }
+  .ivu-modal-body {
+    padding: 15px;
+  }
+}
+// marker-dropdown
+.marker-dropdown {
+  background-color: @color-background;
+  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
+
+  .ivu-dropdown-item {
+    margin-top: 0;
+    color: @color-text;
+    border-top: 1px solid @color-background-light;
+    &:hover {
+      background-color: @color-act1;
+    }
+  }
+}
+// marker-popper
+.marker-popper {
+  &.ivu-poptip-popper {
+    .ivu-poptip-arrow {
+      border-bottom-color: @color-act1;
+      &::after {
+        border-bottom-color: @color-act1;
+      }
+    }
+  }
+  .ivu-poptip-inner {
+    background-color: @color-background;
+    color: @color-text;
+
+    box-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
+  }
+}
+// btn
+.marker-btn-primary {
+  color: @color-text-act;
+  background-color: @color-act1;
+  border-color: @color-act1;
+
+  &:hover {
+    background-color: shade(@color-act1, 10%);
+    border-color: shade(@color-act1, 10%);
+  }
+}

+ 432 - 432
src/modules/grading/components/GradeAction.vue

@@ -1,432 +1,432 @@
-<template>
-  <div class="grade-action">
-    <!-- 头部信息 ------ -->
-    <!-- 试卷状态 -->
-    <!-- 状态:已评,待评,打回,仲裁 -->
-    <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 v-if="IS_ADMIN">
-        <span>试卷考号:</span><span>{{ curPaperOrTask.examNumber }}</span>
-      </p>
-      <p>
-        <span v-if="IS_MARKER">任务密号:</span>
-        <span v-else>试卷密号:</span>
-        <span>NO.{{ curPaperOrTask.sn }}</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 }
-          ]"
-          @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_MARKER && stepType === 'reject'"
-    >
-      <span>原分档档位:{{ curPaperOrTask.originLevel || "" }}</span>
-      <span
-        v-if="
-          paramsSet.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">
-      <span v-if="curPaperOrTask.rejected && curPaperOrTask.isRejectedByLeader"
-        >建议档位:</span
-      >
-      <span v-if="stepType === 'done' || stepType === 'sample'"
-        >已评档位:</span
-      >
-    </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-pass"
-      v-if="rights.gradeList && IS_MARKER"
-      @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 }}</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 } from "@/api";
-import { CODE_TYPE } from "@/constants/enumerate";
-// 三种情况:
-// 管理员(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,
-  gradeHis: false
-};
-
-export default {
-  name: "grade-action",
-  props: {
-    curPaperOrTask: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    levels: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    paramsSet: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      rights: {
-        ...initRights
-      },
-      roleRight: {
-        SUPER_ADMIN: {
-          done: ["search", "gradeHis", "gradeInfo"],
-          reject: ["search", "gradeInfo", "gradeHis"],
-          arbitrate: ["search", "gradeHis"]
-        },
-        ADMIN: {
-          done: ["search", "gradeHis", "gradeInfo"],
-          reject: ["search", "gradeInfo", "gradeHis"],
-          arbitrate: ["search", "gradeHis"]
-        },
-        MARK_LEADER: {
-          undo: ["search", "gradeList", "gradeInfo"],
-          done: ["search", "gradeList", "gradeHis", "gradeInfo"],
-          reject: ["search", "gradeList", "gradeInfo", "gradeHis"],
-          arbitrate: ["search", "gradeList", "gradeHis"]
-        },
-        MARKER: {
-          done: ["gradeList", "gradeInfo"],
-          undo: ["gradeList"],
-          reject: ["gradeList", "gradeInfo"]
-        },
-        STANDARD: ["gradeInfo"]
-      },
-      filter: {
-        codeType: "examNumber",
-        code: ""
-      },
-      codeTypes: [],
-      stepDict: {
-        undo: "待评",
-        done: "已评",
-        reject: "打回",
-        arbitrate: "待仲裁",
-        sample: "标准卷"
-      },
-      stepType: "",
-      stepLabel: "",
-      gradingHistory: [],
-      curLevel: {},
-      setT: null,
-      btnClicked: false,
-      // 科组长权限
-      markLeaderOnlyRight: null
-    };
-  },
-  computed: {
-    IS_ADMIN() {
-      return (
-        this.curUserRoleType === "ADMIN" ||
-        this.curUserRoleType === "SUPER_ADMIN"
-      );
-    },
-    IS_MARKER() {
-      return this.curUserRoleType === "MARKER";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    }
-  },
-  watch: {
-    curPaperOrTask(val) {
-      this.rebuildRight();
-    }
-  },
-  mounted() {
-    this.markLeaderOnlyRight = this.$ls.get("user", {
-      markLeaderOnlyRight: null
-    }).markLeaderOnlyRight;
-
-    this.codeTypes = Object.entries(CODE_TYPE)
-      .map(([key, val]) => {
-        return {
-          key,
-          val
-        };
-      })
-      .filter(item => this.IS_ADMIN || item.key !== "examNumber");
-    this.rebuildRight();
-  },
-  methods: {
-    getStepType() {
-      const info = this.curPaperOrTask;
-      if (info.sample) return "sample";
-      if (info.level) return "done";
-      if (info.arbitrated) return "arbitrate";
-      if (info.rejected) return "reject";
-      if (!info.rejected && !info.arbitrated && !info.level) return "undo";
-      return;
-    },
-    rebuildRight() {
-      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;
-    },
-    getCurLevel() {
-      const levelName = this.curPaperOrTask.rejected
-        ? this.curPaperOrTask.redoLevel
-        : this.curPaperOrTask.level;
-      if (levelName) {
-        this.curLevel = this.levels.find(item => item.name === levelName);
-      } else {
-        this.curLevel = {};
-      }
-    },
-    async getMarkHistory() {
-      // 只有科组长和超管才会展示评卷记录
-      const data = await markHistoryList(this.curPaperOrTask.id, "LEVEL");
-      this.gradingHistory = data.map(item => {
-        let level = item.result || "未评";
-        if (this.stepType === "reject" && !item.result) {
-          level = `${level}(${item.originLevel})`;
-        }
-        return {
-          id: item.id,
-          markerId: item.markerId,
-          name: item.marker,
-          loginName: item.loginName,
-          value: level
-        };
-      });
-    },
-    selectLevel(level) {
-      if (this.IS_MARKER && this.curPaperOrTask.level === level.name) return;
-      if (this.btnClicked) return;
-      this.btnClicked = true;
-
-      this.setT = setTimeout(() => {
-        this.btnClicked = false;
-      }, 500);
-
-      if (this.IS_MARK_LEADER) {
-        this.$emit(
-          "on-leader-level",
-          {
-            paperIds: this.curPaperOrTask.id + "",
-            curLevel: this.curPaperOrTask.level,
-            selectedLevel: level.name,
-            markLeaderOnlyRight: this.markLeaderOnlyRight
-          },
-          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);
-    }
-  },
-  beforeDestroy() {
-    if (this.setT) clearTimeout(this.setT);
-  }
-};
-</script>
+<template>
+  <div class="grade-action">
+    <!-- 头部信息 ------ -->
+    <!-- 试卷状态 -->
+    <!-- 状态:已评,待评,打回,仲裁 -->
+    <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 v-if="IS_ADMIN">
+        <span>试卷考号:</span><span>{{ curPaperOrTask.examNumber }}</span>
+      </p>
+      <p>
+        <span v-if="IS_MARKER">任务密号:</span>
+        <span v-else>试卷密号:</span>
+        <span>NO.{{ curPaperOrTask.sn }}</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 }
+          ]"
+          @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_MARKER && stepType === 'reject'"
+    >
+      <span>原分档档位:{{ curPaperOrTask.originLevel || "" }}</span>
+      <span
+        v-if="
+          paramsSet.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">
+      <span v-if="curPaperOrTask.rejected && curPaperOrTask.isRejectedByLeader"
+        >建议档位:</span
+      >
+      <span v-if="stepType === 'done' || stepType === 'sample'"
+        >已评档位:</span
+      >
+    </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-pass"
+      v-if="rights.gradeList && IS_MARKER"
+      @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 }}</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 } from "@/api";
+import { CODE_TYPE } from "@/constants/enumerate";
+// 三种情况:
+// 管理员(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,
+  gradeHis: false
+};
+
+export default {
+  name: "grade-action",
+  props: {
+    curPaperOrTask: {
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    levels: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    paramsSet: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      rights: {
+        ...initRights
+      },
+      roleRight: {
+        SUPER_ADMIN: {
+          done: ["search", "gradeHis", "gradeInfo"],
+          reject: ["search", "gradeInfo", "gradeHis"],
+          arbitrate: ["search", "gradeHis"]
+        },
+        ADMIN: {
+          done: ["search", "gradeHis", "gradeInfo"],
+          reject: ["search", "gradeInfo", "gradeHis"],
+          arbitrate: ["search", "gradeHis"]
+        },
+        MARK_LEADER: {
+          undo: ["gradeList", "gradeInfo"],
+          done: ["gradeList", "gradeHis", "gradeInfo"],
+          reject: ["gradeList", "gradeInfo", "gradeHis"],
+          arbitrate: ["gradeList", "gradeHis"]
+        },
+        MARKER: {
+          done: ["gradeList", "gradeInfo"],
+          undo: ["gradeList"],
+          reject: ["gradeList", "gradeInfo"]
+        },
+        STANDARD: ["gradeInfo"]
+      },
+      filter: {
+        codeType: "examNumber",
+        code: ""
+      },
+      codeTypes: [],
+      stepDict: {
+        undo: "待评",
+        done: "已评",
+        reject: "打回",
+        arbitrate: "待仲裁",
+        sample: "标准卷"
+      },
+      stepType: "",
+      stepLabel: "",
+      gradingHistory: [],
+      curLevel: {},
+      setT: null,
+      btnClicked: false,
+      // 科组长权限
+      markLeaderOnlyRight: null
+    };
+  },
+  computed: {
+    IS_ADMIN() {
+      return (
+        this.curUserRoleType === "ADMIN" ||
+        this.curUserRoleType === "SUPER_ADMIN"
+      );
+    },
+    IS_MARKER() {
+      return this.curUserRoleType === "MARKER";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    }
+  },
+  watch: {
+    curPaperOrTask(val) {
+      this.rebuildRight();
+    }
+  },
+  mounted() {
+    this.markLeaderOnlyRight = this.$ls.get("user", {
+      markLeaderOnlyRight: null
+    }).markLeaderOnlyRight;
+
+    this.codeTypes = Object.entries(CODE_TYPE)
+      .map(([key, val]) => {
+        return {
+          key,
+          val
+        };
+      })
+      .filter(item => this.IS_ADMIN || item.key !== "examNumber");
+    this.rebuildRight();
+  },
+  methods: {
+    getStepType() {
+      const info = this.curPaperOrTask;
+      if (info.sample) return "sample";
+      if (info.level) return "done";
+      if (info.arbitrated) return "arbitrate";
+      if (info.rejected) return "reject";
+      if (!info.rejected && !info.arbitrated && !info.level) return "undo";
+      return;
+    },
+    rebuildRight() {
+      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;
+    },
+    getCurLevel() {
+      const levelName = this.curPaperOrTask.rejected
+        ? this.curPaperOrTask.redoLevel
+        : this.curPaperOrTask.level;
+      if (levelName) {
+        this.curLevel = this.levels.find(item => item.name === levelName);
+      } else {
+        this.curLevel = {};
+      }
+    },
+    async getMarkHistory() {
+      // 只有科组长和超管才会展示评卷记录
+      const data = await markHistoryList(this.curPaperOrTask.id, "LEVEL");
+      this.gradingHistory = data.map(item => {
+        let level = item.result || "未评";
+        if (this.stepType === "reject" && !item.result) {
+          level = `${level}(${item.originLevel})`;
+        }
+        return {
+          id: item.id,
+          markerId: item.markerId,
+          name: item.marker,
+          loginName: item.loginName,
+          value: level
+        };
+      });
+    },
+    selectLevel(level) {
+      if (this.IS_MARKER && this.curPaperOrTask.level === level.name) return;
+      if (this.btnClicked) return;
+      this.btnClicked = true;
+
+      this.setT = setTimeout(() => {
+        this.btnClicked = false;
+      }, 500);
+
+      if (this.IS_MARK_LEADER) {
+        this.$emit(
+          "on-leader-level",
+          {
+            paperIds: this.curPaperOrTask.id + "",
+            curLevel: this.curPaperOrTask.level,
+            selectedLevel: level.name,
+            markLeaderOnlyRight: this.markLeaderOnlyRight
+          },
+          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);
+    }
+  },
+  beforeDestroy() {
+    if (this.setT) clearTimeout(this.setT);
+  }
+};
+</script>

+ 651 - 606
src/modules/grading/leader/LeaderGrading.vue

@@ -1,606 +1,651 @@
-<template>
-  <div class="marker-grading">
-    <marker-header
-      v-if="curSubject.id"
-      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"
-    ></marker-header>
-
-    <div
-      :class="[
-        'marker-action',
-        { 'marker-action-fullscreen': isFullscreenMarking }
-      ]"
-      v-show="!multipleGradingList.length"
-    >
-      <grade-action
-        :cur-paper-or-task="curPaper"
-        :levels="levels"
-        :params-set="paramsSet"
-        :key="curPaper.key"
-        @on-leader-level="leaderSelectLevel"
-        @on-code-search="serachPaperByCode"
-        ref="GradeAction"
-        v-if="curPaper.id"
-      ></grade-action>
-    </div>
-    <!-- multiple grading action -->
-    <div class="marker-action" v-show="multipleGradingList.length">
-      <div class="grade-action">
-        <div class="action-paper-state">
-          <p class="paper-state-cont">批量操作</p>
-        </div>
-        <div class="action-paper-info">
-          <p><span>试卷密号:</span><span>--</span></p>
-        </div>
-        <h3 class="action-grade-info-title" v-if="markLeaderOnlyRight">
-          当前操作:{{ markLeaderOnlyRight.name }}
-        </h3>
-        <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 }}</p>
-              <p>{{ level.minScore }}~{{ level.maxScore }}</p>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <div class="marker-body">
-      <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"
-              @to-review="toReview(index)"
-              @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"
-      ref="LeaderStatistics"
-    ></leader-statistics>
-    <!-- LeaderProgress -->
-    <leader-progress ref="LeaderProgress"></leader-progress>
-    <!-- MarkerHistory -->
-    <marker-history
-      :question-id="filter.questionId"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers, 'history');
-        }
-      "
-      ref="MarkerHistory"
-    ></marker-history>
-    <!-- MarkerStandard -->
-    <marker-standard
-      :question-id="filter.questionId"
-      :levels="levels"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers, 'sample');
-        }
-      "
-      ref="MarkerStandard"
-      v-if="levels.length && filter.questionId && paramsSet.showSample"
-    ></marker-standard>
-    <!-- modify-leader-grading -->
-    <modify-leader-grading
-      class="marker-modal"
-      :level-info="levelInfo"
-      :markers="markers"
-      @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="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 { 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 SimpleImagePreview from "@/components/SimpleImagePreview";
-import ModifyLeaderGrading from "../components/ModifyLeaderGrading";
-
-import {
-  paperList,
-  levelStatData,
-  workLevelList,
-  taskSnSearch,
-  subjectDetail,
-  markHistoryList,
-  getParamsSet,
-  leaderGradingPaper
-} from "@/api";
-
-export default {
-  name: "marker-grading",
-  components: {
-    MarkerHeader,
-    MarkerImageView,
-    MarkerHistory,
-    MarkerStandard,
-    LeaderProgress,
-    LeaderStatistics,
-    GradeAction,
-    SimpleImagePreview,
-    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,
-      levels: [],
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      // 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"
-    ]),
-    markerImageListClasses() {
-      return ["marker-image-list", `marker-image-list-${this.page.size}`];
-    },
-    IS_TEST() {
-      return this.curSubject.test === 2;
-    },
-    ACTION_CAN_BATCH() {
-      return this.curStep.type === "done" && !this.paramsSet.paperStage;
-    }
-  },
-  created() {
-    this.markLeaderOnlyRight = this.$ls.get("user", {
-      markLeaderOnlyRight: null
-    }).markLeaderOnlyRight;
-
-    const curUserRoleType = this.$ls.get("user", { role: "" }).role;
-    this.setCurUserRoleType(curUserRoleType);
-    this.initData();
-  },
-  methods: {
-    ...mapMutations("marker", [
-      "setParamSet",
-      "setPage",
-      "setSteps",
-      "setCurStep",
-      "setCurArea",
-      "setCurSubject",
-      "setCurUserRoleType",
-      "clearState"
-    ]),
-    initData() {
-      this.getParamsSetInfo();
-      this.getSubjectDetail();
-      this.getWorkLevels();
-    },
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.setParamSet(data || {});
-    },
-    async getSubjectDetail() {
-      const curSubject = await subjectDetail(this.subjectId);
-      this.setCurSubject(curSubject || {});
-    },
-    async getList() {
-      this.multipleGradingList = [];
-      const datas = {
-        ...this.filter,
-        ...this.typeFilter[this.curStep.type],
-        page: this.page.current - 1,
-        size: this.page.size
-      };
-      if (this.curStep.type === "done") datas.level = this.curStep.name;
-
-      const data = await paperList(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 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_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.levels = data.map(item => {
-        return {
-          id: item.id,
-          name: item.code,
-          minScore: item.minScore,
-          maxScore: item.maxScore
-        };
-      });
-    },
-    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();
-      // this.getStepLevels();
-      if (this.papers.length) {
-        this.selectPaper(0);
-      } else {
-        this.curPaper = {};
-      }
-    },
-    async areaChange(curArea) {
-      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);
-    },
-    async multipleSelectLevel(level) {
-      if (!this.multipleGradingList.length) return;
-      if (this.multiplebtnClicked) return;
-
-      this.multiplebtnClicked = true;
-
-      const data = await markHistoryList(
-        this.multipleGradingList[0].id,
-        "LEVEL"
-      ).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(index) {
-      this.isFullscreenMarking = true;
-      this.multipleGradingList = [];
-      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.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) {
-      const data = await taskSnSearch(
-        params.codeType,
-        params.code,
-        this.filter.questionId
-      );
-      if (!data) {
-        this.$Message.error("没有查找到结果!");
-        return;
-      }
-      data.title = `NO.${data.sn}`;
-      this.papers = [data];
-      this.setPage({ current: 1, total: 1, totalPage: 1 });
-      this.selectPaper(0);
-    },
-    async leaderSelectLevel(levelInfo, markers) {
-      // 唯一权限时,直接操作
-      if (levelInfo.markLeaderOnlyRight && !this.paramsSet.leaderConfirm) {
-        const datas = {
-          action: levelInfo.markLeaderOnlyRight.action,
-          level: levelInfo.selectedLevel,
-          originLevel: levelInfo.curLevel,
-          paperIds: levelInfo.paperIds
-        };
-        if (datas.action === "reject") {
-          datas.range = markers.map(item => item.id).join();
-        }
-        let result = true;
-        const paper = await leaderGradingPaper(datas).catch(() => {
-          result = false;
-        });
-        if (!result) return;
-
-        this.leaderGradingSuccess(datas, paper);
-        return;
-      }
-
-      this.levelInfo = levelInfo;
-      this.markers = markers;
-      this.$refs.ModifyLeaderGrading.open();
-    },
-    async leaderGradingSuccess(datas, paper) {
-      this.getStepLevels();
-
-      if (this.multipleGradingList && this.multipleGradingList.length) {
-        // 批量处理逻辑
-        if (
-          this.page.current > 1 &&
-          this.page.current === this.page.totalPage &&
-          this.papers.length === this.multipleGradingList.length
-        ) {
-          this.setPage({ current: this.page.current - 1 });
-        }
-
-        this.multipleGradingList = [];
-        await this.getList();
-        this.selectPaper(this.curPaperIndex);
-      } else {
-        // 单张处理逻辑
-        this.toActionNextPaper();
-      }
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers, type) {
-      this.carouselType = type;
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-      });
-    },
-    selectCarouselPaper(index) {
-      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.carouselType = "";
-      this.selectPaper(this.curPaperIndex);
-    },
-    // header
-    toHistory() {
-      this.$refs.MarkerHistory.open();
-    },
-    toStandard() {
-      this.$refs.MarkerStandard.open();
-    },
-    toProgress() {
-      this.$refs.LeaderProgress.open();
-    },
-    toSelectAll(allSelected) {
-      this.$refs.MarkerImageView.forEach(item => {
-        item.changeSelect(allSelected);
-      });
-    },
-    toStatistics() {
-      this.$refs.LeaderStatistics.open();
-    }
-  },
-  beforeDestroy() {
-    this.clearState();
-  }
-};
-</script>
+<template>
+  <div class="marker-grading">
+    <marker-header
+      v-if="curSubject.id"
+      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
+      :class="[
+        'marker-action',
+        { 'marker-action-fullscreen': isFullscreenMarking }
+      ]"
+      v-show="!multipleGradingList.length"
+    >
+      <grade-action
+        :cur-paper-or-task="curPaper"
+        :levels="levels"
+        :params-set="paramsSet"
+        :key="curPaper.key"
+        @on-leader-level="leaderSelectLevel"
+        @on-code-search="serachPaperByCode"
+        ref="GradeAction"
+        v-if="curPaper.id"
+      ></grade-action>
+    </div>
+    <!-- multiple grading action -->
+    <div class="marker-action" v-show="multipleGradingList.length">
+      <div class="grade-action">
+        <div class="action-paper-state">
+          <p class="paper-state-cont">批量操作</p>
+        </div>
+        <div class="action-paper-info">
+          <p><span>试卷密号:</span><span>--</span></p>
+        </div>
+        <h3 class="action-grade-info-title" v-if="markLeaderOnlyRight">
+          当前操作:{{ markLeaderOnlyRight.name }}
+        </h3>
+        <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 }}</p>
+              <p>{{ level.minScore }}~{{ level.maxScore }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="marker-body">
+      <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"
+              @to-review="toReview(index)"
+              @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"
+      ref="LeaderStatistics"
+    ></leader-statistics>
+    <!-- LeaderProgress -->
+    <leader-progress ref="LeaderProgress"></leader-progress>
+    <!-- MarkerHistory -->
+    <marker-history
+      :question-id="filter.questionId"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers, 'history');
+        }
+      "
+      ref="MarkerHistory"
+    ></marker-history>
+    <!-- MarkerStandard -->
+    <marker-standard
+      :question-id="filter.questionId"
+      :levels="levels"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers, 'sample');
+        }
+      "
+      ref="MarkerStandard"
+      v-if="levels.length && filter.questionId && paramsSet.showSample"
+    ></marker-standard>
+    <!-- modify-leader-grading -->
+    <modify-leader-grading
+      class="marker-modal"
+      :level-info="levelInfo"
+      :markers="markers"
+      @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="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 { 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 SimpleImagePreview from "@/components/SimpleImagePreview";
+import ModifyLeaderGrading from "../components/ModifyLeaderGrading";
+
+import {
+  paperList,
+  markTaskPaperList,
+  levelStatData,
+  workLevelList,
+  taskSnSearch,
+  subjectDetail,
+  markHistoryList,
+  getParamsSet,
+  leaderGradingPaper
+} from "@/api";
+
+export default {
+  name: "marker-grading",
+  components: {
+    MarkerHeader,
+    MarkerImageView,
+    MarkerHistory,
+    MarkerStandard,
+    LeaderProgress,
+    LeaderStatistics,
+    GradeAction,
+    SimpleImagePreview,
+    ModifyLeaderGrading
+  },
+  data() {
+    return {
+      filter: {
+        questionId: "",
+        sort: "secretNumber"
+      },
+      typeFilter: {
+        done: {
+          level: ""
+        },
+        reject: {
+          reject: true
+        },
+        arbitrate: {
+          arbi: true
+        }
+      },
+      speFilter: null,
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      levels: [],
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      // 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"
+    ]),
+    markerImageListClasses() {
+      return ["marker-image-list", `marker-image-list-${this.page.size}`];
+    },
+    IS_TEST() {
+      return this.curSubject.test === 2;
+    },
+    ACTION_CAN_BATCH() {
+      return this.curStep.type === "done" && !this.paramsSet.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",
+      "clearState"
+    ]),
+    initData() {
+      this.getParamsSetInfo();
+      this.getSubjectDetail();
+      this.getWorkLevels();
+    },
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.setParamSet(data || {});
+    },
+    async getSubjectDetail() {
+      const curSubject = await subjectDetail(this.subjectId);
+      this.setCurSubject(curSubject || {});
+    },
+    async getList() {
+      this.multipleGradingList = [];
+
+      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 datas = {
+        ...params,
+        workId: this.workId,
+        subject: this.subject,
+        stage: "LEVEL",
+        page: this.page.current - 1,
+        size: this.page.size
+      };
+
+      const data = await markTaskPaperList(datas);
+      return data;
+    },
+    async toPage(page) {
+      this.setPage({
+        current: page
+      });
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    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_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.levels = data.map(item => {
+        return {
+          id: item.id,
+          name: item.code,
+          minScore: item.minScore,
+          maxScore: item.maxScore
+        };
+      });
+    },
+    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);
+    },
+    async multipleSelectLevel(level) {
+      if (!this.multipleGradingList.length) return;
+      if (this.multiplebtnClicked) return;
+
+      this.multiplebtnClicked = true;
+
+      const data = await markHistoryList(
+        this.multipleGradingList[0].id,
+        "LEVEL"
+      ).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(index) {
+      this.isFullscreenMarking = true;
+      this.multipleGradingList = [];
+      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.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
+      );
+      if (!data) {
+        this.$Message.error("没有查找到结果!");
+        return;
+      }
+      data.title = `NO.${data.sn}`;
+      this.papers = [data];
+      this.setPage({ current: 1, total: 1, totalPage: 1 });
+      this.selectPaper(0);
+    },
+    serachMarkPaper(data) {
+      console.log(data);
+      this.speFilter = { type: data.type, params: data.params };
+      this.toPage(1);
+    },
+    async leaderSelectLevel(levelInfo, markers) {
+      // 唯一权限时,直接操作
+      if (levelInfo.markLeaderOnlyRight && !this.paramsSet.leaderConfirm) {
+        const datas = {
+          action: levelInfo.markLeaderOnlyRight.action,
+          level: levelInfo.selectedLevel,
+          originLevel: levelInfo.curLevel,
+          paperIds: levelInfo.paperIds
+        };
+        if (datas.action === "reject") {
+          datas.range = markers.map(item => item.id).join();
+        }
+        let result = true;
+        const paper = await leaderGradingPaper(datas).catch(() => {
+          result = false;
+        });
+        if (!result) return;
+
+        this.leaderGradingSuccess(datas, paper);
+        return;
+      }
+
+      this.levelInfo = levelInfo;
+      this.markers = markers;
+      this.$refs.ModifyLeaderGrading.open();
+    },
+    async leaderGradingSuccess(datas, paper) {
+      this.getStepLevels();
+
+      if (this.multipleGradingList && this.multipleGradingList.length) {
+        // 批量处理逻辑
+        if (
+          this.page.current > 1 &&
+          this.page.current === this.page.totalPage &&
+          this.papers.length === this.multipleGradingList.length
+        ) {
+          this.setPage({ current: this.page.current - 1 });
+        }
+
+        this.multipleGradingList = [];
+        await this.getList();
+        this.selectPaper(this.curPaperIndex);
+      } else {
+        // 单张处理逻辑
+        this.toActionNextPaper();
+      }
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers, type) {
+      this.carouselType = type;
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+      });
+    },
+    selectCarouselPaper(index) {
+      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.carouselType = "";
+      this.selectPaper(this.curPaperIndex);
+    },
+    // header
+    toHistory() {
+      this.$refs.MarkerHistory.open();
+    },
+    toStandard() {
+      this.$refs.MarkerStandard.open();
+    },
+    toProgress() {
+      this.$refs.LeaderProgress.open();
+    },
+    toSelectAll(allSelected) {
+      this.$refs.MarkerImageView.forEach(item => {
+        item.changeSelect(allSelected);
+      });
+    },
+    toStatistics() {
+      this.$refs.LeaderStatistics.open();
+    }
+  },
+  beforeDestroy() {
+    this.clearState();
+  }
+};
+</script>

+ 486 - 373
src/modules/grading/marker/MarkerHeader.vue

@@ -1,373 +1,486 @@
-<template>
-  <div class="marker-header">
-    <!-- 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="marker-page" slot="content">
-          <div class="marker-page-set">
-            <span>页面跳转:</span>
-            <InputNumber
-              size="small"
-              :min="1"
-              :max="page.totalPage"
-              :step="1"
-              :precision="0"
-              v-model="pageNo"
-            ></InputNumber>
-            <div class="marker-page-btn" @click="pageNoSet">跳转</div>
-          </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>
-      <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 }}</i>
-            <i v-if="showPaperRelateCount">:{{ 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 v-if="showPaperRelateCount">({{ step.count }})</i>
-            </DropdownItem>
-            <DropdownItem
-              class="header-step-item"
-              v-for="step in steps.levelStep"
-              :key="step.name"
-              :name="step.name"
-            >
-              <i>{{ step.name }}</i>
-              <i v-if="showPaperRelateCount && IS_MARK_LEADER__SCORE">
-                ({{ step.count }})
-              </i>
-              <i v-if="showPaperRelateCount && !IS_MARK_LEADER__SCORE">
-                ({{ step.count }} / {{ step.gcount }})
-              </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 && paramsSet.showSample"
-        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>
-
-    <!-- ResetPwd -->
-    <reset-pwd ref="ResetPwd"></reset-pwd>
-  </div>
-</template>
-
-<script>
-import { mapState, mapMutations } from "vuex";
-import { areaList, logout } from "@/api";
-import ResetPwd from "@/modules/login/ResetPwd";
-
-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
-    };
-  },
-  computed: {
-    ...mapState("marker", [
-      "paramsSet",
-      "page",
-      "curStep",
-      "steps",
-      "curArea",
-      "curSubject",
-      "areas",
-      "IS_MARK_LEADER"
-    ]),
-    stageName() {
-      return this.curSubject.stage === "LEVEL" ? "分档" : "打分";
-    },
-    IS_MARK_LEADER__SCORE() {
-      return this.IS_MARK_LEADER && this.curSubject.stage === "SCORE";
-    },
-    showPaperRelateCount() {
-      return !!this.paramsSet["showPaperCount"];
-    }
-  },
-  mounted() {
-    const subjectId = this.$route.params.subjectId.split("-");
-    this.filter.workId = subjectId[0];
-    this.filter.subject = subjectId[1];
-    this.getAreaList();
-    document.addEventListener("keydown", this.keyEvent);
-  },
-  methods: {
-    ...mapMutations("marker", ["setPage", "setAreas"]),
-    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]);
-      }
-    },
-    keyEvent(e) {
-      e.preventDefault();
-      if (!e.altKey && !e.shiftKey && !e.repeat) {
-        // 左右键切换分页
-        if (e.code === "ArrowLeft") {
-          if (e.ctrlKey) {
-            this.toFirstPage();
-          } else {
-            this.toPrevPage();
-          }
-          return;
-        }
-
-        if (e.code === "ArrowRight") {
-          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);
-    },
-    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) {
-      this.setPage({ size });
-      this.pageSetChange();
-    },
-    pageSetChange() {
-      this.pageVisible = false;
-      this.$emit("page-set-change", this.page);
-    },
-    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">
+    <!-- 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="marker-page" slot="content">
+          <div class="marker-page-set">
+            <span>页面跳转:</span>
+            <InputNumber
+              size="small"
+              :min="1"
+              :max="page.totalPage"
+              :step="1"
+              :precision="0"
+              v-model="pageNo"
+            ></InputNumber>
+            <div class="marker-page-btn" @click="pageNoSet">跳转</div>
+          </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 }}</i>
+            <i v-if="showPaperRelateCount">:{{ 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 v-if="showPaperRelateCount">({{ step.count }})</i>
+            </DropdownItem>
+            <DropdownItem
+              class="header-step-item"
+              v-for="step in steps.levelStep"
+              :key="step.name"
+              :name="step.name"
+            >
+              <i>{{ step.name }}</i>
+              <i v-if="showPaperRelateCount && IS_MARK_LEADER__SCORE">
+                ({{ step.count }})
+              </i>
+              <i v-if="showPaperRelateCount && !IS_MARK_LEADER__SCORE">
+                ({{ step.count }} / {{ step.gcount }})
+              </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 && paramsSet.showSample"
+        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>
+
+    <!-- ResetPwd -->
+    <reset-pwd ref="ResetPwd"></reset-pwd>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from "vuex";
+import { areaList, gradingUserList, logout } from "@/api";
+import ResetPwd from "@/modules/login/ResetPwd";
+import { CODE_TYPE } 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"
+    ]),
+    stageName() {
+      return this.curSubject.stage === "LEVEL" ? "分档" : "打分";
+    },
+    IS_MARK_LEADER__SCORE() {
+      return this.IS_MARK_LEADER && this.curSubject.stage === "SCORE";
+    },
+    showPaperRelateCount() {
+      return !!this.paramsSet["showPaperCount"];
+    }
+  },
+  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();
+    document.addEventListener("keydown", this.keyEvent);
+
+    this.codeTypes = Object.entries(CODE_TYPE)
+      .map(([key, val]) => {
+        return {
+          key,
+          val
+        };
+      })
+      .filter(item => item.key !== "examNumber");
+  },
+  methods: {
+    ...mapMutations("marker", ["setPage", "setAreas"]),
+    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 data = await gradingUserList({
+        ...this.filter
+      });
+      this.markers = data || [];
+    },
+    keyEvent(e) {
+      e.preventDefault();
+      if (!e.altKey && !e.shiftKey && !e.repeat) {
+        // 左右键切换分页
+        if (e.code === "ArrowLeft") {
+          if (e.ctrlKey) {
+            this.toFirstPage();
+          } else {
+            this.toPrevPage();
+          }
+          return;
+        }
+
+        if (e.code === "ArrowRight") {
+          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);
+    },
+    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) {
+      this.setPage({ size });
+      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
+      });
+    },
+    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>

+ 327 - 326
src/modules/main/StudentScore.vue

@@ -1,326 +1,327 @@
-<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;
-      }
-    },
-    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;
+      }
+    },
+    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() {
+      this.students = [];
+      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>

+ 561 - 561
src/modules/mark/components/MarkAction.vue

@@ -1,561 +1,561 @@
-<template>
-  <div class="mark-action grade-action">
-    <!-- 头部信息 ------ -->
-    <!-- 试卷状态 -->
-    <!-- 状态:已评,待评,改档,改档打分 -->
-    <div class="action-paper-state">
-      <p class="paper-state-cont">{{ stepLabel }}</p>
-    </div>
-
-    <!-- 试卷信息 -->
-    <div class="action-paper-info">
-      <p v-if="IS_ADMIN">
-        <span>试卷考号:</span><span>{{ curPaperOrTask.examNumber }}</span>
-      </p>
-      <p>
-        <span v-if="IS_MARKER">任务密号:</span>
-        <span v-else>试卷密号:</span>
-        <span>NO.{{ curPaperOrTask.sn }}</span>
-      </p>
-    </div>
-
-    <!-- 改档信息 -->
-    <div class="action-grade-change" v-if="rights.gradeChange">
-      <p>
-        <span>原始档位:</span><span>{{ curPaperOrTask.originLevel }}</span>
-      </p>
-      <p>
-        <span v-if="IS_MARKER">建议档位:</span>
-        <span v-else>申请档位:</span>
-        <span>{{ curPaperOrTask.redoLevel }}</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.gradeInfo">
-      <h3 class="grade-info-name">
-        {{ curPaperLevel }}
-      </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.markInfo">
-      <p class="grade-info-name" v-if="curPaperScore">
-        {{ curPaperScore }}
-      </p>
-      <p class="grade-info-name grade-info-none" v-else>未打分</p>
-    </div>
-
-    <!-- 选择档位 -->
-    <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 }
-          ]"
-          @click="selectLevel(level)"
-        >
-          <p>{{ level.name }}</p>
-          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
-        </div>
-      </div>
-    </div>
-
-    <!-- 选择分数  -->
-    <div class="action-mark-list" v-if="rights.levelList">
-      <div
-        class="action-mark-item"
-        v-for="(score, index) in scores"
-        :key="index"
-      >
-        <div
-          :class="[
-            'action-mark-item-content',
-            { 'action-item-content-disabled': btnClicked }
-          ]"
-          @click="selectScore(score)"
-        >
-          <p>{{ score }}</p>
-        </div>
-      </div>
-    </div>
-    <div
-      class="action-mark-input"
-      v-if="rights.levelList && paramsSet.directScore"
-    >
-      <Form
-        ref="ManualScoreForm"
-        label-position="left"
-        :model="manualScoreModel"
-        :rules="manualScoreModelRules"
-        inline
-      >
-        <FormItem prop="score" label="分数" :show-message="false">
-          <InputNumber
-            :precision="0"
-            v-model="manualScoreModel.score"
-          ></InputNumber>
-        </FormItem>
-        <FormItem class="mark-input-confirm">
-          <Button type="primary" size="small" @click="toInputScore">
-            确定
-          </Button>
-        </FormItem>
-        <p class="tips-info">
-          <Icon type="md-alert" />分数必须介于{{ manualMinScore }}和{{
-            manualMaxScore
-          }}之间
-        </p>
-      </Form>
-    </div>
-    <div class="action-grade-pass" v-if="rights.levelList" @click="toPass">
-      跳过
-    </div>
-
-    <!-- mark confirm grade change -->
-    <div
-      class="action-grade-change-confirm"
-      v-if="IS_MARKER && stepType === 'shift'"
-    >
-      <Button type="primary" @click="gradeChangeConfirm">确认改档</Button>
-    </div>
-
-    <!-- 评卷记录 -->
-    <div class="action-grade-history" v-if="rights.markHis">
-      <h3>评卷记录</h3>
-      <div class="grade-history-list">
-        <div
-          class="grade-history-item"
-          v-for="(his, hindex) in gradingHistory"
-          :key="hindex"
-        >
-          <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 class="action-search" v-if="rights.gradeChangeSearch">
-      <Select
-        class="search-input"
-        v-model="applyChangeLevelStatus"
-        placeholder="类型"
-      >
-        <Option
-          v-for="(val, key) in CHANGE_LEVEL_STATUS"
-          :key="key"
-          :value="key * 1"
-          :label="val"
-        ></Option>
-      </Select>
-      <Button
-        size="small"
-        type="primary"
-        class="search-btn"
-        @click="searchGradeChange"
-        >查询</Button
-      >
-    </div>
-  </div>
-</template>
-
-<script>
-import { markHistoryList } from "@/api";
-import { CODE_TYPE, CHANGE_LEVEL_STATUS } from "@/constants/enumerate";
-
-// 三种情况:
-// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
-// 管理员:查询,头部信息,评卷记录
-// 科组长:查询,头部信息,选择档位,评卷记录
-// 评卷员:头部信息,选择分数
-/*
-[paper template]
-{
-  "id": 42,
-  "sn": "5314987744",
-  "redoLevel": null,
-  "level": "B",
-  "score": null,
-  "result": "88",
-  "originLevel": null,
-  "markerId": 52,
-  "marker": "zj-pj-01",
-  "updatedOn": 1595812145000,
-  "imgSrc": "http://192.168.10.145:9000/images/34/SC/1/1901130046.jpg?random=f5549bb0-ba58-4cd3-a88e-0559be4e06e5",
-  "thumbSrc": "http://192.168.10.145:9000/thumbs/34/SC/1/1901130046.jpg?random=e7f880b8-4cb6-4963-8e66-532f0f8bdeb0",
-  "markByLeader": false,
-  "oldRejected": false,
-  "paperId": 116,
-  "randomSeqNew": 4987744,
-  "randomSeq": null,
-  "serialNumber": "B1",
-  "displayNumber": true,
-  "shift": false,
-  "shiftScore": false,
-  "rejected": false,
-  "sample": false
-}
-[marktask template]
-{
-  "id": 38,
-  "sn": "5314266469",
-  "redoLevel": null,
-  "level": "A",
-  "score": null,
-  "result": "96",
-  "originLevel": null,
-  "markerId": 52,
-  "marker": "zj-pj-01",
-  "updatedOn": 1595812012000,
-  "imgSrc": "http://192.168.10.145:9000/images/34/SC/1/1901130043.jpg?random=bffc061c-7a80-42a4-ad56-36ec6eba0d45",
-  "thumbSrc": "http://192.168.10.145:9000/thumbs/34/SC/1/1901130043.jpg?random=da743f9d-8d46-4499-bb6f-b9c26e003ba2",
-  "markByLeader": true,
-  "oldRejected": false,
-  "paperId": 113,
-  "randomSeqNew": 4266469,
-  "randomSeq": null,
-  "serialNumber": "A1",
-  "displayNumber": true,
-  "shift": false,
-  "shiftScore": false,
-  "rejected": false,
-  "sample": true
-}
-*/
-
-const initRights = {
-  search: false,
-  gradeChangeSearch: false,
-  gradeChange: false,
-  gradeInfo: false,
-  markInfo: false,
-  gradeList: false,
-  levelList: false,
-  markHis: false
-};
-
-export default {
-  name: "mark-action",
-  props: {
-    curPaperOrTask: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    levels: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    paramsSet: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      curUserRoleType: this.$ls.get("user", { role: "" }).role,
-      rights: {
-        ...initRights
-      },
-      roleRight: {
-        SUPER_ADMIN: {
-          done: ["search", "markHis", "gradeInfo", "markInfo"],
-          shift: ["search", "gradeChangeSearch", "gradeChange"]
-        },
-        ADMIN: {
-          done: ["search", "markHis", "gradeInfo", "markInfo"],
-          shift: ["search", "gradeChangeSearch", "gradeChange"]
-        },
-        MARK_LEADER: {
-          undo: ["search", "gradeList", "gradeInfo", "markInfo"],
-          done: ["search", "gradeList", "markHis", "gradeInfo", "markInfo"],
-          shift: ["search", "gradeList", "gradeChange"]
-        },
-        MARKER: {
-          done: ["levelList", "gradeInfo", "markInfo"],
-          undo: ["levelList", "gradeInfo"],
-          shift: ["gradeChange"],
-          shiftScore: ["levelList", "gradeInfo"]
-        }
-      },
-      filter: {
-        codeType: "examNumber",
-        code: ""
-      },
-      manualMaxScore: 100,
-      manualMinScore: 0,
-      manualScoreModel: {
-        score: null,
-        manualScore: 1
-      },
-      manualScoreModelRules: {
-        score: [
-          {
-            validator: (rule, value, callback) => {
-              console.log(value);
-              if (value === null) {
-                callback(new Error("请输入分数"));
-              } else if (
-                value < this.manualMinScore ||
-                value > this.manualMaxScore
-              ) {
-                callback(
-                  new Error(
-                    `分数必须介于${this.manualMinScore}和${this.manualMaxScore}之间`
-                  )
-                );
-              } else {
-                callback();
-              }
-            },
-            trigger: "change"
-          }
-        ]
-      },
-      codeTypes: [],
-      CHANGE_LEVEL_STATUS,
-      applyChangeLevelStatus: null,
-      stepDict: {
-        undo: "待评",
-        done: "已评",
-        shift: "改档",
-        shiftScore: "改档打分"
-      },
-      stepType: "",
-      stepLabel: "",
-      curPaperLevel: "",
-      curPaperScore: "",
-      scores: [],
-      gradingHistory: [],
-      curLevel: {},
-      setT: null,
-      btnClicked: false
-    };
-  },
-  computed: {
-    IS_ADMIN() {
-      return (
-        this.curUserRoleType === "ADMIN" ||
-        this.curUserRoleType === "SUPER_ADMIN"
-      );
-    },
-    IS_MARKER() {
-      return this.curUserRoleType === "MARKER";
-    },
-    IS_MARK_LEADER() {
-      return this.curUserRoleType === "MARK_LEADER";
-    }
-  },
-  watch: {
-    curPaperOrTask(val) {
-      this.rebuildRight();
-    }
-  },
-  mounted() {
-    this.codeTypes = Object.entries(CODE_TYPE)
-      .map(([key, val]) => {
-        return {
-          key,
-          val
-        };
-      })
-      .filter(item => this.IS_ADMIN || item.key !== "examNumber");
-    this.rebuildRight();
-    this.getValidScoreArea();
-  },
-  methods: {
-    getValidScoreArea() {
-      let nums = [];
-      this.levels.forEach(level => {
-        if (level.levelType === "ADMITED") {
-          nums = [...nums, level.minScore, level.maxScore];
-        } else {
-          let scores = this.curLevel.scoreList.split(",").map(item => item * 1);
-          nums = [...nums, ...scores];
-        }
-      });
-      this.manualMaxScore = Math.max.apply(null, nums);
-      this.manualMinScore = Math.min.apply(null, nums);
-    },
-    getStepType() {
-      const paper = this.curPaperOrTask;
-      if (paper.shift && paper.shiftScore && !paper.level && !paper.result)
-        return "shift";
-      if (!paper.shift && paper.shiftScore && !paper.result)
-        return "shiftScore";
-      if (this.IS_MARKER) {
-        if (!paper.result) return "undo";
-        if (paper.result) return "done";
-      } else {
-        if (paper.score !== null) return "done";
-        if (paper.score === null) return "undo";
-      }
-    },
-    rebuildRight() {
-      const curPaperScore = this.IS_MARKER
-        ? this.curPaperOrTask.result
-        : this.curPaperOrTask.score;
-      this.curPaperScore = curPaperScore !== null ? curPaperScore + "" : "";
-      this.stepType = this.getStepType();
-      this.stepLabel = this.stepDict[this.stepType];
-      this.rights = { ...initRights };
-      const roleRights =
-        this.roleRight[this.curUserRoleType][this.stepType] || [];
-      roleRights.map(key => {
-        this.rights[key] = true;
-      });
-
-      if (this.curPaperOrTask.level) {
-        this.curLevel = this.levels.find(
-          level => level.name === this.curPaperOrTask.level
-        );
-        this.curPaperLevel =
-          this.curPaperOrTask["displayNumber"] && this.stepType !== "shiftScore"
-            ? this.curPaperOrTask["serialNumber"]
-            : this.curPaperOrTask.level;
-        this.updateScoreList();
-      }
-      if (this.rights.markHis) {
-        this.getMarkHistory();
-      }
-
-      this.btnClicked = false;
-    },
-    updateScoreList() {
-      let scores = [];
-      if (this.curLevel.levelType === "ADMITED") {
-        const { minScore, maxScore, intervalScore } = this.curLevel;
-        for (let i = minScore; i <= maxScore; i += intervalScore) {
-          scores.push(i);
-        }
-      } else {
-        scores = this.curLevel.scoreList.split(",").map(item => item * 1);
-      }
-
-      this.scores = scores;
-    },
-    async getMarkHistory() {
-      const data = await markHistoryList(this.curPaperOrTask.id, "SCORE");
-      this.gradingHistory = data.map(item => {
-        return {
-          id: item.markerId,
-          name: item.marker,
-          loginName: item.loginName,
-          value: item.result || "未评"
-        };
-      });
-    },
-    selectLevel(level) {
-      if (this.curPaperOrTask.level === level.name) return;
-
-      if (this.btnClicked) return;
-      this.btnClicked = true;
-
-      this.setT = setTimeout(() => {
-        this.btnClicked = false;
-      }, 500);
-
-      // 科组长改档 / 评卷同意改档:只使用selectedLevel
-      this.$emit("on-leader-level", {
-        paperId: this.curPaperOrTask.paperId,
-        curLevel:
-          this.stepType === "shift"
-            ? this.curPaperOrTask.redoLevel
-            : this.curPaperOrTask.level,
-        selectedLevel: level.name
-      });
-    },
-    gradeChangeConfirm() {
-      this.selectLevel({ name: this.curPaperOrTask.redoLevel });
-    },
-    selectScore(score, manualScore = 0) {
-      if (!score && score !== 0) return;
-      if (this.btnClicked) return;
-      this.btnClicked = true;
-
-      this.setT = setTimeout(() => {
-        this.btnClicked = false;
-      }, 500);
-      // 评卷员打分
-      this.$emit("on-select-score", { score, manualScore });
-    },
-    async toInputScore() {
-      const valid = await this.$refs.ManualScoreForm.validate();
-      if (!valid) return;
-      this.selectScore(
-        this.manualScoreModel.score,
-        this.manualScoreModel.manualScore
-      );
-      this.manualScoreModel.score = null;
-    },
-    toPass() {
-      this.$emit("on-pass");
-    },
-    searchCode() {
-      if (!this.filter.code || !this.filter.codeType) {
-        this.$Message.error("请设置密号类型和密号!");
-        return;
-      }
-      this.$emit("on-code-search", this.filter);
-    },
-    searchGradeChange() {
-      this.$emit("on-grade-change-search", this.applyChangeLevelStatus);
-    }
-  }
-};
-</script>
+<template>
+  <div class="mark-action grade-action">
+    <!-- 头部信息 ------ -->
+    <!-- 试卷状态 -->
+    <!-- 状态:已评,待评,改档,改档打分 -->
+    <div class="action-paper-state">
+      <p class="paper-state-cont">{{ stepLabel }}</p>
+    </div>
+
+    <!-- 试卷信息 -->
+    <div class="action-paper-info">
+      <p v-if="IS_ADMIN">
+        <span>试卷考号:</span><span>{{ curPaperOrTask.examNumber }}</span>
+      </p>
+      <p>
+        <span v-if="IS_MARKER">任务密号:</span>
+        <span v-else>试卷密号:</span>
+        <span>NO.{{ curPaperOrTask.sn }}</span>
+      </p>
+    </div>
+
+    <!-- 改档信息 -->
+    <div class="action-grade-change" v-if="rights.gradeChange">
+      <p>
+        <span>原始档位:</span><span>{{ curPaperOrTask.originLevel }}</span>
+      </p>
+      <p>
+        <span v-if="IS_MARKER">建议档位:</span>
+        <span v-else>申请档位:</span>
+        <span>{{ curPaperOrTask.redoLevel }}</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.gradeInfo">
+      <h3 class="grade-info-name">
+        {{ curPaperLevel }}
+      </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.markInfo">
+      <p class="grade-info-name" v-if="curPaperScore">
+        {{ curPaperScore }}
+      </p>
+      <p class="grade-info-name grade-info-none" v-else>未打分</p>
+    </div>
+
+    <!-- 选择档位 -->
+    <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 }
+          ]"
+          @click="selectLevel(level)"
+        >
+          <p>{{ level.name }}</p>
+          <p>{{ level.minScore }}~{{ level.maxScore }}</p>
+        </div>
+      </div>
+    </div>
+
+    <!-- 选择分数  -->
+    <div class="action-mark-list" v-if="rights.levelList">
+      <div
+        class="action-mark-item"
+        v-for="(score, index) in scores"
+        :key="index"
+      >
+        <div
+          :class="[
+            'action-mark-item-content',
+            { 'action-item-content-disabled': btnClicked }
+          ]"
+          @click="selectScore(score)"
+        >
+          <p>{{ score }}</p>
+        </div>
+      </div>
+    </div>
+    <div
+      class="action-mark-input"
+      v-if="rights.levelList && paramsSet.directScore"
+    >
+      <Form
+        ref="ManualScoreForm"
+        label-position="left"
+        :model="manualScoreModel"
+        :rules="manualScoreModelRules"
+        inline
+      >
+        <FormItem prop="score" label="分数" :show-message="false">
+          <InputNumber
+            :precision="0"
+            v-model="manualScoreModel.score"
+          ></InputNumber>
+        </FormItem>
+        <FormItem class="mark-input-confirm">
+          <Button type="primary" size="small" @click="toInputScore">
+            确定
+          </Button>
+        </FormItem>
+        <p class="tips-info">
+          <Icon type="md-alert" />分数必须介于{{ manualMinScore }}和{{
+            manualMaxScore
+          }}之间
+        </p>
+      </Form>
+    </div>
+    <div class="action-grade-pass" v-if="rights.levelList" @click="toPass">
+      跳过
+    </div>
+
+    <!-- mark confirm grade change -->
+    <div
+      class="action-grade-change-confirm"
+      v-if="IS_MARKER && stepType === 'shift'"
+    >
+      <Button type="primary" @click="gradeChangeConfirm">确认改档</Button>
+    </div>
+
+    <!-- 评卷记录 -->
+    <div class="action-grade-history" v-if="rights.markHis">
+      <h3>评卷记录</h3>
+      <div class="grade-history-list">
+        <div
+          class="grade-history-item"
+          v-for="(his, hindex) in gradingHistory"
+          :key="hindex"
+        >
+          <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 class="action-search" v-if="rights.gradeChangeSearch">
+      <Select
+        class="search-input"
+        v-model="applyChangeLevelStatus"
+        placeholder="类型"
+      >
+        <Option
+          v-for="(val, key) in CHANGE_LEVEL_STATUS"
+          :key="key"
+          :value="key * 1"
+          :label="val"
+        ></Option>
+      </Select>
+      <Button
+        size="small"
+        type="primary"
+        class="search-btn"
+        @click="searchGradeChange"
+        >查询</Button
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+import { markHistoryList } from "@/api";
+import { CODE_TYPE, CHANGE_LEVEL_STATUS } from "@/constants/enumerate";
+
+// 三种情况:
+// 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
+// 管理员:查询,头部信息,评卷记录
+// 科组长:查询,头部信息,选择档位,评卷记录
+// 评卷员:头部信息,选择分数
+/*
+[paper template]
+{
+  "id": 42,
+  "sn": "5314987744",
+  "redoLevel": null,
+  "level": "B",
+  "score": null,
+  "result": "88",
+  "originLevel": null,
+  "markerId": 52,
+  "marker": "zj-pj-01",
+  "updatedOn": 1595812145000,
+  "imgSrc": "http://192.168.10.145:9000/images/34/SC/1/1901130046.jpg?random=f5549bb0-ba58-4cd3-a88e-0559be4e06e5",
+  "thumbSrc": "http://192.168.10.145:9000/thumbs/34/SC/1/1901130046.jpg?random=e7f880b8-4cb6-4963-8e66-532f0f8bdeb0",
+  "markByLeader": false,
+  "oldRejected": false,
+  "paperId": 116,
+  "randomSeqNew": 4987744,
+  "randomSeq": null,
+  "serialNumber": "B1",
+  "displayNumber": true,
+  "shift": false,
+  "shiftScore": false,
+  "rejected": false,
+  "sample": false
+}
+[marktask template]
+{
+  "id": 38,
+  "sn": "5314266469",
+  "redoLevel": null,
+  "level": "A",
+  "score": null,
+  "result": "96",
+  "originLevel": null,
+  "markerId": 52,
+  "marker": "zj-pj-01",
+  "updatedOn": 1595812012000,
+  "imgSrc": "http://192.168.10.145:9000/images/34/SC/1/1901130043.jpg?random=bffc061c-7a80-42a4-ad56-36ec6eba0d45",
+  "thumbSrc": "http://192.168.10.145:9000/thumbs/34/SC/1/1901130043.jpg?random=da743f9d-8d46-4499-bb6f-b9c26e003ba2",
+  "markByLeader": true,
+  "oldRejected": false,
+  "paperId": 113,
+  "randomSeqNew": 4266469,
+  "randomSeq": null,
+  "serialNumber": "A1",
+  "displayNumber": true,
+  "shift": false,
+  "shiftScore": false,
+  "rejected": false,
+  "sample": true
+}
+*/
+
+const initRights = {
+  search: false,
+  gradeChangeSearch: false,
+  gradeChange: false,
+  gradeInfo: false,
+  markInfo: false,
+  gradeList: false,
+  levelList: false,
+  markHis: false
+};
+
+export default {
+  name: "mark-action",
+  props: {
+    curPaperOrTask: {
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    levels: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    paramsSet: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      curUserRoleType: this.$ls.get("user", { role: "" }).role,
+      rights: {
+        ...initRights
+      },
+      roleRight: {
+        SUPER_ADMIN: {
+          done: ["search", "markHis", "gradeInfo", "markInfo"],
+          shift: ["search", "gradeChangeSearch", "gradeChange"]
+        },
+        ADMIN: {
+          done: ["search", "markHis", "gradeInfo", "markInfo"],
+          shift: ["search", "gradeChangeSearch", "gradeChange"]
+        },
+        MARK_LEADER: {
+          undo: ["gradeList", "gradeInfo", "markInfo"],
+          done: ["gradeList", "markHis", "gradeInfo", "markInfo"],
+          shift: ["gradeList", "gradeChange"]
+        },
+        MARKER: {
+          done: ["levelList", "gradeInfo", "markInfo"],
+          undo: ["levelList", "gradeInfo"],
+          shift: ["gradeChange"],
+          shiftScore: ["levelList", "gradeInfo"]
+        }
+      },
+      filter: {
+        codeType: "examNumber",
+        code: ""
+      },
+      manualMaxScore: 100,
+      manualMinScore: 0,
+      manualScoreModel: {
+        score: null,
+        manualScore: 1
+      },
+      manualScoreModelRules: {
+        score: [
+          {
+            validator: (rule, value, callback) => {
+              console.log(value);
+              if (value === null) {
+                callback(new Error("请输入分数"));
+              } else if (
+                value < this.manualMinScore ||
+                value > this.manualMaxScore
+              ) {
+                callback(
+                  new Error(
+                    `分数必须介于${this.manualMinScore}和${this.manualMaxScore}之间`
+                  )
+                );
+              } else {
+                callback();
+              }
+            },
+            trigger: "change"
+          }
+        ]
+      },
+      codeTypes: [],
+      CHANGE_LEVEL_STATUS,
+      applyChangeLevelStatus: null,
+      stepDict: {
+        undo: "待评",
+        done: "已评",
+        shift: "改档",
+        shiftScore: "改档打分"
+      },
+      stepType: "",
+      stepLabel: "",
+      curPaperLevel: "",
+      curPaperScore: "",
+      scores: [],
+      gradingHistory: [],
+      curLevel: {},
+      setT: null,
+      btnClicked: false
+    };
+  },
+  computed: {
+    IS_ADMIN() {
+      return (
+        this.curUserRoleType === "ADMIN" ||
+        this.curUserRoleType === "SUPER_ADMIN"
+      );
+    },
+    IS_MARKER() {
+      return this.curUserRoleType === "MARKER";
+    },
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    }
+  },
+  watch: {
+    curPaperOrTask(val) {
+      this.rebuildRight();
+    }
+  },
+  mounted() {
+    this.codeTypes = Object.entries(CODE_TYPE)
+      .map(([key, val]) => {
+        return {
+          key,
+          val
+        };
+      })
+      .filter(item => this.IS_ADMIN || item.key !== "examNumber");
+    this.rebuildRight();
+    this.getValidScoreArea();
+  },
+  methods: {
+    getValidScoreArea() {
+      let nums = [];
+      this.levels.forEach(level => {
+        if (level.levelType === "ADMITED") {
+          nums = [...nums, level.minScore, level.maxScore];
+        } else {
+          let scores = this.curLevel.scoreList.split(",").map(item => item * 1);
+          nums = [...nums, ...scores];
+        }
+      });
+      this.manualMaxScore = Math.max.apply(null, nums);
+      this.manualMinScore = Math.min.apply(null, nums);
+    },
+    getStepType() {
+      const paper = this.curPaperOrTask;
+      if (paper.shift && paper.shiftScore && !paper.level && !paper.result)
+        return "shift";
+      if (!paper.shift && paper.shiftScore && !paper.result)
+        return "shiftScore";
+      if (this.IS_MARKER) {
+        if (!paper.result) return "undo";
+        if (paper.result) return "done";
+      } else {
+        if (paper.score !== null) return "done";
+        if (paper.score === null) return "undo";
+      }
+    },
+    rebuildRight() {
+      const curPaperScore = this.IS_MARKER
+        ? this.curPaperOrTask.result
+        : this.curPaperOrTask.score;
+      this.curPaperScore = curPaperScore !== null ? curPaperScore + "" : "";
+      this.stepType = this.getStepType();
+      this.stepLabel = this.stepDict[this.stepType];
+      this.rights = { ...initRights };
+      const roleRights =
+        this.roleRight[this.curUserRoleType][this.stepType] || [];
+      roleRights.map(key => {
+        this.rights[key] = true;
+      });
+
+      if (this.curPaperOrTask.level) {
+        this.curLevel = this.levels.find(
+          level => level.name === this.curPaperOrTask.level
+        );
+        this.curPaperLevel =
+          this.curPaperOrTask["displayNumber"] && this.stepType !== "shiftScore"
+            ? this.curPaperOrTask["serialNumber"]
+            : this.curPaperOrTask.level;
+        this.updateScoreList();
+      }
+      if (this.rights.markHis) {
+        this.getMarkHistory();
+      }
+
+      this.btnClicked = false;
+    },
+    updateScoreList() {
+      let scores = [];
+      if (this.curLevel.levelType === "ADMITED") {
+        const { minScore, maxScore, intervalScore } = this.curLevel;
+        for (let i = minScore; i <= maxScore; i += intervalScore) {
+          scores.push(i);
+        }
+      } else {
+        scores = this.curLevel.scoreList.split(",").map(item => item * 1);
+      }
+
+      this.scores = scores;
+    },
+    async getMarkHistory() {
+      const data = await markHistoryList(this.curPaperOrTask.id, "SCORE");
+      this.gradingHistory = data.map(item => {
+        return {
+          id: item.markerId,
+          name: item.marker,
+          loginName: item.loginName,
+          value: item.result || "未评"
+        };
+      });
+    },
+    selectLevel(level) {
+      if (this.curPaperOrTask.level === level.name) return;
+
+      if (this.btnClicked) return;
+      this.btnClicked = true;
+
+      this.setT = setTimeout(() => {
+        this.btnClicked = false;
+      }, 500);
+
+      // 科组长改档 / 评卷同意改档:只使用selectedLevel
+      this.$emit("on-leader-level", {
+        paperId: this.curPaperOrTask.paperId,
+        curLevel:
+          this.stepType === "shift"
+            ? this.curPaperOrTask.redoLevel
+            : this.curPaperOrTask.level,
+        selectedLevel: level.name
+      });
+    },
+    gradeChangeConfirm() {
+      this.selectLevel({ name: this.curPaperOrTask.redoLevel });
+    },
+    selectScore(score, manualScore = 0) {
+      if (!score && score !== 0) return;
+      if (this.btnClicked) return;
+      this.btnClicked = true;
+
+      this.setT = setTimeout(() => {
+        this.btnClicked = false;
+      }, 500);
+      // 评卷员打分
+      this.$emit("on-select-score", { score, manualScore });
+    },
+    async toInputScore() {
+      const valid = await this.$refs.ManualScoreForm.validate();
+      if (!valid) return;
+      this.selectScore(
+        this.manualScoreModel.score,
+        this.manualScoreModel.manualScore
+      );
+      this.manualScoreModel.score = null;
+    },
+    toPass() {
+      this.$emit("on-pass");
+    },
+    searchCode() {
+      if (!this.filter.code || !this.filter.codeType) {
+        this.$Message.error("请设置密号类型和密号!");
+        return;
+      }
+      this.$emit("on-code-search", this.filter);
+    },
+    searchGradeChange() {
+      this.$emit("on-grade-change-search", this.applyChangeLevelStatus);
+    }
+  }
+};
+</script>

+ 514 - 457
src/modules/mark/leader/LeaderMarking.vue

@@ -1,457 +1,514 @@
-<template>
-  <div class="leader-marking marker-grading">
-    <marker-header
-      :show-standard="false"
-      :show-statistics="false"
-      @area-change="areaChange"
-      @step-change="stepChange"
-      @page-set-change="pageSetChange"
-      @to-progress="toProgress"
-      @to-history="toHistory"
-      @to-statistics="toStatistics"
-    ></marker-header>
-
-    <div
-      :class="[
-        'marker-action',
-        { 'marker-action-fullscreen': isFullscreenMarking }
-      ]"
-    >
-      <mark-action
-        :cur-paper-or-task="curPaper"
-        :levels="levels"
-        :key="curPaper.key"
-        @on-leader-level="leaderSelectLevel"
-        @on-code-search="serachPaperByCode"
-        @on-grade-change-search="searchGradeChangeList"
-        v-if="curPaper.id"
-        ref="GradeAction"
-      ></mark-action>
-    </div>
-
-    <div class="marker-body">
-      <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="stage"
-              @to-review="toReview(index)"
-            ></marker-image-view>
-          </div>
-        </div>
-      </div>
-      <div v-else class="marker-image-none">暂无数据</div>
-    </div>
-
-    <!-- LeaderProgress -->
-    <leader-progress ref="LeaderProgress"></leader-progress>
-    <!-- MarkerHistory -->
-    <marker-history
-      :question-id="filter.questionId"
-      :stage="stage"
-      @on-paper-click="
-        (index, papers) => {
-          toViewCarouselPaper(index, papers);
-        }
-      "
-      ref="MarkerHistory"
-    ></marker-history>
-    <!-- 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 { mapState, mapMutations } from "vuex";
-import MarkerHeader from "../../grading/marker/MarkerHeader";
-import MarkAction from "../components/MarkAction";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-import LeaderProgress from "../../grading/leader/LeaderProgress";
-import MarkerImageView from "../../grading/marker/MarkerImageView";
-import MarkerHistory from "../../grading/marker/MarkerHistory";
-
-import {
-  paperList,
-  subjectDetail,
-  changeLevelPaperList,
-  paperManualScoreList,
-  scoreStatData,
-  workLevelList,
-  taskSnSearch,
-  markStepChangeLevel,
-  getParamsSet
-} from "@/api";
-
-export default {
-  name: "leader-marking",
-  components: {
-    MarkerHeader,
-    MarkerImageView,
-    MarkerHistory,
-    // MarkerStatistics,
-    LeaderProgress,
-    MarkAction,
-    SimpleImagePreview
-  },
-  data() {
-    return {
-      filter: {
-        questionId: "",
-        sort: "score,desc"
-      },
-      stage: "SCORE",
-      workId: this.$route.params.workId,
-      subjectId: this.$route.params.subjectId,
-      subject: "",
-      workSubject: {},
-      applyChangeLevelStatus: 1, // 改档申请处理状态
-      levels: [],
-      papers: [],
-      curPaper: {},
-      curPaperIndex: 0,
-      // carousel paper review,
-      carouselPapers: [],
-      curCarouselPaperIndex: 0,
-      isFullscreenMarking: false
-    };
-  },
-  computed: {
-    ...mapState("marker", ["paramsSet", "page", "steps", "curStep", "curArea"]),
-    markerImageListClasses() {
-      return ["marker-image-list", `marker-image-list-${this.page.size}`];
-    },
-    showPaperRelateCount() {
-      return !!this.paramsSet["showPaperCount"];
-    }
-  },
-  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",
-      "setPage",
-      "setSteps",
-      "setCurArea",
-      "setCurStep",
-      "setCurSubject",
-      "setCurUserRoleType",
-      "clearState"
-    ]),
-    initData() {
-      this.getWorkLevels();
-      this.getSubjectDetail();
-      this.getParamsSetInfo();
-    },
-    async getParamsSetInfo() {
-      const data = await getParamsSet(this.workId);
-      this.setParamSet(data || {});
-    },
-    async getSubjectDetail() {
-      const curSubject = await subjectDetail(this.subjectId);
-      this.setCurSubject(curSubject || {});
-    },
-    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.page.current - 1,
-          size: this.page.size
-        };
-        data = await changeLevelPaperList(datas);
-      } else if (this.curStep.type === "manualScore") {
-        const datas = {
-          workId: this.workId,
-          questionId: this.filter.questionId,
-          page: this.page.current - 1,
-          size: this.page.size
-        };
-        data = await paperManualScoreList(datas);
-      } else {
-        const datas = {
-          ...this.filter,
-          isScore: true,
-          page: this.page.current - 1,
-          size: this.page.size
-        };
-        if (this.curStep.type === "done") datas.level = this.curStep.name;
-
-        data = await paperList(datas);
-      }
-      this.papers = data.data.map(paper => {
-        paper.key = this.$randomCode();
-        paper.title = this.IS_ADMIN ? paper.examNumber : `NO.${paper.sn}`;
-        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 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
-        .filter(item => item.id !== "manualScore")
-        .map(item => {
-          return {
-            ...item,
-            name: item.id,
-            type: "done"
-          };
-        });
-      const msInfo = data.find(item => item.id === "manualScore");
-      if (msInfo) {
-        otherStep.push({
-          count: msInfo.count,
-          name: "输分试卷",
-          type: "manualScore"
-        });
-      }
-
-      this.setSteps({ levelStep, otherStep });
-
-      if (!this.curStep.type) {
-        this.setCurStep(levelStep[0]);
-      } else {
-        const curStep = [...levelStep, ...otherStep].find(
-          item => item.name === this.curStep.name
-        );
-        this.setCurStep(curStep);
-      }
-    },
-    async getWorkLevels() {
-      const data = await workLevelList(this.workId);
-      this.levels = data.map(item => {
-        return {
-          ...item,
-          name: item.code
-        };
-      });
-    },
-    async pageSetChange() {
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
-    },
-    async stepChange(step) {
-      this.applyChangeLevelStatus = 1;
-      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.setCurArea(curArea);
-      this.filter.questionId = curArea.id;
-      await this.getStepLevels();
-      this.toPage(1);
-    },
-    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.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) {
-      const data = await taskSnSearch(
-        params.codeType,
-        params.code,
-        this.filter.questionId
-      );
-      if (!data) {
-        this.$Message.error("没有查找到结果!");
-        return;
-      }
-      data.title = this.IS_ADMIN ? data.examNumber : `NO.${data.sn}`;
-      this.papers = [data];
-      this.setPage({ current: 1, total: 1, totalPage: 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.toActionNextPaper();
-        }
-      });
-    },
-    // paper carousel
-    toViewCarouselPaper(paperIndex, papers) {
-      this.isFullscreenMarking = true;
-      this.carouselPapers = papers;
-      this.selectCarouselPaper(paperIndex);
-      this.$nextTick(() => {
-        this.$refs.CarouselPapersPreview.open();
-      });
-    },
-    selectCarouselPaper(index) {
-      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);
-    },
-    // header
-    toHistory() {
-      this.$refs.MarkerHistory.open();
-    },
-    toStatistics() {
-      this.$refs.MarkerStatistics.open();
-    },
-    toProgress() {
-      this.$refs.LeaderProgress.open();
-    }
-  },
-  beforeDestroy() {
-    this.clearState();
-  }
-};
-</script>
+<template>
+  <div class="leader-marking marker-grading">
+    <marker-header
+      :show-standard="false"
+      :show-statistics="false"
+      @area-change="areaChange"
+      @step-change="stepChange"
+      @page-set-change="pageSetChange"
+      @to-progress="toProgress"
+      @to-history="toHistory"
+      @to-statistics="toStatistics"
+      @on-code-search="serachPaperByCode"
+      @on-mark-search="serachMarkPaper"
+    ></marker-header>
+
+    <div
+      :class="[
+        'marker-action',
+        { 'marker-action-fullscreen': isFullscreenMarking }
+      ]"
+    >
+      <mark-action
+        :cur-paper-or-task="curPaper"
+        :levels="levels"
+        :key="curPaper.key"
+        @on-leader-level="leaderSelectLevel"
+        @on-code-search="serachPaperByCode"
+        @on-grade-change-search="searchGradeChangeList"
+        v-if="curPaper.id"
+        ref="GradeAction"
+      ></mark-action>
+    </div>
+
+    <div class="marker-body">
+      <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="stage"
+              @to-review="toReview(index)"
+            ></marker-image-view>
+          </div>
+        </div>
+      </div>
+      <div v-else class="marker-image-none">暂无数据</div>
+    </div>
+
+    <!-- LeaderProgress -->
+    <leader-progress ref="LeaderProgress"></leader-progress>
+    <!-- MarkerHistory -->
+    <marker-history
+      :question-id="filter.questionId"
+      :stage="stage"
+      @on-paper-click="
+        (index, papers) => {
+          toViewCarouselPaper(index, papers);
+        }
+      "
+      ref="MarkerHistory"
+    ></marker-history>
+    <!-- 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 { mapState, mapMutations } from "vuex";
+import MarkerHeader from "../../grading/marker/MarkerHeader";
+import MarkAction from "../components/MarkAction";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+import LeaderProgress from "../../grading/leader/LeaderProgress";
+import MarkerImageView from "../../grading/marker/MarkerImageView";
+import MarkerHistory from "../../grading/marker/MarkerHistory";
+
+import {
+  paperList,
+  subjectDetail,
+  changeLevelPaperList,
+  paperManualScoreList,
+  scoreStatData,
+  workLevelList,
+  taskSnSearch,
+  markStepChangeLevel,
+  getParamsSet,
+  markTaskPaperList
+} from "@/api";
+
+export default {
+  name: "leader-marking",
+  components: {
+    MarkerHeader,
+    MarkerImageView,
+    MarkerHistory,
+    // MarkerStatistics,
+    LeaderProgress,
+    MarkAction,
+    SimpleImagePreview
+  },
+  data() {
+    return {
+      filter: {
+        questionId: "",
+        sort: "score,desc"
+      },
+      speFilter: null,
+      stage: "SCORE",
+      workId: this.$route.params.workId,
+      subjectId: this.$route.params.subjectId,
+      subject: "",
+      workSubject: {},
+      applyChangeLevelStatus: 1, // 改档申请处理状态
+      levels: [],
+      papers: [],
+      curPaper: {},
+      curPaperIndex: 0,
+      // carousel paper review,
+      carouselPapers: [],
+      curCarouselPaperIndex: 0,
+      isFullscreenMarking: false
+    };
+  },
+  computed: {
+    ...mapState("marker", [
+      "paramsSet",
+      "page",
+      "steps",
+      "curStep",
+      "curArea",
+      "curSubject"
+    ]),
+    markerImageListClasses() {
+      return ["marker-image-list", `marker-image-list-${this.page.size}`];
+    },
+    showPaperRelateCount() {
+      return !!this.paramsSet["showPaperCount"];
+    }
+  },
+  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",
+      "setPage",
+      "setSteps",
+      "setCurArea",
+      "setCurStep",
+      "setCurSubject",
+      "setCurUserRoleType",
+      "clearState"
+    ]),
+    initData() {
+      this.getWorkLevels();
+      this.getSubjectDetail();
+      this.getParamsSetInfo();
+    },
+    async getParamsSetInfo() {
+      const data = await getParamsSet(this.workId);
+      this.setParamSet(data || {});
+    },
+    async getSubjectDetail() {
+      const curSubject = await subjectDetail(this.subjectId);
+      this.setCurSubject(curSubject || {});
+    },
+    async getList() {
+      let data = {
+        data: [],
+        totalCount: 0,
+        pageCount: 0
+      };
+
+      if (this.speFilter) {
+        const { type, params } = this.speFilter;
+        if (type === "mark") {
+          data = await this.getMarkList(params);
+        }
+      } else {
+        if (this.curStep.type === "shift") {
+          data = await this.getChangeLevelList();
+        } else if (this.curStep.type === "manualScore") {
+          data = await this.getManualScoreList();
+        } else {
+          data = await this.getCommonList();
+        }
+      }
+
+      this.papers = data.data.map(paper => {
+        paper.key = this.$randomCode();
+        paper.title = this.IS_ADMIN ? paper.examNumber : `NO.${paper.sn}`;
+        return paper;
+      });
+
+      this.setPage({
+        total: data.totalCount,
+        totalPage: data.pageCount
+      });
+    },
+    async getCommonList() {
+      const datas = {
+        ...this.filter,
+        isScore: true,
+        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 getChangeLevelList() {
+      const datas = {
+        workId: this.workId,
+        subject: this.subject,
+        questionId: this.filter.questionId,
+        status: this.applyChangeLevelStatus,
+        page: this.page.current - 1,
+        size: this.page.size
+      };
+      const data = await changeLevelPaperList(datas);
+      return data;
+    },
+    async getManualScoreList() {
+      const datas = {
+        workId: this.workId,
+        questionId: this.filter.questionId,
+        page: this.page.current - 1,
+        size: this.page.size
+      };
+      const data = await paperManualScoreList(datas);
+      return data;
+    },
+    async getMarkList(params) {
+      const datas = {
+        ...params,
+        workId: this.workId,
+        subject: this.subject,
+        stage: "SCORE",
+        page: this.page.current - 1,
+        size: this.page.size
+      };
+
+      const data = await markTaskPaperList(datas);
+      return data;
+    },
+    async toPage(page) {
+      this.setPage({
+        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
+        .filter(item => item.id !== "manualScore")
+        .map(item => {
+          return {
+            ...item,
+            name: item.id,
+            type: "done"
+          };
+        });
+      const msInfo = data.find(item => item.id === "manualScore");
+      if (msInfo) {
+        otherStep.push({
+          count: msInfo.count,
+          name: "输分试卷",
+          type: "manualScore"
+        });
+      }
+
+      this.setSteps({ levelStep, otherStep });
+
+      if (!this.curStep.type) {
+        this.setCurStep(levelStep[0]);
+      } else {
+        const curStep = [...levelStep, ...otherStep].find(
+          item => item.name === this.curStep.name
+        );
+        this.setCurStep(curStep);
+      }
+    },
+    async getWorkLevels() {
+      const data = await workLevelList(this.workId);
+      this.levels = data.map(item => {
+        return {
+          ...item,
+          name: item.code
+        };
+      });
+    },
+    async pageSetChange() {
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    async stepChange(step) {
+      this.speFilter = null;
+      this.applyChangeLevelStatus = 1;
+      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);
+    },
+    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.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
+      );
+      if (!data) {
+        this.$Message.error("没有查找到结果!");
+        return;
+      }
+      data.title = this.IS_ADMIN ? data.examNumber : `NO.${data.sn}`;
+      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);
+    },
+    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.toActionNextPaper();
+        }
+      });
+    },
+    // paper carousel
+    toViewCarouselPaper(paperIndex, papers) {
+      this.isFullscreenMarking = true;
+      this.carouselPapers = papers;
+      this.selectCarouselPaper(paperIndex);
+      this.$nextTick(() => {
+        this.$refs.CarouselPapersPreview.open();
+      });
+    },
+    selectCarouselPaper(index) {
+      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);
+    },
+    // header
+    toHistory() {
+      this.$refs.MarkerHistory.open();
+    },
+    toStatistics() {
+      this.$refs.MarkerStatistics.open();
+    },
+    toProgress() {
+      this.$refs.LeaderProgress.open();
+    }
+  },
+  beforeDestroy() {
+    this.clearState();
+  }
+};
+</script>