zhangjie hace 4 años
padre
commit
abf658205e
Se han modificado 36 ficheros con 745 adiciones y 718 borrados
  1. 12 12
      card/api.js
  2. 1 3
      card/components/PagePropEdit.vue
  3. 4 1
      card/elements/card-head/CardHead.vue
  4. 8 8
      card/elements/card-head/cardHeadSpin/HeadDynamic.vue
  5. 4 6
      card/elements/card-head/cardHeadSpin/HeadNotice.vue
  6. 7 6
      card/elements/card-head/cardHeadSpin/HeadStdinfo.vue
  7. 3 4
      card/elements/card-head/cardHeadSpin/HeadStdno.vue
  8. 5 49
      card/enumerate.js
  9. 27 21
      card/views/CardDesign.vue
  10. 2 2
      src/assets/styles/element-ui-costom.scss
  11. 1 1
      src/assets/styles/home.scss
  12. 82 0
      src/assets/styles/pages.scss
  13. 0 10
      src/constants/enumerate.js
  14. 1 1
      src/main.js
  15. 0 79
      src/modules/base/components/BusinessFields.vue
  16. 133 0
      src/modules/base/components/CardTitleRuleEdit.vue
  17. 23 9
      src/modules/base/components/ModifyCardRule.vue
  18. 13 0
      src/modules/base/components/ModifyRole.vue
  19. 14 5
      src/modules/base/components/RuleBusiness.vue
  20. 0 227
      src/modules/base/components/RuleCard.vue
  21. 0 139
      src/modules/base/components/RuleExamroom.vue
  22. 0 70
      src/modules/base/components/RuleWarning.vue
  23. 0 1
      src/modules/base/components/SelectOrgs.vue
  24. 12 1
      src/modules/base/views/CardRuleManage.vue
  25. 0 15
      src/modules/card/api.js
  26. 0 3
      src/modules/card/enumerate.js
  27. 14 10
      src/modules/exam/components/ApplyContent.vue
  28. 6 5
      src/modules/exam/components/CardOptionDialog.vue
  29. 2 1
      src/modules/exam/components/ModifyExamTask.vue
  30. 111 0
      src/modules/exam/components/WaitTaskAudit.vue
  31. 103 0
      src/modules/exam/components/WaitTaskExam.vue
  32. 103 0
      src/modules/exam/components/WaitTaskExamTask.vue
  33. 46 4
      src/modules/exam/views/WaitTask.vue
  34. 3 0
      src/modules/login/api.js
  35. 1 18
      src/store.js
  36. 4 7
      src/views/Home.vue

+ 12 - 12
card/api.js

@@ -1,7 +1,7 @@
 import { $get, $post } from "@/plugins/axios";
 
-export const cardConfigInfos = () => {
-  return $get("/api/print/basic/cardRule/selectBySchoolId", {});
+export const cardConfigInfos = id => {
+  return $get("/api/basic/card_rule/get_one", { id });
 
   // return Promise.resolve({
   //   pageSize: "A3",
@@ -9,39 +9,39 @@ export const cardConfigInfos = () => {
   //   columnGap: 20,
   //   showForbidArea: true,
   //   cardName: "",
-  //   missAndFill: true,
+  //   examAbsent: true,
   //   writeSign: true,
-  //   examNumberStyle: "auto", // auto:自动条码, empty:手动条码, fill:手动涂填
+  //   examNumberStyle: "PRINT", // PRINT:印刷条码, PASTE:粘贴条码, FILL:考号填涂
   //   aOrBSystem: true, // 后台附带的aOrB设置,如果有则使用这个值,如果没有则前台自动设置
-  //   aOrBType: "auto", // fill:手动涂填,auto:自动条码
+  //   paperType: "PRINT", // PRINT: "印刷",FILL: "填涂"
   //   schoolName: "河南财经政法大学", // cartTitle
   //   cardTitleDesc: "",
   //   businessParams: [
   //     {
   //       name: "学号",
-  //       field: "studentNo"
+  //       code: "studentNo"
   //     },
   //     {
   //       name: "姓名",
-  //       field: "username"
+  //       code: "username"
   //     },
   //     {
   //       name: "课程名称",
-  //       field: "courseName"
+  //       code: "courseName"
   //     },
   //     {
   //       name: "课程名称",
-  //       field: "subjectName"
+  //       code: "subjectName"
   //     }
   //   ],
-  //   noticeHead: [
+  //   attention: [
   //     "答题前,请考生认真核对姓名、学号、教学班号、课程名称等信息,确认无误后签名。",
   //     "客观题部分必须使用2B铅笔填涂,主观题部分请使用黑色签字笔写在指定的答题区内。",
   //     "保持卡面清洁,不破损。"
   //   ],
-  //   objectiveNotice:
+  //   objectiveAttention:
   //     "注意:必须使用2B铅笔填涂;在答题区内作答,超出涂填边框限定区域的答案无效。",
-  //   subjectiveNotice:
+  //   subjectiveAttention:
   //     "注意:必须使用黑色字迹签字笔书写;在答题区内作答,超出以下黑色矩形边框限定区域的答案无效。"
   // });
 };

+ 1 - 3
card/components/PagePropEdit.vue

@@ -40,9 +40,7 @@
         </el-button>
       </el-form-item>
       <el-form-item label-width="0px">
-        <el-checkbox v-model="form.aOrB" @change="configChange"
-          >启用A/B卷</el-checkbox
-        >
+        <el-checkbox v-model="form.aOrB" disabled>启用A/B卷</el-checkbox>
       </el-form-item>
       <el-form-item label-width="0px">
         <el-checkbox

+ 4 - 1
card/elements/card-head/CardHead.vue

@@ -156,9 +156,12 @@ export default {
       return !noDynamic;
     }
   },
-  mounted() {},
+  // created() {
+  //   this.initCardTitle();
+  // },
   methods: {
     ...mapMutations("card", ["setCardConfig"]),
+    // initCardTitle() {},
     nameChange() {
       this.setCardConfig({
         cardName: this.cardName,

+ 8 - 8
card/elements/card-head/cardHeadSpin/HeadDynamic.vue

@@ -3,7 +3,7 @@
     <!-- write -->
     <div
       class="head-dynamic-part head-dynamic-write"
-      v-if="data.examNumberStyle !== 'fill' && data.writeSign"
+      v-if="data.examNumberStyle !== 'FILL' && data.writeSign"
     >
       <div class="stdinfo-item">
         <span>手写签名</span>
@@ -16,7 +16,7 @@
     </div>
     <!-- miss-fill -->
     <div class="head-dynamic-part head-dynamic-missfill">
-      <div class="head-dynamic-miss" v-if="data.missAndFill">
+      <div class="head-dynamic-miss" v-if="data.examAbsent">
         <div class="head-dynamic-content">
           <span class="dynamic-miss-title">缺考标记</span>
           <span class="dynamic-miss-body"
@@ -42,7 +42,7 @@
       :class="[
         'head-dynamic-part',
         'head-dynamic-aorb',
-        `head-dynamic-aorb-${data.aOrBType}`
+        `head-dynamic-aorb-${data.paperType.toLowerCase()}`
       ]"
       id="head-dynamic-aorb"
       v-if="data.aOrB"
@@ -52,7 +52,7 @@
       </div>
       <div
         class="dynamic-aorb-item dynamic-aorb-rects"
-        v-if="data.aOrBType === 'fill'"
+        v-if="data.paperType === 'FILL'"
       >
         <div class="dynamic-aorb-content">
           <span class="head-dynamic-rect"><i>A</i></span>
@@ -61,7 +61,7 @@
       </div>
       <div
         class="dynamic-aorb-item dynamic-aorb-info"
-        v-if="data.aOrBType === 'auto'"
+        v-if="data.paperType === 'PRINT'"
       >
         <div class="dynamic-aorb-content">
           <i>{{ aorbBarcodeName }}</i>
@@ -70,7 +70,7 @@
       <div
         class="dynamic-aorb-item dynamic-aorb-barcode"
         id="dynamic-aorb-barcode"
-        v-if="data.aOrBType === 'auto'"
+        v-if="data.paperType === 'PRINT'"
       >
         <div class="dynamic-aorb-content">
           <img :src="aorbBarcodeSrc" v-if="aorbBarcodeSrc" />
@@ -103,7 +103,7 @@ export default {
   computed: {
     classes() {
       let partNum = 1;
-      if (this.data.examNumberStyle !== "fill" && this.data.writeSign)
+      if (this.data.examNumberStyle !== "FILL" && this.data.writeSign)
         partNum++;
       if (this.data.aOrB) partNum++;
 
@@ -115,7 +115,7 @@ export default {
   },
   methods: {
     initStyles() {
-      if (this.data.examNumberStyle === "fill" || this.data.columnNumber !== 2)
+      if (this.data.examNumberStyle === "FILL" || this.data.columnNumber !== 2)
         return;
       const parentHeight = this.$el.parentNode.offsetHeight;
       this.$el.style.height = parentHeight + "px";

+ 4 - 6
card/elements/card-head/cardHeadSpin/HeadNotice.vue

@@ -1,11 +1,7 @@
 <template>
   <div :class="classes">
     <h4>注意事项:</h4>
-    <div
-      class="head-notice-cont"
-      v-for="(cont, index) in data.noticeHead"
-      :key="index"
-    >
+    <div class="head-notice-cont" v-for="(cont, index) in notices" :key="index">
       <span>{{ index + 1 }}、</span>
       <span>{{ cont }}</span>
     </div>
@@ -32,9 +28,11 @@ export default {
           "head-notice-exam-number-fill": this.data.examNumberStyle === "fill"
         }
       ];
+    },
+    notices() {
+      return this.data.attention.split("\n") || [];
     }
   },
-  mounted() {},
   methods: {}
 };
 </script>

+ 7 - 6
card/elements/card-head/cardHeadSpin/HeadStdinfo.vue

@@ -1,10 +1,6 @@
 <template>
   <div class="head-stdinfo card-head-body-spin">
-    <div
-      class="stdinfo-item"
-      v-for="(info, index) in data.businessParams"
-      :key="index"
-    >
+    <div class="stdinfo-item" v-for="(info, index) in fields" :key="index">
       <span :style="paramStyle">{{ info.name }}</span>
       <span>:</span>
       <span>{{ fieldInfos[info.field] }}</span>
@@ -23,6 +19,7 @@ export default {
   data() {
     return {
       fieldInfos: this.data["fieldInfos"] || {},
+      fields: [],
       paramStyle: {},
       lenWidths: {
         3: 42,
@@ -39,7 +36,11 @@ export default {
   },
   methods: {
     init() {
-      const nameNums = this.data.businessParams.map(item => item.name.length);
+      this.fields = [
+        ...this.data.requiredFields,
+        ...this.data.extendFields
+      ].filter(item => item.enable);
+      const nameNums = this.fields.map(item => item.name.length);
       const maxNameLen = Math.max.apply(null, nameNums);
       const num = maxNameLen < 3 ? 3 : maxNameLen > 8 ? 8 : maxNameLen;
       this.paramStyle = {

+ 3 - 4
card/elements/card-head/cardHeadSpin/HeadStdno.vue

@@ -1,16 +1,16 @@
 <template>
   <div :class="classes">
-    <div class="stdno-empty" v-if="data.examNumberStyle === 'empty'">
+    <div class="stdno-empty" v-if="data.examNumberStyle === 'PASTE'">
       <p class="">粘贴条形码区</p>
     </div>
-    <div class="stdno-auto" v-if="data.examNumberStyle === 'auto'">
+    <div class="stdno-auto" v-if="data.examNumberStyle === 'PRINT'">
       <div class="stdno-auto-barcode">
         <img :src="examNumberBarcodeSrc" v-if="examNumberBarcodeSrc" />
         <img src="../../../assets/images/barcode-sample-notext.png" v-else />
         <p>{{ examNumberBarcodeName || "123456789" }}</p>
       </div>
     </div>
-    <div class="stdno-fill" v-if="data.examNumberStyle === 'fill'">
+    <div class="stdno-fill" v-if="data.examNumberStyle === 'FILL'">
       <div class="stdno-fill-head">
         <h5>准考证号</h5>
         <div class="stdno-fill-rect">
@@ -49,7 +49,6 @@ export default {
       return ["head-stdno", "card-head-body-spin"];
     }
   },
-  mounted() {},
   methods: {}
 };
 </script>

+ 5 - 49
card/enumerate.js

@@ -1,24 +1,14 @@
 export const CARD_VERSION = "1.0.0";
 
 export const EXAM_NUMBER_STYLE = {
-  0: "印刷条码",
-  1: "粘贴条码",
-  2: "考号填涂"
-};
-export const EXAM_NUMBER_STYLE_MAP = {
-  0: "auto",
-  1: "empty",
-  2: "fill"
+  PRINT: "印刷条码",
+  PASTE: "粘贴条码",
+  FILL: "考号填涂"
 };
 
 export const PAPER_TYPE = {
-  0: "印刷",
-  1: "填涂"
-};
-
-export const PAPER_TYPE_MAP = {
-  0: "auto",
-  1: "fill"
+  PRINT: "印刷",
+  FILL: "填涂"
 };
 
 export const BOOLEAN_TYPE = ["√,×", "是,否", "对,错"];
@@ -27,37 +17,3 @@ export const DIRECTION_TYPE = {
   horizontal: "横向",
   vertical: "纵向"
 };
-
-export const transformField = data => {
-  const businessParams = [
-    ...JSON.parse(data.examMustColumn),
-    ...JSON.parse(data.examExtendColumn)
-  ]
-    .filter(item => item.select)
-    .map(item => {
-      return {
-        name: item.name,
-        field: item.code
-      };
-    });
-
-  const config = {
-    missAndFill: !!data.examAbsent,
-    writeSign: !!data.writeSign,
-    examNumberStyle: EXAM_NUMBER_STYLE_MAP[data.examNumberStyle], // auto:自动条码, empty:手动条码, fill:手动涂填
-    // aOrBSystem: true, // 后台附带的aOrB设置,如果有则使用这个值,如果没有则前台自动设置
-    aOrBType: PAPER_TYPE_MAP[data.paperType], // fill:手动涂填,auto:自动条码
-    schoolName: data.schoolName,
-    businessParams,
-    noticeHead: data.attention.split("\n") || [],
-    objectiveNotice: data.objectiveAttention,
-    subjectiveNotice: data.subjectiveAttention
-  };
-  return config;
-};
-
-export const getAOrBSystem = data => {
-  return data["enablePaperType"]
-    ? data.enablePaperType.split(",").length > 1
-    : null;
-};

+ 27 - 21
card/views/CardDesign.vue

@@ -2,11 +2,11 @@
   <div class="card-design">
     <div class="design-top">
       <div class="design-top-logo">
-        <h1><i class="icon icon-back" @click="toExit"></i>答题卡制作</h1>
+        <h1>答题卡制作</h1>
       </div>
-      <div class="design-top-info">
+      <!-- <div class="design-top-info">
         <div class="info-help"><i class="icon icon-help"></i>帮助</div>
-      </div>
+      </div> -->
     </div>
 
     <div class="design-main">
@@ -258,7 +258,7 @@ import {
   ELEMENT_LIST,
   TOPIC_LIST
 } from "../elementModel";
-import { transformField, getAOrBSystem, CARD_VERSION } from "../enumerate";
+import { CARD_VERSION } from "../enumerate";
 // import CardConfigPropEdit from "../components/CardConfigPropEdit";
 import TopicElementEdit from "../components/TopicElementEdit";
 import TopicElementPreview from "../components/TopicElementPreview";
@@ -320,6 +320,10 @@ export default {
     }
   },
   mounted() {
+    if (!this.prepareTcPCard.examTaskId) {
+      this.$message.error("找不到命题任务,请退出题卡制作!");
+      return;
+    }
     this.initCard();
     this.registWindowSubmit();
   },
@@ -354,11 +358,11 @@ export default {
       }
       this.addWatch();
     },
-    async getCardTempDetail(content) {
+    async getCardTempDetail() {
       const detData = await cardDetailEdit(this.cardId);
       const tempData = await cardTempDetail(this.cardId);
-      this.canSave = !detData.operateStatus;
-      this.prepareTcPCard = Object.assign(this.prepareTcPCard, detData);
+      // this.canSave = !detData.operateStatus;
+      // this.prepareTcPCard = Object.assign(this.prepareTcPCard, detData);
 
       // 可能存在题卡内容没有记录的情况
       if (tempData) {
@@ -389,22 +393,24 @@ export default {
       });
     },
     async getCardConfig() {
-      const data = await cardConfigInfos();
+      const data = await cardConfigInfos(this.prepareTcPCard.cardRuleId);
       if (!data) {
-        this.$message.error("请先配置题卡规则!");
+        this.$message.error("找不到题卡规则!");
         return;
       }
-      const aOrBSystem = getAOrBSystem(this.prepareTcPCard);
       let config = {
-        ...transformField(data),
-        pageSize: "A3",
-        columnNumber: 2,
-        columnGap: 20,
-        showForbidArea: true,
-        cardName: ""
+        ...data,
+        ...{
+          pageSize: "A3",
+          columnNumber: 2,
+          columnGap: 20,
+          showForbidArea: true,
+          cardName: ""
+        }
       };
-      if (aOrBSystem !== null) config.aOrBSystem = aOrBSystem;
-      config.aOrB = !!config["aOrBSystem"];
+      config.aOrB = this.prepareTcPCard["paperType"]
+        ? this.prepareTcPCard.paperType.split(",").length > 1
+        : null;
       this.setCardConfig(config);
     },
     addNewTopic(item) {
@@ -473,9 +479,9 @@ export default {
     // save
     getCardData(contentTemp = "", model = "") {
       const multiEnablePaperType =
-        this.prepareTcPCard["enablePaperType"] &&
-        this.prepareTcPCard["enablePaperType"].split(",").length > 1
-          ? this.prepareTcPCard["enablePaperType"]
+        this.prepareTcPCard["paperType"] &&
+        this.prepareTcPCard["paperType"].split(",").length > 1
+          ? this.prepareTcPCard["paperType"]
           : "";
       const tcPCard = this.$objAssign(
         {

+ 2 - 2
src/assets/styles/element-ui-costom.scss

@@ -147,12 +147,12 @@
 }
 .el-button--default {
   color: $--color-text-regular;
-  background: $--color-background;
+  background: $--color-white;
   border: 1px solid $--color-border;
   &:hover,
   &:focus {
     color: $--color-text-regular;
-    background: $--color-white;
+    background: $--color-background;
     border: 1px solid $--color-border;
   }
   &.el-button--default-act {

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

@@ -68,7 +68,7 @@
     }
     > span {
       display: inline-block;
-      vertical-align: middle;
+      vertical-align: top;
     }
   }
 

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

@@ -92,6 +92,88 @@
     }
   }
 }
+// task-list
+.task-head {
+  font-size: 16px;
+
+  i {
+    cursor: pointer;
+
+    &:hover {
+      color: $--color-primary;
+    }
+  }
+}
+.task-list {
+  .task-item {
+    margin-bottom: 15px;
+    padding: 15px;
+    border-radius: $--border-radius;
+    background-color: $--color-background;
+
+    p {
+      line-height: 1.5;
+      margin-bottom: 5px;
+      > span:first-child {
+        color: $--color-text-regular;
+      }
+    }
+  }
+  .task-action {
+    cursor: pointer;
+    &:hover {
+      color: $--color-primary;
+    }
+  }
+}
+// wait-task
+.wait-task {
+  .wait-module {
+    height: 100%;
+  }
+}
+// card-title-rule-edit
+.card-title-rule-edit {
+  .field-item {
+    display: inline-block;
+    vertical-align: top;
+    margin: 0 10px 10px 0;
+    padding: 8px 10px;
+    border-radius: 4px;
+    line-height: 1;
+    background-color: $--color-background;
+    cursor: pointer;
+
+    &:hover {
+      color: $--color-primary;
+    }
+    &-act {
+      background-color: $--color-primary;
+      color: #fff !important;
+    }
+  }
+  .field-textarea {
+    border-radius: $--border-radius;
+    border: 1px solid $--border-color-base;
+    min-height: 60px;
+    padding: 2px;
+    overflow: hidden;
+
+    &:focus {
+      border-color: $--color-primary;
+    }
+
+    span.var-field {
+      display: inline-block;
+      vertical-align: middle;
+      padding: 3px 5px;
+      background-color: $--color-primary;
+      color: $--color-white;
+      line-height: 1;
+      border-radius: 3px;
+    }
+  }
+}
 
 // rule-warning
 .rule-warning {

+ 0 - 10
src/constants/enumerate.js

@@ -177,13 +177,3 @@ export const ROLE_TYPE = {
   PRINT: "印刷人员",
   CUSTOM: "自定义"
 };
-
-export const keepAliveRoutesPairs = [
-  ["wait-task", ["wait-task-detail"]],
-  ["done-task", ["done-task-detail"]],
-  ["exam-manage", ["exam-room-detail", "exam-edit"]],
-  ["exam-task-audit", ["exam-task-audit-edit"]],
-  ["user-manage", ["user-edit"]],
-  ["topic-task-manage", ["topic-task-edit"]],
-  ["todo-exam", ["exam-edit"]]
-];

+ 1 - 1
src/main.js

@@ -7,7 +7,7 @@ import store from "./store";
 import globalVuePlugins from "./plugins/globalVuePlugins";
 import GLOBAL from "./config";
 import { jsonBigNumberToString } from "./plugins/utils";
-import "./plugins/keepAlive";
+// import "./plugins/keepAlive";
 import "./plugins/filters";
 // import { getAuthorisation } from "./plugins/crypto";
 

+ 0 - 79
src/modules/base/components/BusinessFields.vue

@@ -1,79 +0,0 @@
-<template>
-  <div class="business-fields">
-    <h3>题卡版头变量印刷字段配置:</h3>
-    <el-form ref="ModalForm" label-width="90px">
-      <el-form-item label="必选字段:">
-        <el-checkbox
-          v-for="column in mustColumns"
-          :key="column.code"
-          v-model="column.select"
-          disabled
-          >{{ column.name }}</el-checkbox
-        >
-      </el-form-item>
-      <el-form-item label="扩展字段:">
-        <el-checkbox
-          v-for="column in extendColumns"
-          :key="column.code"
-          v-model="column.select"
-          >{{ column.name }}</el-checkbox
-        >
-      </el-form-item>
-    </el-form>
-  </div>
-</template>
-
-<script>
-import { CARD_BUSINESS_FIELDS } from "@/constants/enumerate";
-
-export default {
-  name: "business-fields",
-  props: {
-    data: {
-      type: Object
-    }
-  },
-  data() {
-    return {
-      mustColumns: [],
-      extendColumns: [],
-      // import
-      uploadUrl: "/api/print/basic/cardRule/impExtendColums"
-    };
-  },
-  computed: {
-    examExtendColumn() {
-      return { examExtendColumn: JSON.stringify(this.extendColumns) };
-    }
-  },
-  mounted() {
-    this.mustColumns = CARD_BUSINESS_FIELDS.must.map(item => {
-      item.select = true;
-      return item;
-    });
-    if (this.data.examExtendColumn) {
-      this.extendColumns = JSON.parse(this.data.examExtendColumn);
-    } else {
-      this.extendColumns = CARD_BUSINESS_FIELDS.extend.map(item => {
-        item.select = false;
-        return item;
-      });
-    }
-  },
-  methods: {
-    uplaodError(errorData) {
-      this.$notify.error({ title: "错误提示", message: errorData.message });
-    },
-    uploadSuccess(response) {
-      this.$message.success("导入成功!");
-      this.extendColumns = response.data;
-    },
-    getSelectColumns() {
-      return {
-        examMustColumn: JSON.stringify(this.mustColumns),
-        examExtendColumn: JSON.stringify(this.extendColumns)
-      };
-    }
-  }
-};
-</script>

+ 133 - 0
src/modules/base/components/CardTitleRuleEdit.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="card-title-rule-edit">
+    <div class="field-list">
+      <div
+        v-for="field in fields"
+        :key="field.code"
+        :class="['field-item', { 'field-item-act': field.selected }]"
+        @mousedown="event => selectField(field, event)"
+      >
+        {{ field.name }}({{ field.code }})
+      </div>
+    </div>
+    <el-input
+      type="textarea"
+      resize="none"
+      :rows="2"
+      placeholder="请输入内容"
+      v-model="content"
+      @input="contentChange"
+      ref="FieldTextarea"
+    >
+    </el-input>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "card-title-rule-edit",
+  props: {
+    value: {
+      type: String,
+      default: ""
+    },
+    fieldSourses: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      fields: [],
+      fieldNameToCode: {},
+      fieldCodeToName: {},
+      frameWin: null,
+      content: ""
+    };
+  },
+  watch: {
+    fieldSourses: {
+      immediate: true,
+      handler(val) {
+        this.rebuildTextarea();
+        this.setFields(val);
+        this.updateFieldStatus();
+      }
+    },
+    value: {
+      immediate: true,
+      handler(val) {
+        if (!val) return;
+        this.content = val;
+        this.updateFieldStatus();
+      }
+    }
+  },
+  methods: {
+    setFields(data) {
+      const selectedCodes = this.fields
+        .filter(item => item.selected)
+        .map(item => item.code);
+      this.fields = data.map(item => {
+        item.selected = selectedCodes.includes(item.code);
+        return item;
+      });
+      this.fields.forEach(field => {
+        this.fieldNameToCode[field.name] = field.code;
+        this.fieldCodeToName[field.code] = field.name;
+      });
+    },
+    updateFieldStatus() {
+      const rexp = new RegExp(/\$\{.+?\}/, "g");
+      const variates = this.content.match(rexp);
+
+      const selectedCodes = variates
+        ? variates.map(item => item.replace("${", "").replace("}", ""))
+        : [];
+      this.fields = this.fields.map(field => {
+        field.selected = selectedCodes.includes(field.code);
+        return field;
+      });
+    },
+    rebuildTextarea() {
+      const soursesCodes = this.fieldSourses.map(item => item.code);
+      const deletedCodes = this.fields.filter(
+        item => item.selected && !soursesCodes.includes(item.code)
+      );
+      console.log(deletedCodes);
+      deletedCodes.forEach(field => {
+        this.content = this.content.replace(`\${${field.code}}`, "");
+      });
+    },
+    selectField(field, event) {
+      event.preventDefault();
+      field.selected = !field.selected;
+      if (field.selected) {
+        // 选中
+        const variateStr = `\${${field.code}}`;
+        const textareaDom = this.$refs.FieldTextarea.$el.children[0];
+        const { selectionStart, selectionEnd } = textareaDom;
+
+        this.content =
+          this.content.slice(0, selectionStart) +
+          variateStr +
+          this.content.slice(selectionEnd);
+      } else {
+        // 取消
+        this.content = this.content.replace(`\${${field.code}}`, "");
+      }
+      this.contentChange();
+    },
+    contentChange() {
+      this.$emit("input", this.content);
+      this.$emit("change", this.content);
+    }
+  }
+};
+</script>

+ 23 - 9
src/modules/base/components/ModifyCardRule.vue

@@ -93,7 +93,7 @@
               v-for="column in requiredFields"
               :key="column.code"
               v-model="column.enable"
-              :disabled="!editable"
+              disabled
               >{{ column.name }}</el-checkbox
             >
           </el-form-item>
@@ -108,10 +108,17 @@
           </el-form-item>
         </div>
         <el-form-item prop="titleRule" label="题卡标题规则:">
-          <el-input
+          <!-- <el-input
             v-model="modalForm.titleRule"
             :disabled="!editable"
-          ></el-input>
+          ></el-input> -->
+          <card-title-rule-edit
+            v-model="modalForm.titleRule"
+            :disabled="!editable"
+            :field-sourses="fieldSourses"
+            v-if="fieldSourses.length"
+            ref="CardTitleRuleEdit"
+          ></card-title-rule-edit>
         </el-form-item>
         <el-form-item prop="attention" label="注意事项:">
           <el-input
@@ -136,9 +143,9 @@
             :disabled="!editable"
           ></el-input>
         </el-form-item>
-        <el-form-item prop="orgs" label="适用学院范围:">
+        <el-form-item prop="orgIds" label="适用学院范围:">
           <select-orgs
-            v-model="modalForm.orgs"
+            v-model="modalForm.orgIds"
             ref="SelectOrgs"
             :disabled="!editable"
           ></select-orgs>
@@ -163,6 +170,7 @@
 import { EXAM_NUMBER_STYLE, PAPER_TYPE } from "@/constants/enumerate";
 import { saveCardRule } from "../api";
 import SelectOrgs from "./SelectOrgs";
+import CardTitleRuleEdit from "./CardTitleRuleEdit";
 
 const initModalForm = {
   id: null,
@@ -178,12 +186,12 @@ const initModalForm = {
   attention: "",
   objectiveAttention: "",
   subjectiveAttention: "",
-  orgs: []
+  orgIds: []
 };
 
 export default {
   name: "modify-card-rule",
-  components: { SelectOrgs },
+  components: { SelectOrgs, CardTitleRuleEdit },
   props: {
     instance: {
       type: Object,
@@ -208,6 +216,11 @@ export default {
     },
     editable() {
       return this.editType !== "PREVIEW";
+    },
+    fieldSourses() {
+      return [...this.requiredFields, ...this.extendFields].filter(
+        item => item.enable
+      );
     }
   },
   data() {
@@ -292,7 +305,7 @@ export default {
             trigger: "change"
           }
         ],
-        orgs: [
+        orgIds: [
           {
             required: true,
             validator: (rule, value, callback) => {
@@ -313,10 +326,11 @@ export default {
       this.modalForm = this.$objAssign(initModalForm, val);
       this.requiredFields = val.requiredFields;
       this.extendFields = val.extendFields;
+
       if (val.id) {
         this.modalForm.examAbsent = Boolean(val.examAbsent);
         this.modalForm.writeSign = Boolean(val.writeSign);
-        this.modalForm.orgs = val.orgs.map(item => item.id);
+        this.modalForm.orgIds = val.orgs.map(item => item.id);
       }
     },
     visibleChange() {

+ 13 - 0
src/modules/base/components/ModifyRole.vue

@@ -71,6 +71,7 @@
 
 <script>
 import { updateRole, roleBoundPrivileges } from "../api";
+import { getEnums } from "../../login/api";
 import { ROLE_TYPE } from "../../../constants/enumerate";
 
 const initModalForm = {
@@ -112,6 +113,7 @@ export default {
         label: "name"
       },
       ROLE_TYPE,
+      // ROLE_TYPE: {},
       rules: {
         name: [
           {
@@ -144,7 +146,18 @@ export default {
       }
     };
   },
+  mounted() {
+    // this.getRoleTypes();
+  },
   methods: {
+    async getRoleTypes() {
+      const data = await getEnums("ROLE_TYPE");
+      let ROLE_TYPE = {};
+      data.forEach(element => {
+        ROLE_TYPE[element.name] = element.desc;
+      });
+      this.ROLE_TYPE = ROLE_TYPE;
+    },
     async visibleChange() {
       if (this.instance.id) {
         this.modalForm = this.$objAssign(initModalForm, this.instance);

+ 14 - 5
src/modules/base/components/RuleBusiness.vue

@@ -99,6 +99,7 @@
 import ModifyField from "../components/ModifyField";
 import { ABLE_TYPE, CONFIRM_PRINT_TYPE } from "@/constants/enumerate";
 import { commonRuleDetail, saveCommonBusinessRule } from "../api";
+import { getEnums } from "../../login/api";
 
 const initModalForm = {
   id: null,
@@ -156,11 +157,19 @@ export default {
   },
   methods: {
     async init() {
-      const data = await commonRuleDetail();
-      this.modalForm = Object.assign(initModalForm, data);
-      this.modalForm.review = Number(data.review);
-      this.modalForm.includePaper = Number(data.includePaper);
-      this.modalForm.customCard = Number(data.customCard);
+      const requiredFields = await getEnums("REQUIRED_FIELDS");
+      let commonRule = await commonRuleDetail();
+      commonRule.requiredFields = requiredFields.map(item => {
+        return {
+          code: item.code,
+          name: item.desc,
+          enable: commonRule.requiredFields.includes(item.code)
+        };
+      });
+      this.modalForm = Object.assign(initModalForm, commonRule);
+      this.modalForm.review = Number(commonRule.review);
+      this.modalForm.includePaper = Number(commonRule.includePaper);
+      this.modalForm.customCard = Number(commonRule.customCard);
     },
     validateRequiredFields() {
       this.$refs.modalFormComp.validateField("requiredFields");

+ 0 - 227
src/modules/base/components/RuleCard.vue

@@ -1,227 +0,0 @@
-<template>
-  <div class="rule-card rule-form">
-    <el-form
-      ref="ModalFormLine"
-      label-width="100px"
-      :rules="rulesLine"
-      :model="modalForm"
-      inline
-      style="padding-left: 40px;"
-    >
-      <el-form-item prop="examNumberStyle" label="考号版式:">
-        <el-select
-          v-model="modalForm.examNumberStyle"
-          style="width: 142px;"
-          @change="numStyleChange"
-          placeholder="请选择"
-        >
-          <el-option
-            v-for="(val, key) in EXAM_NUMBER_STYLE"
-            :key="key"
-            :value="key"
-            :label="val"
-          ></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item prop="paperType" label="AB卷版式:">
-        <el-select
-          v-model="modalForm.paperType"
-          style="width: 142px;"
-          placeholder="请选择"
-        >
-          <el-option
-            v-for="(val, key) in PAPER_TYPE"
-            :key="key"
-            :value="key"
-            :label="val"
-          ></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item style="margin-left: 30px;">
-        <el-checkbox v-model="modalForm.examAbsent">启用“缺考填涂”</el-checkbox>
-      </el-form-item>
-      <el-form-item style="margin-left: 30px;">
-        <el-checkbox
-          v-model="modalForm.writeSign"
-          :disabled="modalForm.examNumberStyle === '2'"
-          >启用“手写签名”</el-checkbox
-        >
-      </el-form-item>
-    </el-form>
-
-    <el-form
-      ref="ModalFormRow"
-      label-width="140px"
-      :rules="rulesRow"
-      :model="modalForm"
-      style="max-width: 850px;"
-    >
-      <el-form-item label="考务字段:" style="min-height:200px;">
-        <business-fields
-          :data="modalForm"
-          ref="BusinessFields"
-          v-if="dataReady"
-        ></business-fields>
-      </el-form-item>
-      <el-form-item prop="attention" label="注意事项:">
-        <el-input
-          type="textarea"
-          :rows="5"
-          v-model="modalForm.attention"
-        ></el-input>
-        <p class="tips-info">
-          提示:换行之后,题卡注意事项会展示为多条内容,内容序号会被自动添加。
-        </p>
-      </el-form-item>
-      <el-form-item prop="objectiveAttention" label="客观题注意事项:">
-        <el-input v-model="modalForm.objectiveAttention"></el-input>
-      </el-form-item>
-      <el-form-item prop="subjectiveAttention" label="主观题注意事项:">
-        <el-input v-model="modalForm.subjectiveAttention"></el-input>
-      </el-form-item>
-      <el-form-item>
-        <el-button
-          type="primary"
-          @click="submit"
-          :disabled="isSubmit"
-          style="width:88px"
-          >保存</el-button
-        >
-      </el-form-item>
-    </el-form>
-  </div>
-</template>
-
-<script>
-import BusinessFields from "./BusinessFields";
-import { EXAM_NUMBER_STYLE, PAPER_TYPE } from "@/constants/enumerate";
-import { cardRuleDetail, saveCardRule } from "../api";
-
-export default {
-  name: "rule-card",
-  components: {
-    BusinessFields
-  },
-  data() {
-    return {
-      modalForm: {
-        examNumberStyle: "",
-        paperType: "",
-        examAbsent: true,
-        writeSign: true,
-        examMustColumn: "",
-        examExtendColumn: "",
-        attention: "",
-        objectiveAttention: "",
-        subjectiveAttention: ""
-      },
-      EXAM_NUMBER_STYLE,
-      PAPER_TYPE,
-      isSubmit: false,
-      dataReady: false,
-      rulesLine: {
-        examNumberStyle: [
-          {
-            required: true,
-            message: "请选择考号版式",
-            trigger: "change"
-          }
-        ],
-        paperType: [
-          {
-            required: true,
-            message: "请选择AB卷版式",
-            trigger: "change"
-          }
-        ]
-      },
-      rulesRow: {
-        attention: [
-          {
-            required: true,
-            message: "请输入注意事项",
-            trigger: "change"
-          },
-          {
-            validator: (rule, value, callback) => {
-              const val = value.replace(/\n/g, "");
-              if (val.length > 200) {
-                callback(new Error("注意事项最多只能输入200个字符"));
-              } else {
-                callback();
-              }
-            },
-            trigger: "change"
-          }
-        ],
-        objectiveAttention: [
-          {
-            required: true,
-            message: "请输入客观题注意事项",
-            trigger: "change"
-          },
-          {
-            max: 26,
-            message: "客观题注意事项最多只能输入26个汉字",
-            trigger: "change"
-          }
-        ],
-        subjectiveAttention: [
-          {
-            required: true,
-            message: "请输入主观题注意事项",
-            trigger: "change"
-          },
-          {
-            max: 26,
-            message: "主观题注意事项最多只能输入26个汉字",
-            trigger: "change"
-          }
-        ]
-      }
-    };
-  },
-  mounted() {
-    this.getCardRule();
-  },
-  methods: {
-    async getCardRule() {
-      const data = await cardRuleDetail();
-      this.modalForm = Object.assign(this.modalForm, data);
-      this.modalForm.examNumberStyle += "";
-      this.modalForm.paperType += "";
-      this.modalForm.examAbsent = Boolean(this.modalForm.examAbsent);
-      this.modalForm.writeSign = Boolean(this.modalForm.writeSign);
-      this.dataReady = true;
-    },
-    numStyleChange() {
-      this.modalForm.writeSign = this.modalForm.examNumberStyle !== "2";
-    },
-    async submit() {
-      const valid1 = await this.$refs["ModalFormLine"]
-        .validate()
-        .catch(() => {});
-      const valid2 = await this.$refs["ModalFormRow"]
-        .validate()
-        .catch(() => {});
-      if (!valid1 || !valid2) return;
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      const modals = {
-        ...this.modalForm,
-        ...this.$refs.BusinessFields.getSelectColumns()
-      };
-      modals.examNumberStyle = Number(modals.examNumberStyle);
-      modals.paperType = Number(modals.paperType);
-      modals.examAbsent = Number(modals.examAbsent);
-      modals.writeSign = Number(modals.writeSign);
-      const data = await saveCardRule(modals).catch(() => {});
-      this.isSubmit = false;
-      if (!data) return;
-
-      this.$message.success("保存成功!");
-    }
-  }
-};
-</script>

+ 0 - 139
src/modules/base/components/RuleExamroom.vue

@@ -1,139 +0,0 @@
-<template>
-  <div class="rule-examroom">
-    <div class="part-box">
-      <el-table ref="TableList" :data="dataList" border stripe>
-        <el-table-column prop="schoolId" label="学校ID"></el-table-column>
-        <el-table-column prop="schoolName" label="学校名称"></el-table-column>
-        <el-table-column prop="createTime" label="上传时间"></el-table-column>
-        <el-table-column label="操作" align="center">
-          <template slot-scope="scope">
-            <el-button
-              class="btn-table-icon"
-              type="text"
-              icon="icon icon-upload-act"
-              @click="toUpload(scope.row)"
-              title="上传登记表"
-            ></el-button>
-            <el-button
-              class="btn-table-icon"
-              type="text"
-              icon="icon icon-circle-right"
-              @click="toView(scope.row.path)"
-              title="预览登记表"
-              v-if="scope.row.id"
-            ></el-button>
-            <el-button
-              class="btn-table-icon"
-              type="text"
-              icon="icon icon-delete"
-              @click="toDelete(scope.row)"
-              title="删除登记表"
-              v-if="scope.row.id"
-            ></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"
-          hide-on-single-page
-        >
-        </el-pagination>
-      </div>
-    </div>
-
-    <upload-file-dialog
-      :paper-attachment="curAttachment"
-      :format="['html']"
-      @confirm="uploadConfirm"
-      ref="UploadFileDialog"
-    ></upload-file-dialog>
-  </div>
-</template>
-
-<script>
-import { checkinExamList, saveCheckinExam, deleteCheckinExam } from "../api";
-import UploadFileDialog from "@/components/UploadFileDialog";
-
-export default {
-  name: "rule-examroom",
-  components: { UploadFileDialog },
-  data() {
-    return {
-      schoolId: this.$ls.get("schoolId"),
-      dataList: [],
-      current: 1,
-      size: this.GLOBAL.pageSize,
-      total: 0,
-      curAttachment: {},
-      curCheckinExam: {}
-    };
-  },
-  mounted() {
-    this.toPage(1);
-  },
-  methods: {
-    async getList() {
-      const datas = {
-        schoolId: this.schoolId,
-        pageNumber: this.current,
-        pageSize: this.size
-      };
-      const data = await checkinExamList(datas);
-      this.dataList = data.records;
-      this.total = data.total;
-    },
-    toPage(page) {
-      this.current = page;
-      this.getList();
-    },
-    toUpload(row) {
-      this.curCheckinExam = row;
-      this.curAttachment = {
-        attachmentId: row.attachmentId,
-        filename: ""
-      };
-      this.$refs.UploadFileDialog.open();
-      console.log(row);
-    },
-    toDelete(row) {
-      this.$confirm("确定要删除当前学校登记表吗?", "删除警告", {
-        cancelButtonClass: "el-button--danger is-plain",
-        confirmButtonClass: "el-button--primary",
-        type: "warning"
-      })
-        .then(async () => {
-          await deleteCheckinExam(row.id);
-          this.$message.success("删除成功!");
-          this.deletePageLastItem();
-        })
-        .catch(() => {});
-    },
-    toView(path) {
-      window.open(path);
-    },
-    async uploadConfirm(attachment) {
-      const datas = {
-        attachmentId: attachment.attachmentId,
-        createId: "",
-        id: this.curCheckinExam.id,
-        schoolId: this.curCheckinExam.schoolId,
-        updateId: ""
-      };
-      const userId = this.$ls.get("user", { id: "" }).id;
-      const modInfo = this.curCheckinExam.id
-        ? { updateId: userId }
-        : { createId: userId };
-      await saveCheckinExam(Object.assign(datas, modInfo));
-
-      this.$message.success("编辑成功!");
-      this.getList();
-    }
-  }
-};
-</script>

+ 0 - 70
src/modules/base/components/RuleWarning.vue

@@ -1,70 +0,0 @@
-<template>
-  <div class="rule-warning rule-form">
-    <p class="rule-tips">题卡/试卷制作计划预警:以“印刷计划”时间为参照</p>
-    <el-form ref="ModalForm" label-width="100px" style="min-height: 200px;">
-      <el-form-item
-        v-for="(ruleItem, index) in warnRules"
-        :key="index"
-        :label="`${ruleItem.roleName}:`"
-      >
-        <span class="rule-spin">提前</span>
-        <el-select
-          v-model="ruleItem.unit"
-          style="width: 156px;"
-          placeholder="请选择"
-          clearable
-        >
-          <el-option
-            v-for="item in times"
-            :key="item"
-            :value="item"
-            :label="`${item}天`"
-          ></el-option>
-        </el-select>
-      </el-form-item>
-    </el-form>
-    <div class="rule-btns">
-      <el-button type="primary" :disabled="isSubmit" @click="submit"
-        >保存</el-button
-      >
-    </div>
-  </div>
-</template>
-
-<script>
-import { warningRuleDetail, saveWarningRule } from "../api";
-
-export default {
-  name: "rule-warning",
-  data() {
-    return {
-      warnRules: [],
-      times: ["1", "3", "5"],
-      isSubmit: false
-    };
-  },
-  created() {
-    this.init();
-  },
-  methods: {
-    async init() {
-      this.warnRules = await warningRuleDetail();
-    },
-    async submit() {
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      const list = this.warnRules.map(item => {
-        return {
-          roleCode: item.roleCode,
-          unit: item.unit
-        };
-      });
-
-      const data = await saveWarningRule({ list }).catch(() => {});
-      this.isSubmit = false;
-      if (!data) return;
-      this.$message.success("保存成功!");
-    }
-  }
-};
-</script>

+ 0 - 1
src/modules/base/components/SelectOrgs.vue

@@ -8,7 +8,6 @@
         node-key="id"
         ref="MenuTree"
         :props="defaultProps"
-        check-strictly
         check-on-click-node
         :expand-on-click-node="false"
         @check-change="checkChange"

+ 12 - 1
src/modules/base/views/CardRuleManage.vue

@@ -132,6 +132,8 @@
 <script>
 import { ABLE_TYPE } from "@/constants/enumerate";
 import { commonRuleDetail, cardRuleListPage, ableCardRule } from "../api";
+import { getEnums } from "../../login/api";
+
 import ModifyCardRule from "../components/ModifyCardRule";
 
 export default {
@@ -162,7 +164,16 @@ export default {
   },
   methods: {
     async getCommonRuleDetail() {
-      this.commonRule = await commonRuleDetail();
+      const requiredFields = await getEnums("REQUIRED_FIELDS");
+      let commonRule = await commonRuleDetail();
+      commonRule.requiredFields = requiredFields.map(item => {
+        return {
+          code: item.code,
+          name: item.desc,
+          enable: commonRule.requiredFields.includes(item.code)
+        };
+      });
+      this.commonRule = commonRule;
     },
     async getList() {
       const datas = {

+ 0 - 15
src/modules/card/api.js

@@ -1,15 +0,0 @@
-import {
-  cardConfigInfos,
-  cardDetailEdit,
-  cardTempDetail,
-  saveCard,
-  submitCard
-} from "../../../card/api";
-
-export {
-  cardConfigInfos,
-  cardDetailEdit,
-  cardTempDetail,
-  saveCard,
-  submitCard
-};

+ 0 - 3
src/modules/card/enumerate.js

@@ -1,3 +0,0 @@
-import { transformField } from "../../../card/enumerate";
-
-export { transformField };

+ 14 - 10
src/modules/exam/components/ApplyContent.vue

@@ -317,20 +317,24 @@ export default {
         if (this.curTaskApply.cardSource === 0) {
           this.$refs.CardOptionDialog.open();
         } else if (this.curTaskApply.cardSource === 1) {
-          this.$router.push({
-            name: "CardDesign",
-            params: {
-              cardId: this.curTaskApply.cardId
-            }
-          });
-        } else {
-          if (this.curTaskApply.auditingStatus) {
-            this.$router.push({
+          window.open(
+            this.getRouterPath({
               name: "CardDesign",
               params: {
                 cardId: this.curTaskApply.cardId
               }
-            });
+            })
+          );
+        } else {
+          if (this.curTaskApply.auditingStatus) {
+            window.open(
+              this.getRouterPath({
+                name: "CardDesign",
+                params: {
+                  cardId: this.curTaskApply.cardId
+                }
+              })
+            );
           } else {
             window.open(
               this.getRouterPath({

+ 6 - 5
src/modules/exam/components/CardOptionDialog.vue

@@ -106,8 +106,7 @@ import UploadButton from "@/components/UploadButton";
 const initModalForm = {
   examTaskId: "",
   paperType: "",
-  courseName: "",
-  courseCode: "",
+  cardRuleId: "",
   cardId: "",
   cardSource: "",
   refCardId: ""
@@ -243,9 +242,11 @@ export default {
         this.$emit("draft-task");
         // 打开题卡编辑页,创建题卡,并预设需要绑定的任务
         this.$ls.set("prepareTcPCard", this.modalForm);
-        this.$router.push({
-          name: "CardDesign"
-        });
+        window.open(
+          this.getRouterPath({
+            name: "CardDesign"
+          })
+        );
         return;
       }
 

+ 2 - 1
src/modules/exam/components/ModifyExamTask.vue

@@ -14,6 +14,7 @@
       <el-form
         ref="modalFormComp"
         label-width="130px"
+        :class="{ 'form-info': !editable }"
         :rules="rules"
         :model="modalForm"
       >
@@ -142,7 +143,7 @@ export default {
       const names = {
         ADD: "新增命题任务",
         PREVIEW: "命题任务详情",
-        EDIT: "编辑命题任务"
+        EDIT: "指派命题任务"
       };
       return names[this.editType];
     },

+ 111 - 0
src/modules/exam/components/WaitTaskAudit.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="wait-task-audit part-box part-box-pad part-box-border">
+    <div class="task-head part-box part-box-flex">
+      <h3>
+        审核代办(<span class="color-danger">{{ total }}</span
+        >)
+      </h3>
+      <div>
+        <i class="el-icon-s-fold"></i>
+      </div>
+    </div>
+    <div class="task-list">
+      <div v-for="task in tasks" :key="task.id" class="task-item">
+        <p>
+          <span>试卷编号:</span>
+          <span>{{ task.paperNumber }}</span>
+        </p>
+        <p>
+          <span>课程(代码):</span>
+          <span>{{ task.courseName }}({{ task.courseCode }})</span>
+        </p>
+        <p>
+          <span>命题结束时间:</span>
+          <span>{{ task.endTime | timestampFilter }}</span>
+        </p>
+        <p>
+          <span>命题老师:</span>
+          <span>{{ task.userName }}</span>
+        </p>
+        <p>
+          <span>提交时间:</span>
+          <span>{{ task.createTime | timestampFilter }}</span>
+        </p>
+        <div class="part-box-flex">
+          <el-tag type="success" effect="dark">
+            {{ task.specialty }}
+          </el-tag>
+          <span class="task-action" @click="toDo(task)"
+            >立即处理 <i class="el-icon-arrow-right"></i
+          ></span>
+        </div>
+      </div>
+    </div>
+    <div class="text-center">
+      <el-pagination
+        background
+        layout="prev, pager, next"
+        :current-page="current"
+        :total="total"
+        :page-size="size"
+        @current-change="toPage"
+      >
+      </el-pagination>
+    </div>
+
+    <!-- ModifyTaskApply -->
+    <modify-task-apply
+      ref="ModifyTaskApply"
+      :edit-type="editType"
+      :instance="curTask"
+      @modified="getList"
+    ></modify-task-apply>
+  </div>
+</template>
+
+<script>
+import ModifyTaskApply from "./ModifyTaskApply";
+import { taskReviewListPage } from "../api";
+
+export default {
+  name: "wait-task-audit",
+  components: { ModifyTaskApply },
+  data() {
+    return {
+      filter: {
+        status: "NEW",
+        enable: true
+      },
+      total: 0,
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      tasks: [],
+      curTask: {},
+      editType: "AUDIT"
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size
+      };
+      const data = await taskReviewListPage(datas);
+      this.tasks = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    toDo(task) {
+      this.curTask = task;
+      this.$refs.ModifyTaskApply.open();
+    }
+  }
+};
+</script>

+ 103 - 0
src/modules/exam/components/WaitTaskExam.vue

@@ -0,0 +1,103 @@
+<template>
+  <div class="wait-task-exam part-box part-box-pad part-box-border">
+    <div class="task-head part-box part-box-flex">
+      <h3>
+        命题分配代办(<span class="color-danger">{{ total }}</span
+        >)
+      </h3>
+      <div>
+        <i class="el-icon-s-fold"></i>
+      </div>
+    </div>
+    <div class="task-list">
+      <div v-for="task in tasks" :key="task.id" class="task-item">
+        <p>
+          <span>试卷编号:</span>
+          <span>{{ task.paperNumber }}</span>
+        </p>
+        <p>
+          <span>课程(代码):</span>
+          <span>{{ task.courseName }}({{ task.courseCode }})</span>
+        </p>
+        <p>
+          <span>命题结束时间:</span>
+          <span>{{ task.endTime | timestampFilter }}</span>
+        </p>
+        <div class="part-box-flex">
+          <el-tag type="success" effect="dark">
+            {{ task.specialty }}
+          </el-tag>
+          <span class="task-action" @click="toDo(task)"
+            >立即处理 <i class="el-icon-arrow-right"></i
+          ></span>
+        </div>
+      </div>
+    </div>
+    <div class="text-center">
+      <el-pagination
+        background
+        layout="prev, pager, next"
+        :current-page="current"
+        :total="total"
+        :page-size="size"
+        @current-change="toPage"
+      >
+      </el-pagination>
+    </div>
+
+    <!-- ModifyExamTask -->
+    <modify-exam-task
+      ref="ModifyExamTask"
+      :instance="curTask"
+      :edit-type="editType"
+      @modified="getList"
+    ></modify-exam-task>
+  </div>
+</template>
+
+<script>
+import { examTaskListPage } from "../api";
+import ModifyExamTask from "./ModifyExamTask";
+
+export default {
+  name: "wait-task-exam",
+  components: { ModifyExamTask },
+  data() {
+    return {
+      filter: {
+        status: "NEW",
+        enable: true
+      },
+      total: 0,
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      tasks: [],
+      curTask: {},
+      editType: "EDIT"
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size
+      };
+      const data = await examTaskListPage(datas);
+      this.tasks = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    toDo(task) {
+      this.curTask = task;
+      this.$refs.ModifyExamTask.open();
+    }
+  }
+};
+</script>

+ 103 - 0
src/modules/exam/components/WaitTaskExamTask.vue

@@ -0,0 +1,103 @@
+<template>
+  <div class="wait-task-exam part-box part-box-pad part-box-border">
+    <div class="task-head part-box part-box-flex">
+      <h3>
+        命题代办(<span class="color-danger">{{ total }}</span
+        >)
+      </h3>
+      <div>
+        <i class="el-icon-s-fold"></i>
+      </div>
+    </div>
+    <div class="task-list">
+      <div v-for="task in tasks" :key="task.id" class="task-item">
+        <p>
+          <span>试卷编号:</span>
+          <span>{{ task.paperNumber }}</span>
+        </p>
+        <p>
+          <span>课程(代码):</span>
+          <span>{{ task.courseName }}({{ task.courseCode }})</span>
+        </p>
+        <p>
+          <span>命题结束时间:</span>
+          <span>{{ task.endTime | timestampFilter }}</span>
+        </p>
+        <div class="part-box-flex">
+          <el-tag type="success" effect="dark">
+            {{ task.specialty }}
+          </el-tag>
+          <span class="task-action" @click="toDo(task)"
+            >立即处理 <i class="el-icon-arrow-right"></i
+          ></span>
+        </div>
+      </div>
+    </div>
+    <div class="text-center">
+      <el-pagination
+        background
+        layout="prev, pager, next"
+        :current-page="current"
+        :total="total"
+        :page-size="size"
+        @current-change="toPage"
+      >
+      </el-pagination>
+    </div>
+
+    <!-- ModifyTaskApply -->
+    <modify-task-apply
+      ref="ModifyTaskApply"
+      :edit-type="editType"
+      :instance="curTask"
+      @modified="getList"
+    ></modify-task-apply>
+  </div>
+</template>
+
+<script>
+import { examTaskListPage } from "../api";
+import ModifyTaskApply from "./ModifyTaskApply";
+
+export default {
+  name: "wait-task-exam",
+  components: { ModifyTaskApply },
+  data() {
+    return {
+      filter: {
+        status: "NEW",
+        enable: true
+      },
+      total: 0,
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      tasks: [],
+      curTask: {},
+      editType: "APPLY"
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size
+      };
+      const data = await examTaskListPage(datas);
+      this.tasks = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    toDo(task) {
+      this.curTask = task;
+      this.$refs.ModifyTaskApply.open();
+    }
+  }
+};
+</script>

+ 46 - 4
src/modules/exam/views/WaitTask.vue

@@ -1,14 +1,56 @@
 <template>
-  <div class="WaitTask">
-    WaitTask
+  <div class="wait-task">
+    <el-row type="flex" :gutter="20">
+      <el-col v-if="IS_QUESTION_TEACHER" :span="colSpan">
+        <wait-task-exam-task
+          class="wait-module"
+          ref="WaitTaskExamTask"
+        ></wait-task-exam-task>
+      </el-col>
+      <el-col v-if="IS_EXAM_TEACHER" :span="colSpan">
+        <wait-task-exam class="wait-module" ref="WaitTaskExam"></wait-task-exam>
+      </el-col>
+      <el-col v-if="IS_EXAM_TEACHER" :span="colSpan">
+        <wait-task-audit
+          class="wait-module"
+          ref="WaitTaskAudit"
+        ></wait-task-audit>
+      </el-col>
+    </el-row>
   </div>
 </template>
 
 <script>
+import WaitTaskExamTask from "../components/WaitTaskExamTask";
+import WaitTaskExam from "../components/WaitTaskExam";
+import WaitTaskAudit from "../components/WaitTaskAudit";
+
 export default {
-  name: "WaitTask",
+  name: "wait-task",
+  components: { WaitTaskExam, WaitTaskAudit, WaitTaskExamTask },
   data() {
-    return {};
+    return {
+      userRoles: this.$ls.get("user", { roles: [] }).roles
+    };
+  },
+  computed: {
+    IS_QUESTION_TEACHER() {
+      return !!this.userRoles.filter(item => item.type === "QUESTION_TEACHER")
+        .length;
+    },
+    IS_EXAM_TEACHER() {
+      return !!this.userRoles.filter(item => item.type === "EXAM_TEACHER")
+        .length;
+    },
+    colSpan() {
+      const modules = [
+        this.IS_QUESTION_TEACHER,
+        this.IS_EXAM_TEACHER,
+        this.IS_EXAM_TEACHER
+      ];
+      const moduleCount = modules.filter(item => item).length;
+      return 24 / moduleCount;
+    }
   },
   methods: {}
 };

+ 3 - 0
src/modules/login/api.js

@@ -15,3 +15,6 @@ export const sysMenu = () => {
 export const attachmentPreview = id => {
   return $get("/api/common/file/get_one", { id });
 };
+export const getEnums = type => {
+  return $get("/api/common/get_enums", { type });
+};

+ 1 - 18
src/store.js

@@ -1,39 +1,22 @@
 import Vue from "vue";
 import Vuex from "vuex";
-import { keepAliveRoutesPairs } from "@/constants/enumerate";
 
 Vue.use(Vuex);
 
 // modules
 import card from "./modules/card/store";
-// import examCenter from "./modules/exam-center/store";
 
 export default new Vuex.Store({
   state: {
-    user: {},
-    keepAliveRoutes: keepAliveRoutesPairs.map(v => v[0])
+    user: {}
   },
   mutations: {
     setUser(state, user) {
       state.user = user;
-    },
-    setEmptyKeepAliveRoutes(state) {
-      state.keepAliveRoutes = [];
-    },
-    setRestoreKeepAliveRoutes(state) {
-      state.keepAliveRoutes = keepAliveRoutesPairs.map(v => v[0]);
-    },
-    addKeepAliveRouteItem(state, name) {
-      state.keepAliveRoutes.push(name);
-    },
-    removeKeepAliveRouteItem(state, name) {
-      const pos = state.keepAliveRoutes.indexOf(name);
-      if (pos !== -1) state.keepAliveRoutes.splice(pos, 1);
     }
   },
   actions: {},
   modules: {
     card
-    // examCenter
   }
 });

+ 4 - 7
src/views/Home.vue

@@ -103,7 +103,7 @@
         <!-- home-view: page detail -->
         <div class="home-view">
           <!-- <router-view /> -->
-          <keep-alive :include="keepAliveRoutes">
+          <keep-alive>
             <router-view />
           </keep-alive>
         </div>
@@ -122,7 +122,7 @@
 // import { mapState, mapActions } from "vuex";
 import localNavs from "@/constants/navs";
 import { deepCopy } from "@/plugins/utils";
-import { logout, sysMenu } from "../modules/login/api";
+import { sysMenu } from "../modules/login/api";
 import ResetPwd from "../modules/base/components/ResetPwd";
 
 export default {
@@ -148,9 +148,6 @@ export default {
   },
   computed: {
     // ...mapState("examCenter", ["waitTaskCount"]),
-    keepAliveRoutes() {
-      return this.$store.state.keepAliveRoutes;
-    }
   },
   created() {
     this.getMenus();
@@ -288,8 +285,8 @@ export default {
         })
         .catch(() => {});
     },
-    async logoutAction() {
-      await logout(this.$ls.get("user", { id: "" }).id);
+    logoutAction() {
+      // await logout(this.$ls.get("user", { id: "" }).id);
       this.$ls.clear();
       this.$router.push({ name: "Login" });
     },