Bläddra i källkod

v1.3 task over

zhangjie 4 år sedan
förälder
incheckning
3b81370bbc

+ 0 - 0
public/temps/考务导入模板.xlsx → public/temps/考务编排导入模板.xlsx


BIN
public/temps/考试计划导入模板.xlsx


+ 1 - 1
src/assets/styles/adaptive.scss

@@ -98,7 +98,7 @@
     font-size: 14px;
   }
   .el-button {
-    padding: 10px 15px;
+    padding: 9px 15px;
   }
   .el-input__inner {
     height: 36px;

+ 5 - 0
src/assets/styles/base.scss

@@ -167,3 +167,8 @@ body {
     color: $--color-success;
   }
 }
+.tb-action-column {
+  .cell {
+    overflow: visible;
+  }
+}

+ 20 - 7
src/assets/styles/element-ui-costom.scss

@@ -112,13 +112,6 @@
     border-color: #ddd;
     background-color: #f5f5f5;
   }
-  .el-input__prefix {
-    left: 9px;
-    > i {
-      height: 12px;
-      width: 12px;
-    }
-  }
 }
 // upload
 .el-upload,
@@ -129,6 +122,7 @@
 // button
 .el-button {
   border-radius: $--border-radius;
+
   > .icon {
     margin-right: 5px;
   }
@@ -261,6 +255,11 @@
   .el-table__row.row-danger {
     color: $--color-danger;
   }
+  &.el-table--noback {
+    tr.el-table__row {
+      background-color: $--color-white;
+    }
+  }
 }
 // el-checkbox
 .el-checkbox {
@@ -442,3 +441,17 @@
     }
   }
 }
+
+// el-date-editor
+.el-date-editor {
+  .el-range-separator {
+    width: auto;
+    line-height: 28px;
+  }
+  .el-range-input {
+    background-color: transparent;
+  }
+  .el-input__icon {
+    line-height: 28px;
+  }
+}

+ 0 - 1
src/assets/styles/home.scss

@@ -410,7 +410,6 @@
 // other
 .tips-info {
   font-size: 14px;
-  height: 25px;
   line-height: 25px;
   color: $--color-text-secondary;
 }

+ 7 - 0
src/assets/styles/login.scss

@@ -87,4 +87,11 @@
   .el-form-item:last-child {
     margin-bottom: 0;
   }
+  .el-input__prefix {
+    left: 9px;
+    > i {
+      height: 12px;
+      width: 12px;
+    }
+  }
 }

+ 11 - 0
src/assets/styles/pages.scss

@@ -21,6 +21,17 @@
     &-infos {
       float: right;
     }
+    &-add {
+      margin-left: 15px;
+      cursor: pointer;
+      i {
+        margin-right: 5px;
+      }
+
+      &:hover {
+        color: #333;
+      }
+    }
     .el-checkbox__label {
       font-size: 16px;
       color: $--color-text-primary !important;

+ 3 - 1
src/constants/enumerate.js

@@ -132,5 +132,7 @@ export const MENU_ROUTER_DICT = {
   printManager: "PrintManage",
   cardAuditingManager: "CardAudit",
   courseManager: "CourseManage",
-  examTaskAudit: "ExamTaskAudit"
+  examTaskAudit: "ExamTaskAudit",
+  topicTaskManage: "TopicTaskManage",
+  todoExam: "TodoExam"
 };

+ 18 - 0
src/constants/navs.js

@@ -74,6 +74,24 @@ const navs = [
       {
         title: "考试任务审核",
         router: "ExamTaskAudit"
+      },
+      {
+        title: "命题任务管理",
+        router: "TopicTaskManage",
+        children: [
+          {
+            title: "编辑任务",
+            router: "TopicTaskEdit"
+          },
+          {
+            title: "新增任务",
+            router: "TopicTaskAdd"
+          }
+        ]
+      },
+      {
+        title: "待办任务",
+        router: "TodoExam"
       }
     ]
   },

+ 5 - 1
src/modules/card/components/SavePage.vue

@@ -178,9 +178,13 @@ export default {
         });
       } else {
         // barcode
+        const stdnoDom =
+          element.columnNumber <= 2
+            ? dom.querySelector(".head-stdno").parentNode
+            : dom.querySelector(".head-stdno");
         barcode.push({
           field: "examNumber",
-          area: this.getOffsetInfo(dom.querySelector(".head-stdno").parentNode)
+          area: this.getOffsetInfo(stdnoDom)
         });
       }
       // 缺考涂填

+ 35 - 0
src/modules/exam-center/api.js

@@ -65,10 +65,18 @@ export const deleteExam = examId => {
   return $post("/api/print/exam/exam/delete", { examId });
 };
 
+// todo-exam
+export const todoExamList = datas => {
+  return $get("/api/print/exam/exam/listExams", datas);
+};
+
 // course
 export const courseList = () => {
   return $get("/api/print/basic/sys/courseList", {});
 };
+export const examCourseList = examId => {
+  return $get("/api/print/exam/examTask/listCourseByExamId", { examId });
+};
 
 // card-manage
 export const cardList = datas => {
@@ -126,6 +134,33 @@ export const examTaskAudtiHistory = taskId => {
   return $get("/api/print/exam/taskAudit/listHis", { taskId });
 };
 
+// topic-task-manage
+export const topicTaskListPage = datas => {
+  return $get("/api/print/exam/examTask/listTaskPage", datas);
+};
+export const topicTaskDetail = taskId => {
+  return $get("/api/print/exam/examTask/preUpdate", { taskId });
+};
+export const topicTaskExamList = () => {
+  return $get("/api/print/exam/examTask/exams", {});
+};
+export const topicTaskExamCourseList = examId => {
+  return $get("/api/print/exam/examTask/courses", { examId });
+};
+export const topicTaskExamTeacherList = courseCode => {
+  return $get("/api/print/exam/examTask/users", { courseCode });
+};
+export const eableTopicTask = datas => {
+  return $post("/api/print/exam/examTask/enable", datas);
+};
+export const updateTopicTask = datas => {
+  if (datas.taskId) {
+    return $post("/api/print/exam/examTask/update", datas);
+  } else {
+    return $post("/api/print/exam/examTask/add", datas);
+  }
+};
+
 // custom upload-file
 export const customUpload = options => {
   let formData = new FormData();

+ 47 - 0
src/modules/exam-center/components/ExamPlanData.vue

@@ -0,0 +1,47 @@
+<template>
+  <el-dialog
+    class="exam-plan-data"
+    :visible.sync="modalIsShow"
+    title="导入考试计划数据预览"
+    top="10vh"
+    width="540px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+  >
+    <el-table ref="TableList" :data="datas" border stripe>
+      <el-table-column prop="courseName" label="科目名称"></el-table-column>
+      <el-table-column prop="courseCode" label="科目代码"></el-table-column>
+    </el-table>
+    <div slot="footer" style="text-align: right">
+      <el-button type="primary" @click="cancel">确定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: "exam-plan-data",
+  props: {
+    datas: {
+      type: Array,
+      default() {
+        return [];
+      }
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    }
+  }
+};
+</script>

+ 6 - 1
src/modules/exam-center/components/UploadFileView.vue

@@ -19,10 +19,11 @@
       :http-request="upload"
       :show-file-list="false"
       :auto-upload="false"
+      :disabled="disabled"
       style="display:inline-block;margin: 0 10px;"
       ref="UploadComp"
     >
-      <el-button type="primary">选择</el-button>
+      <el-button type="primary" :disabled="disabled">选择</el-button>
     </el-upload>
     <el-button
       type="primary"
@@ -69,6 +70,10 @@ export default {
     addFilenameParam: {
       type: String,
       default: "filename"
+    },
+    disabled: {
+      type: Boolean,
+      default: false
     }
   },
   data() {

+ 26 - 7
src/modules/exam-center/components/UploadPaperDialog.vue

@@ -2,20 +2,20 @@
   <el-dialog
     class="file-upload-view"
     :visible.sync="modalIsShow"
-    title="上传试卷文件"
+    :title="`上传${curConfig.title}`"
     top="10vh"
-    width="685px"
+    width="710px"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     append-to-body
     @opened="visibleChange"
   >
     <div class="file-upload-body">
-      <el-form label-width="75px" label-position="left">
-        <el-form-item label="试卷文件:">
+      <el-form label-position="left">
+        <el-form-item :label="`${curConfig.title}:`">
           <upload-file-view
             input-width="270px"
-            :format="['doc', 'docx', 'pdf']"
+            :format="curConfig.format"
             :upload-url="uploadUrl"
             @upload-error="uplaodError"
             @upload-success="uploadSuccess"
@@ -43,13 +43,31 @@ export default {
   components: { UploadFileView },
   props: {
     paperAttachment: {
-      type: Object
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    uploadType: {
+      type: String,
+      default: "paper",
+      validator(val) {
+        return ["paper", "paperConfirm"].includes(val);
+      }
     }
   },
   data() {
     return {
       modalIsShow: false,
       attachment: {},
+      config: {
+        paper: { title: "试卷文件", format: ["pdf"] },
+        paperConfirm: {
+          title: "试卷审核确认书文件",
+          format: ["jpg", "png"]
+        }
+      },
+      curConfig: {},
       // import
       uploadUrl: "/api/print/basic/sys/saveAttachment"
     };
@@ -60,6 +78,7 @@ export default {
         `${this.paperAttachment.filename || ""}`
       );
       this.attachment = { ...this.paperAttachment };
+      this.curConfig = this.config[this.uploadType];
     },
     // upload-handler
     uplaodError(errorData) {
@@ -82,7 +101,7 @@ export default {
       this.modalIsShow = true;
     },
     confirm() {
-      this.$emit("confirm", this.attachment);
+      this.$emit("confirm", this.attachment, this.uploadType);
       this.cancel();
     },
     async toPreview() {

+ 29 - 0
src/modules/exam-center/router.js

@@ -12,6 +12,9 @@ import ExamRomeStudentDetail from "./views/ExamRomeStudentDetail.vue";
 import CardManage from "./views/CardManage.vue";
 import ExamTaskAudit from "./views/ExamTaskAudit.vue";
 import ExamTaskAuditEdit from "./views/ExamTaskAuditEdit.vue";
+import TopicTaskManage from "./views/TopicTaskManage.vue";
+import TopicTaskModify from "./views/TopicTaskModify.vue";
+import TodoExam from "./views/TodoExam.vue";
 
 export default [
   {
@@ -112,5 +115,31 @@ export default [
     meta: {
       relate: "ExamTaskAudit/ExamTaskAuditEdit"
     }
+  },
+  {
+    path: "/exam-center/topic-task-manage",
+    name: "TopicTaskManage",
+    component: TopicTaskManage
+  },
+  {
+    path: "/exam-center/topic-task-add",
+    name: "TopicTaskAdd",
+    component: TopicTaskModify,
+    meta: {
+      relate: "TopicTaskManage/TopicTaskAdd"
+    }
+  },
+  {
+    path: "/exam-center/topic-task-edit/:taskId",
+    name: "TopicTaskEdit",
+    component: TopicTaskModify,
+    meta: {
+      relate: "TopicTaskManage/TopicTaskEdit"
+    }
+  },
+  {
+    path: "/exam-center/todo-exam",
+    name: "TodoExam",
+    component: TodoExam
   }
 ];

+ 20 - 3
src/modules/exam-center/views/DoneTaskDetail.vue

@@ -11,6 +11,7 @@
         <tr>
           <th>试卷类型</th>
           <th v-if="task.examPaper">试卷文件</th>
+          <th v-if="task.examPaper">试卷审核确认书</th>
           <th v-if="task.answerSheet">答题卡</th>
           <!-- <th>标答</th>
           <th>试卷结构</th> -->
@@ -21,10 +22,22 @@
         >
           <td>{{ attachment.name }}卷</td>
           <td class="td-link" v-if="task.examPaper">
-            <span @click="downloadPaper(attachment)" title="点击下载试卷">
+            <span
+              @click="downloadPaper(attachment, 'paper')"
+              title="点击下载试卷"
+            >
               <i class="icon icon-download-act"></i>{{ attachment.filename }}
             </span>
           </td>
+          <td class="td-link" v-if="task.examPaper">
+            <span
+              @click="downloadPaper(attachment, 'paperConfirm')"
+              title="点击下载确认书文件"
+            >
+              <i class="icon icon-download-act"></i
+              >{{ attachment.paperConfirmFilename }}
+            </span>
+          </td>
           <td
             class="td-link"
             :rowspan="pTypeEnable ? paperAttachments.length : 1"
@@ -108,8 +121,12 @@ export default {
         this.goback();
       });
     },
-    async downloadPaper(attachment) {
-      const data = await attachmentPreview(attachment.attachmentId);
+    async downloadPaper(attachment, downloadType) {
+      const attachmentId =
+        downloadType === "paper"
+          ? attachment.attachmentId
+          : attachment.paperConfirmAttachmentId;
+      const data = await attachmentPreview(attachmentId);
       window.open(data.path);
     },
     toPreviewCard() {

+ 109 - 32
src/modules/exam-center/views/ExamModify.vue

@@ -15,35 +15,64 @@
           clearable
         ></el-input>
       </el-form-item>
-      <el-form-item prop="examCodeTemp" label="考务文件:">
+      <el-form-item prop="examPlanCodeTemp" label="考试计划表:">
         <upload-file-view
-          :upload-url="uploadUrl"
+          :upload-url="uploadExamPlanUrl"
           :upload-data="uploadData"
+          :disabled="!canEdit"
           @upload-error="uplaodError"
-          @upload-success="uploadSuccess"
-          ref="UploadFileView"
+          @upload-success="uploadExamPlanSuccess"
+          ref="ExamPlanUploadFileView"
         ></upload-file-view>
-        <el-button @click="toPreview" style="margin-left:16px;">预览</el-button>
+        <el-button @click="toPreviewExamPlan" style="margin-left:16px;"
+          >预览</el-button
+        >
         <el-button
           type="warning"
-          icon="icon icon-plus"
+          icon="icon icon-download"
           style="margin-left:10px;"
         >
-          <a :href="downloadUrl" download="考务导入模板.xlsx">考务模板下载</a>
+          <a :href="planDownloadUrl" download="考试计划导入模板.xlsx"
+            >考试计划导入模板下载</a
+          >
         </el-button>
       </el-form-item>
-      <el-form-item label="考试开始时间:">
-        <p class="form-item-content" v-if="modalForm.beginTime">
-          {{ modalForm.beginTime }}
-        </p>
-        <p class="color-info" v-else>请上传考务文件</p>
+      <el-form-item label="考务编排文件:">
+        <upload-file-view
+          :upload-url="uploadExamBusinessUrl"
+          :upload-data="uploadData"
+          @upload-error="uplaodError"
+          @upload-success="uploadExamBusinessSuccess"
+          ref="ExamBusinessUploadFileView"
+        ></upload-file-view>
+        <el-button @click="toPreviewExamBusiness" style="margin-left:16px;"
+          >预览</el-button
+        >
+        <el-button
+          type="warning"
+          icon="icon icon-download"
+          style="margin-left:10px;"
+        >
+          <a :href="businessDownloadUrl" download="考务编排导入模板.xlsx"
+            >考务编排导入模板下载</a
+          >
+        </el-button>
+      </el-form-item>
+      <el-form-item prop="beginTime" label="考试开始时间:">
+        <el-date-picker
+          v-model="modalForm.beginTime"
+          type="datetime"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          placeholder="请选择时间"
+        >
+        </el-date-picker>
       </el-form-item>
       <el-form-item prop="printTime" label="打印时间:">
         <el-date-picker
           v-model="modalForm.printTime"
           type="datetime"
           value-format="yyyy-MM-dd HH:mm:ss"
-          placeholder="请选择日期"
+          placeholder="请选择时间"
         >
         </el-date-picker>
       </el-form-item>
@@ -123,7 +152,12 @@
         </el-popover>
       </el-form-item>
       <el-form-item prop="teacher" label="指派命题老师:">
-        <el-table :data="courses" style="width: 420px;" border stripe>
+        <el-table
+          class="el-table--noback"
+          :data="courses"
+          style="width: 420px;"
+          border
+        >
           <el-table-column prop="courseName" label="科目"></el-table-column>
           <el-table-column label="命题老师" width="180px">
             <template slot-scope="scope">
@@ -132,6 +166,7 @@
                 size="small"
                 style="width: 156px;"
                 placeholder="请选择"
+                :disabled="!scope.row.canEdit"
               >
                 <el-option
                   v-for="user in scope.row.users"
@@ -159,6 +194,8 @@
       :exam-code="modalForm.examCodeTemp"
       ref="BusinessData"
     ></business-data>
+    <!-- exam-plan -->
+    <exam-plan-data :datas="courses" ref="ExamPlanData"></exam-plan-data>
   </div>
 </template>
 
@@ -170,11 +207,12 @@ import {
 } from "@/constants/enumerate";
 import { uploadExam, examDetail } from "../api";
 import BusinessData from "../components/BusinessData";
+import ExamPlanData from "../components/ExamPlanData";
 import UploadFileView from "../components/UploadFileView";
 
 export default {
   name: "exam-modify",
-  components: { BusinessData, UploadFileView },
+  components: { BusinessData, ExamPlanData, UploadFileView },
   data() {
     const printTimeValidator = (rule, value, callback) => {
       if (!this.checkDateRangeValid(value, this.modalForm.beginTime)) {
@@ -206,6 +244,7 @@ export default {
     return {
       examId: this.$route.params.examId,
       modalForm: {
+        id: null,
         examName: "",
         beginTime: "",
         printTime: "",
@@ -213,6 +252,8 @@ export default {
         backup: 0,
         review: 0,
         backupCard: "",
+        examPlanCodeTemp: "",
+        examPlanAttachmentId: "",
         examCodeTemp: "",
         attachmentId: ""
       },
@@ -224,10 +265,17 @@ export default {
             trigger: "change"
           }
         ],
-        examCodeTemp: [
+        examPlanCodeTemp: [
           {
             required: true,
-            message: "请上传考务文件",
+            message: "请上传考试计划表",
+            trigger: "change"
+          }
+        ],
+        beginTime: [
+          {
+            required: true,
+            message: "请选择考试开始时间",
             trigger: "change"
           }
         ],
@@ -279,9 +327,12 @@ export default {
       printContentCheckAll: false,
       courses: [],
       isSubmit: false,
-      downloadUrl: this.GLOBAL.domain + "/temps/考务导入模板.xlsx",
+      canEdit: true,
+      planDownloadUrl: this.GLOBAL.domain + "/temps/考试计划导入模板.xlsx",
+      businessDownloadUrl: this.GLOBAL.domain + "/temps/考务编排导入模板.xlsx",
       // import
-      uploadUrl: "/api/print/exam/exam/impExamData",
+      uploadExamPlanUrl: "/api/print/exam/exam/impExamPlanData",
+      uploadExamBusinessUrl: "/api/print/exam/exam/impExamData",
       uploadData: {
         examId: ""
       }
@@ -304,15 +355,27 @@ export default {
   methods: {
     async getExamDetail() {
       const data = await examDetail(this.examId);
-      this.modalForm = Object.assign({}, this.modalForm, data.tcPExam);
+      this.modalForm = this.$objAssign(this.modalForm, data.tcPExam);
       this.modalForm.printContent = this.printContentAll.filter(
         key => data.tcPExam[key]
       );
-      this.courses = data.userCourses;
+      this.courses = data.userCourses.map(item => {
+        item.canEdit = item.status === "未开始";
+        return item;
+      });
+      this.canEdit = !this.courses.some(item => !item.canEdit);
       this.handleCheckedChange();
-      this.$refs.UploadFileView.setAttachmentName(
-        `${data.tcPAttachment.name}${data.tcPAttachment.type}`
+      this.$refs.ExamPlanUploadFileView.setAttachmentName(
+        `${data.tcPPlanAttachment.name}${data.tcPPlanAttachment.type}`
       );
+      if (
+        data.tcPAttachment &&
+        data.tcPAttachment["name"] &&
+        data.tcPAttachment["type"]
+      )
+        this.$refs.ExamBusinessUploadFileView.setAttachmentName(
+          `${data.tcPAttachment.name}${data.tcPAttachment.type}`
+        );
     },
     checkDateRangeValid(startTime, endTime) {
       if (startTime && endTime) {
@@ -334,8 +397,8 @@ export default {
         this.modalForm.printContent.length === this.printContentAll.length;
     },
     async save() {
-      // const valid = await this.$refs["ModalForm"].validate().catch(() => {});
-      // if (!valid) return;
+      const valid = await this.$refs["ModalForm"].validate().catch(() => {});
+      if (!valid) return;
 
       if (this.isSubmit) return;
       this.isSubmit = true;
@@ -363,9 +426,16 @@ export default {
       this.$message.success("保存成功!");
       this.goback();
     },
-    toPreview() {
+    toPreviewExamPlan() {
+      if (!this.modalForm.examPlanCodeTemp) {
+        this.$message.error("请先上传考试计划表!");
+        return;
+      }
+      this.$refs.ExamPlanData.open();
+    },
+    toPreviewExamBusiness() {
       if (!this.modalForm.examCodeTemp) {
-        this.$message.error("请先上传考务文件!");
+        this.$message.error("请先上传考试计划表!");
         return;
       }
       this.$refs.BusinessData.open();
@@ -374,19 +444,26 @@ export default {
     uplaodError(errorData) {
       this.$notify.error({ title: "错误提示", message: errorData.message });
     },
-    uploadSuccess(res) {
+    uploadExamPlanSuccess(res) {
       this.$message.success("上传成功!");
       const data = res.data;
 
-      this.modalForm.beginTime = data.startTime;
-      this.modalForm.examCodeTemp = data.examCode;
-      this.modalForm.attachmentId = data.attachmentId;
-      this.$refs["ModalForm"].validateField("examCodeTemp");
+      this.modalForm.examPlanCodeTemp = data.examPlanCodeTemp;
+      this.modalForm.examPlanAttachmentId = data.attachmentId;
+      this.$refs["ModalForm"].validateField("examPlanCodeTemp");
 
       this.courses = data.userCourses.map(item => {
         item.teacherId = item.users.length === 1 ? item.users[0].id + "" : "";
         return item;
       });
+    },
+    uploadExamBusinessSuccess(res) {
+      this.$message.success("上传成功!");
+      const data = res.data;
+
+      this.modalForm.examCodeTemp = data.examCode;
+      this.modalForm.attachmentId = data.attachmentId;
+      this.$refs["ModalForm"].validateField("examCodeTemp");
     }
   }
 };

+ 25 - 8
src/modules/exam-center/views/PrintManage.vue

@@ -111,14 +111,16 @@ export default {
       REVOKE_STATUS,
       exams: [],
       dataList: [],
-      setT: "",
-      IS_PRINTER: false
+      IS_PRINTER: false,
+      loopRunning: false,
+      loopSetTs: []
     };
   },
   created() {
     if (this.setT) clearInterval(this.setT);
     this.init();
-    this.setInter();
+    this.loopRunning = true;
+    this.timerUpdatePage();
   },
   methods: {
     init() {
@@ -128,10 +130,24 @@ export default {
       this.getExamList();
       this.getList();
     },
-    setInter() {
-      this.setT = setInterval(() => {
-        this.getList();
-      }, 30 * 1000);
+    clearLoopSetTs() {
+      if (!this.loopSetTs.length) return;
+      this.loopSetTs.forEach(sett => {
+        clearTimeout(sett);
+      });
+      this.loopSetTs = [];
+    },
+    async timerUpdatePage() {
+      this.clearLoopSetTs();
+      if (!this.loopRunning) return;
+
+      await this.getList().catch(() => {});
+
+      this.loopSetTs.push(
+        setTimeout(() => {
+          this.timerUpdatePage();
+        }, 30 * 1000)
+      );
     },
     async getList() {
       const datas = {
@@ -163,7 +179,8 @@ export default {
     }
   },
   beforeDestroy() {
-    if (this.setT) clearInterval(this.setT);
+    this.loopRunning = false;
+    this.clearLoopSetTs();
   }
 };
 </script>

+ 147 - 0
src/modules/exam-center/views/TodoExam.vue

@@ -0,0 +1,147 @@
+<template>
+  <div class="todo-exam">
+    <div class="part-box part-box-filter">
+      <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
+        <el-form-item label="考试名称:">
+          <el-select
+            v-model="filter.examId"
+            style="width: 193px;"
+            placeholder="请选择"
+            clearable
+          >
+            <el-option
+              v-for="item in exams"
+              :key="item.id"
+              :value="item.id"
+              :label="item.name"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label-width="0px">
+          <el-button type="primary" icon="icon icon-search" @click="toPage(1)">
+            查询
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="part-box">
+      <el-table
+        ref="TableList"
+        :data="dataList"
+        :row-class-name="tableRowClassName"
+        border
+        stripe
+      >
+        <el-table-column prop="examCode" label="考试ID"></el-table-column>
+        <el-table-column prop="examName" label="考试名称"></el-table-column>
+        <el-table-column
+          prop="printTime"
+          label="任务截止日期"
+          min-width="100"
+        ></el-table-column>
+        <el-table-column
+          prop="overTime"
+          label="剩余时间"
+          min-width="100"
+        ></el-table-column>
+        <el-table-column
+          prop="createTime"
+          label="接收时间"
+          min-width="100"
+        ></el-table-column>
+        <el-table-column
+          label="操作"
+          align="center"
+          width="120"
+          class-name="tb-action-column"
+        >
+          <template slot-scope="scope">
+            <el-button
+              class="btn-table-icon"
+              type="text"
+              icon="icon icon-edit"
+              @click="toEdit(scope.row)"
+              title="编辑"
+            ></el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { examList, todoExamList } from "../api";
+
+export default {
+  name: "todo-exam",
+  data() {
+    return {
+      filter: {
+        examId: ""
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      exams: [],
+      dataList: []
+    };
+  },
+  mounted() {
+    this.getExamList();
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size
+      };
+      const data = await todoExamList(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    async getExamList() {
+      const data = await examList();
+      this.exams = data.map(item => {
+        return {
+          id: item.id,
+          name: item.examName
+        };
+      });
+    },
+    tableRowClassName({ row }) {
+      return row.warning ? "row-danger" : "";
+    },
+    toEdit(row) {
+      this.$router.push({
+        name: "ExamEdit",
+        params: {
+          examId: row.id
+        }
+      });
+    }
+  },
+  beforeRouteLeave(to, from, next) {
+    const nextRouters = ["TopicTaskEdit"];
+    if (!nextRouters.includes(to.name)) {
+      this.$destroy();
+    }
+    next();
+  },
+  beforeRouteEnter(to, from, next) {
+    const nextRouters = ["TopicTaskEdit"];
+    if (nextRouters.includes(from.name)) {
+      next(vm => vm.$nextTick(() => vm.getList()));
+    } else {
+      next();
+    }
+  }
+};
+</script>

+ 326 - 0
src/modules/exam-center/views/TopicTaskManage.vue

@@ -0,0 +1,326 @@
+<template>
+  <div class="exam-task-manage">
+    <div class="part-box part-box-filter">
+      <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
+        <el-form-item label="考试名称:">
+          <el-select
+            v-model="filter.examId"
+            style="width: 193px;"
+            placeholder="请选择"
+            @change="examChange"
+            clearable
+          >
+            <el-option
+              v-for="item in exams"
+              :key="item.id"
+              :value="item.id"
+              :label="item.name"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="科目(代码):" label-width="110px">
+          <el-select
+            v-model="filter.courseCode"
+            style="width: 193px;"
+            placeholder="请选择"
+            clearable
+          >
+            <el-option
+              v-for="item in courses"
+              :key="item.courseCode"
+              :value="item.courseCode"
+              :label="item.courseName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="状态:" label-width="60px">
+          <el-select
+            v-model="filter.status"
+            style="width: 142px;"
+            placeholder="请选择"
+            clearable
+          >
+            <el-option
+              v-for="(val, key) in TASK_TYPES"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="提交印刷:">
+          <el-select
+            v-model="filter.printStatus"
+            style="width: 142px;"
+            placeholder="请选择"
+            clearable
+          >
+            <el-option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="启用:" label-width="60px">
+          <el-select
+            v-model="filter.enable"
+            style="width: 142px;"
+            placeholder="请选择"
+            clearable
+          >
+            <el-option
+              v-for="(val, key) in BOOLEAN_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="打印起始时间:" label-width="110px">
+          <el-date-picker
+            v-model="printTime"
+            type="daterange"
+            @change="printTimeChange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="timestamp"
+            format="yyyy-MM-dd"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label-width="0px">
+          <el-button type="primary" icon="icon icon-search" @click="toPage(1)">
+            查询
+          </el-button>
+          <el-button type="warning" icon="icon icon-plus" @click="toAdd">
+            新增命题任务
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="part-box">
+      <el-table ref="TableList" :data="dataList" border stripe>
+        <el-table-column prop="examCode" label="考试ID"></el-table-column>
+        <el-table-column prop="examName" label="考试名称"></el-table-column>
+        <el-table-column prop="courseNameCode" label="科目名称(编码)">
+        </el-table-column>
+        <el-table-column
+          prop="questionTeacherName"
+          label="命题老师"
+        ></el-table-column>
+        <el-table-column
+          prop="printTime"
+          label="打印时间"
+          min-width="100"
+        ></el-table-column>
+        <el-table-column
+          prop="beginTime"
+          label="考试时间"
+          min-width="160"
+        ></el-table-column>
+        <el-table-column prop="status" label="状态"> </el-table-column>
+        <el-table-column prop="printStatus" label="提交印刷">
+          <span slot-scope="scope">
+            {{ BOOLEAN_TYPE[scope.row.printStatus] }}
+          </span>
+        </el-table-column>
+        <el-table-column
+          label="操作"
+          align="center"
+          width="120"
+          class-name="tb-action-column"
+        >
+          <template slot-scope="scope">
+            <el-button
+              class="btn-table-icon"
+              type="text"
+              :icon="
+                scope.row.enable
+                  ? 'icon icon-circle-stop'
+                  : 'icon icon-circle-caret-right'
+              "
+              @click="toEnable(scope.row)"
+              :title="scope.row.enable ? '禁用' : '启用'"
+              v-if="!scope.row.printStatus"
+            ></el-button>
+            <el-button
+              class="btn-table-icon"
+              type="text"
+              icon="icon icon-edit"
+              @click="toEdit(scope.row)"
+              title="编辑"
+            ></el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="part-page">
+        <el-pagination
+          background
+          layout="prev, pager, next"
+          :current-page="current"
+          :total="total"
+          :page-size="size"
+          @current-change="toPage"
+        >
+        </el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { BOOLEAN_TYPE } from "@/constants/enumerate";
+import {
+  topicTaskListPage,
+  examList,
+  examCourseList,
+  eableTopicTask
+} from "../api";
+
+export default {
+  name: "exam-task-manage",
+  data() {
+    return {
+      filter: {
+        examId: "",
+        courseCode: "",
+        status: "",
+        printStatus: null,
+        enable: null,
+        printStartTime: "",
+        printEntTime: ""
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      BOOLEAN_TYPE,
+      TASK_TYPES: {
+        0: "未开始",
+        1: "进行中",
+        2: "待审核",
+        3: "已完成"
+      },
+      printTime: "",
+      exams: [],
+      courses: [],
+      dataList: []
+    };
+  },
+  mounted() {
+    this.getExamList();
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size
+      };
+      const data = await topicTaskListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    async getExamList() {
+      const data = await examList();
+      this.exams = data.map(item => {
+        return {
+          id: item.id,
+          name: item.examName
+        };
+      });
+    },
+    async getCourses() {
+      if (!this.filter.examId) return;
+      this.courses = await examCourseList(this.filter.examId);
+    },
+    examChange() {
+      this.filter.courseCode = "";
+      this.courses = [];
+      this.getCourses();
+    },
+    printTimeChange(vals) {
+      const dvals = vals || [];
+      this.filter.printStartTime = dvals[0] || null;
+      this.filter.printEntTime = dvals[1] || null;
+    },
+    toAdd() {
+      this.$router.push({ name: "TopicTaskAdd" });
+    },
+    toEnable(row) {
+      if (row.enable) {
+        const h = this.$createElement;
+        const tips = [
+          "命题老师无法查看到该任务的待办。",
+          "若试卷正在审核,则无法继续审核流程,审核界面也无法查看到该命题任务。",
+          "若试卷已经绑定了题卡,则会取消题卡绑定,但题卡仍可以在题卡管理里查看到,可与其它命题任务重新进行绑定。",
+          "被取消的命题任务不会发送印刷。",
+          "任务的数据系统和流程进度系统仍然保留。"
+        ];
+        let msgs = tips.map((item, index) =>
+          h("p", null, `${index + 1}、${item}`)
+        );
+        msgs.unshift(h("p", null, "任务取消后,会有如下影响:"));
+        msgs.push(
+          h(
+            "p",
+            { style: "margin-top: 20px;color: rgba(254, 108, 105, 1)" },
+            "确定要取消当前任务吗?"
+          )
+        );
+        this.$msgbox({
+          title: "操作警告",
+          message: h("div", { style: "text-align: left" }, msgs),
+          cancelButtonClass: "el-button--danger is-plain",
+          confirmButtonClass: "el-button--primary",
+          showCancelButton: true
+        })
+          .then(async () => {
+            this.enableTask(row);
+          })
+          .catch(() => {});
+      } else {
+        this.enableTask(row);
+      }
+    },
+    async enableTask(row) {
+      const enable = Number(!row.enable);
+      await eableTopicTask({
+        taskId: row.taskId,
+        enable
+      });
+      row.enable = enable;
+    },
+    toEdit(row) {
+      this.$router.push({
+        name: "TopicTaskEdit",
+        params: {
+          taskId: row.taskId
+        }
+      });
+    }
+  },
+  beforeRouteLeave(to, from, next) {
+    const nextRouters = ["TopicTaskAdd", "TopicTaskEdit"];
+    if (!nextRouters.includes(to.name)) {
+      this.$destroy();
+    }
+    next();
+  },
+  beforeRouteEnter(to, from, next) {
+    const nextRouters = ["TopicTaskAdd", "TopicTaskEdit"];
+    if (nextRouters.includes(from.name)) {
+      next(vm => vm.$nextTick(() => vm.getList()));
+    } else {
+      next();
+    }
+  }
+};
+</script>

+ 222 - 0
src/modules/exam-center/views/TopicTaskModify.vue

@@ -0,0 +1,222 @@
+<template>
+  <div class="topic-task-modify part-box part-box-border part-box-pad">
+    <el-form
+      ref="ModalForm"
+      :model="modalForm"
+      :rules="rules"
+      label-width="180px"
+      style="min-width:800px;"
+    >
+      <el-form-item prop="examId" label="考试名称:">
+        <el-select
+          v-model="modalForm.examId"
+          style="width: 439px;"
+          placeholder="请选择"
+          @change="examChange"
+          clearable
+          v-if="!isEdit"
+        >
+          <el-option
+            v-for="item in exams"
+            :key="item.id"
+            :value="item.id"
+            :label="item.name"
+          ></el-option>
+        </el-select>
+        <el-input
+          v-model.trim="modalForm.examName"
+          style="width: 439px;"
+          readonly
+          v-else
+        ></el-input>
+      </el-form-item>
+      <el-form-item prop="courseCode" label="科目:">
+        <el-select
+          v-model="modalForm.courseCode"
+          style="width: 439px;"
+          placeholder="请选择"
+          @change="courseChange"
+          clearable
+          v-if="!isEdit"
+        >
+          <el-option
+            v-for="item in courses"
+            :key="item.courseCode"
+            :value="item.courseCode"
+            :label="item.courseName"
+          ></el-option>
+        </el-select>
+        <el-input
+          v-model.trim="modalForm.courseName"
+          style="width: 439px;"
+          readonly
+          v-else
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="考试开始时间:">
+        <el-input
+          v-model.trim="modalForm.beginTime"
+          style="width: 439px;"
+          readonly
+        ></el-input>
+      </el-form-item>
+      <el-form-item prop="questionTeacherId" label="命题老师:">
+        <el-select
+          v-model="modalForm.questionTeacherId"
+          style="width: 439px;"
+          placeholder="请选择"
+          clearable
+        >
+          <el-option
+            v-for="item in teachers"
+            :key="item.id"
+            :value="item.id"
+            :label="item.name"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" :disabled="isSubmit" @click="save"
+          >保存</el-button
+        >
+        <el-button @click="goback">返回</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import {
+  updateTopicTask,
+  topicTaskDetail,
+  topicTaskExamList,
+  topicTaskExamCourseList,
+  topicTaskExamTeacherList
+} from "../api";
+
+export default {
+  name: "topic-task-modify",
+  data() {
+    return {
+      taskId: this.$route.params.taskId,
+      modalForm: {
+        examId: "",
+        examName: "",
+        courseCode: "",
+        courseName: "",
+        beginTime: "",
+        questionTeacherId: ""
+      },
+      curExam: {},
+      rules: {
+        examId: [
+          {
+            required: true,
+            message: "请选择考试",
+            trigger: "change"
+          }
+        ],
+        courseCode: [
+          {
+            required: true,
+            message: "请选择科目",
+            trigger: "change"
+          }
+        ],
+        questionTeacherId: [
+          {
+            required: true,
+            message: "请选择命题老师",
+            trigger: "change"
+          }
+        ]
+      },
+      exams: [],
+      courses: [],
+      teachers: [],
+      isSubmit: false
+    };
+  },
+  computed: {
+    isEdit() {
+      return !!this.taskId;
+    }
+  },
+  mounted() {
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      if (this.isEdit) {
+        await this.getTaskDetail();
+        this.getTeachers();
+      } else {
+        this.getExams();
+      }
+    },
+    async getTaskDetail() {
+      const data = await topicTaskDetail(this.taskId);
+      this.modalForm = this.$objAssign(this.modalForm, data);
+    },
+    async getExams() {
+      const data = await topicTaskExamList();
+      this.exams = data.map(item => {
+        return {
+          id: item.id,
+          name: item.examName,
+          beginTime: item.beginTime
+        };
+      });
+    },
+    async getCourses() {
+      this.courses = await topicTaskExamCourseList(this.modalForm.examId);
+    },
+    async getTeachers() {
+      this.teachers = await topicTaskExamTeacherList(this.modalForm.courseCode);
+    },
+    examChange() {
+      this.modalForm.courseCode = "";
+      this.modalForm.questionTeacherId = "";
+      this.courses = [];
+      this.teachers = [];
+      if (!this.modalForm.examId) {
+        this.curExam = {};
+        return;
+      }
+      this.curExam = this.exams.find(item => item.id === this.modalForm.examId);
+      this.modalForm.beginTime = this.curExam.beginTime;
+      this.getCourses();
+    },
+    courseChange() {
+      this.modalForm.questionTeacherId = "";
+      this.teachers = [];
+      if (!this.modalForm.courseCode) return;
+      this.getTeachers();
+    },
+    async save() {
+      const valid = await this.$refs["ModalForm"].validate().catch(() => {});
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const datas = {
+        ...this.modalForm
+      };
+      if (this.isEdit) {
+        datas.taskId = this.taskId;
+      } else {
+        const curCourse = this.courses.find(
+          item => item.courseCode === datas.courseCode
+        );
+        datas.courseName = curCourse.courseName;
+      }
+      const data = await updateTopicTask(datas).catch(() => {});
+      this.isSubmit = false;
+      if (!data) return;
+      this.$message.success("保存成功!");
+      this.goback();
+    }
+  }
+};
+</script>

+ 103 - 50
src/modules/exam-center/views/WaitTaskDetail.vue

@@ -6,9 +6,12 @@
         <span>科目名称:{{ task.courseName }}</span>
       </h2>
       <div class="task-title-infos">
-        <el-checkbox v-model="pTypeEnable" @change="pTypeEnableChange"
+        <el-checkbox v-model="pTypeEnable" disabled
           >启用{{ paperTypeFieldContent }}卷</el-checkbox
         >
+        <span class="task-title-add" @click="addAtachment">
+          <i class="icon icon-plus-act"></i>增加卷型
+        </span>
       </div>
     </div>
     <div class="task-body">
@@ -16,12 +19,14 @@
         <tr>
           <th>试卷类型</th>
           <th v-if="task.examPaper">试卷文件</th>
+          <th v-if="task.examPaper">试卷审核确认书</th>
           <th v-if="task.answerSheet">答题卡</th>
+          <th>操作</th>
         </tr>
         <tr v-for="(attachment, index) in curPaperAttachments" :key="index">
           <td>{{ attachment.name }}卷</td>
           <td class="td-link" v-if="task.examPaper">
-            <span @click="toUpload(attachment)" title="点击上传试卷">
+            <span @click="toUpload(attachment, 'paper')" title="点击上传试卷">
               <i
                 :class="[
                   'icon',
@@ -35,6 +40,26 @@
               }}
             </span>
           </td>
+          <td class="td-link" v-if="task.examPaper">
+            <span
+              @click="toUpload(attachment, 'paperConfirm')"
+              title="点击上传确认书文件"
+            >
+              <i
+                :class="[
+                  'icon',
+                  attachment.paperConfirmAttachmentId
+                    ? 'icon-files-act'
+                    : 'icon-files'
+                ]"
+              ></i
+              >{{
+                attachment.paperConfirmAttachmentId
+                  ? attachment.paperConfirmFilename
+                  : "点击上传确认书文件"
+              }}
+            </span>
+          </td>
           <td
             class="td-link"
             :rowspan="pTypeEnable ? curPaperAttachments.length : 1"
@@ -44,6 +69,15 @@
               ><i class="icon icon-plus-act"></i>{{ cardTodoName }}</span
             >
           </td>
+          <td>
+            <el-button
+              class="btn-table-icon"
+              type="text"
+              icon="icon icon-delete"
+              title="删除"
+              @click="deleteAttachment(index)"
+            ></el-button>
+          </td>
         </tr>
       </table>
 
@@ -86,6 +120,7 @@
     <!-- upload-paper-dialog -->
     <upload-paper-dialog
       :paper-attachment="curAttachment"
+      :upload-type="curUploadType"
       @confirm="uploadConfirm"
       ref="UploadPaperDialog"
     ></upload-paper-dialog>
@@ -136,27 +171,26 @@ export default {
         paperSticker: 0,
         review: 1,
         auditStatus: 0,
-        remark:
-          "这是按税法二,的啊ad框架,安大街开始的罚款案件发,发生的叫法卡是的罚款是安抚,继发技术附件发卡上开发发顺丰,发斯蒂芬咖啡机大法级法师打发斯蒂芬阿道夫。"
+        remark: ""
       },
-      pTypeEnable: false,
       paperAttachments: [],
       curPaperAttachments: [],
       curAttachment: {},
+      curUploadType: "paper",
+      attachmentLimitCount: 4,
+      abc: "",
       // audit history
       modalIsShow: false,
-      auditHistory: [
-        {
-          createTime: "2020-01-15 15:15:15",
-          remark: "这是很航的阿克苏就按"
-        }
-      ]
+      auditHistory: []
     };
   },
   computed: {
     paperTypeFieldContent() {
       return this.PAPER_TYPE_FIELDS.join("/");
     },
+    pTypeEnable() {
+      return this.curPaperAttachments.length > 1;
+    },
     cardTodoName() {
       let name = "创建答题卡";
       if (this.task.cardId) {
@@ -173,6 +207,9 @@ export default {
     }
   },
   mounted() {
+    this.abc = "abcdefghijklmnopqrstuvwxyz"
+      .toUpperCase()
+      .slice(0, this.attachmentLimitCount);
     this.getData();
   },
   methods: {
@@ -184,11 +221,14 @@ export default {
         courseName: nameCode[0],
         courseCode: nameCode[1]
       });
-      this.pTypeEnable =
-        this.task.enablePaperType &&
-        this.task.enablePaperType.split(",").length > 1;
-      this.parsePaperAttachment();
-      this.pTypeEnableChange(this.pTypeEnable);
+
+      const paperAttachment =
+        this.task.paperAttachmentId && JSON.parse(this.task.paperAttachmentId);
+      this.paperAttachments = paperAttachment && paperAttachment.paper;
+      this.curPaperAttachments = this.paperAttachments.map(item => {
+        return { ...item };
+      });
+      this.task.enablePaperType = this.getEnablePaperType();
 
       if (this.task.review && this.task.auditStatus === 2)
         this.getHistoryList();
@@ -196,45 +236,58 @@ export default {
     async getHistoryList() {
       this.auditHistory = await examTaskAudtiHistory(this.taskId);
     },
-    parsePaperAttachment() {
-      const paperAttachment =
-        this.task.paperAttachmentId && JSON.parse(this.task.paperAttachmentId);
-      const papers = paperAttachment && paperAttachment.paper;
-      let paperDict = {};
-      if (papers) {
-        papers.map(paper => {
-          paperDict[paper.name] = paper;
-        });
+    addAtachment() {
+      if (this.curPaperAttachments.length >= this.attachmentLimitCount) return;
+
+      const newAttachment = {
+        name: this.abc[this.curPaperAttachments.length],
+        attachmentId: "",
+        filename: "",
+        paperConfirmAttachmentId: "",
+        paperConfirmFilename: ""
+      };
+      this.curPaperAttachments.push(newAttachment);
+    },
+    deleteAttachment(index) {
+      if (this.curPaperAttachments.length <= 1) {
+        this.$message.error("试卷类型数量不得少于1");
+        return;
       }
-      this.paperAttachments = this.PAPER_TYPE_FIELDS.map(paperType => {
-        const paperInfo = paperDict[paperType];
-        let paper = {
-          attachmentId: "",
-          name: paperType
-        };
-        return paperInfo ? Object.assign({}, paper, paperInfo) : paper;
+      this.curPaperAttachments.splice(index, 1);
+      this.curPaperAttachments.forEach((item, itemIndex) => {
+        item.name = this.abc[itemIndex];
       });
     },
-    pTypeEnableChange(val) {
-      this.curPaperAttachments = val
-        ? this.paperAttachments
-        : [this.paperAttachments[0]];
-      this.task.enablePaperType = this.getEnablePaperType();
-    },
-    toUpload(attachment) {
-      this.curAttachment = { ...attachment };
+    toUpload(attachment, uploadType) {
+      this.curUploadType = uploadType;
+      this.curAttachment = {
+        name: attachment.name,
+        attachmentId:
+          uploadType === "paper"
+            ? attachment.attachmentId
+            : attachment.paperConfirmAttachmentId,
+        filename:
+          uploadType === "paper"
+            ? attachment.filename
+            : attachment.paperConfirmFilename
+      };
       this.$refs.UploadPaperDialog.open();
     },
-    uploadConfirm(attachment) {
-      this.curAttachment = Object.assign(this.curAttachment, attachment);
-      const index = this.paperAttachments.findIndex(
+    uploadConfirm(attachment, uploadType) {
+      if (uploadType !== "paper")
+        attachment = {
+          name: attachment.name,
+          paperConfirmAttachmentId: attachment.attachmentId,
+          paperConfirmFilename: attachment.filename
+        };
+      const index = this.curPaperAttachments.findIndex(
         item => item.name === attachment.name
       );
-      this.paperAttachments.splice(index, 1, { ...this.curAttachment });
-      this.pTypeEnableChange(this.pTypeEnable);
-      this.task.paperAttachmentId = JSON.stringify({
-        paper: this.curPaperAttachments
-      });
+      const curAttachment = Object.assign(
+        this.curPaperAttachments[index],
+        attachment
+      );
+      this.curPaperAttachments.splice(index, 1, { ...curAttachment });
     },
     toCreateCard() {
       if (this.task.cardId) {
@@ -288,10 +341,10 @@ export default {
     },
     checkDataValid() {
       const attachmentValid = !this.curPaperAttachments.some(
-        item => !item.attachmentId
+        item => !item.attachmentId || !item.paperConfirmAttachmentId
       );
       if (this.task.examPaper && !attachmentValid) {
-        this.$message.error("请完成试卷文件上传!");
+        this.$message.error("请完成试卷文件和试卷审核确认书上传!");
         return;
       }
 

+ 17 - 1
src/views/Home.vue

@@ -188,6 +188,9 @@ export default {
       curSubIndex: 0,
       breadcrumbs: [],
       username: this.$ls.get("user", { name: "" }).name,
+      IS_SUPER_ADMIN: this.$ls
+        .get("user", { roleCode: "" })
+        .roleCode.includes("SUPER_ADMIN"),
       menuDailogIsShow: false,
       cacheRouters: [
         "wait-task",
@@ -196,7 +199,9 @@ export default {
         "exam-room-detail",
         "exam-task-audit",
         "card-manage",
-        "user-manage"
+        "user-manage",
+        "exam-task-manage",
+        "todo-exam"
       ]
     };
   },
@@ -244,6 +249,16 @@ export default {
       }
     },
     menusToTree(menus) {
+      if (this.IS_SUPER_ADMIN) {
+        const names = {
+          todoExam: "待办任务(考务)",
+          todoTaskManager: "待办任务(命题)",
+          doneTaskManager: "已办任务(命题)"
+        };
+        menus.forEach(item => {
+          item.name = names[item.url] || item.name;
+        });
+      }
       let navTree = deepCopy(localNavs);
       let validRoutes = [];
       const anchorNav = (menu, navs) => {
@@ -251,6 +266,7 @@ export default {
         navs.forEach(item => {
           if (item.router === name) {
             item.fixed = true;
+            item.title = menu.name;
             validRoutes.push(item.router);
 
             if (menu.parentId !== null && item["children"]) {