zhangjie 5 years ago
parent
commit
a5827778fa
53 changed files with 1040 additions and 451 deletions
  1. 1 0
      package.json
  2. 1 1
      src/assets/styles/element-ui-costom.scss
  3. 7 0
      src/assets/styles/home.scss
  4. 1 1
      src/assets/styles/index.scss
  5. 134 0
      src/components/UploadButton.vue
  6. 48 0
      src/constants/enumerate.js
  7. 0 4
      src/constants/navs.js
  8. 2 2
      src/main.js
  9. 1 1
      src/modules/analyze/components/ModifyData.vue
  10. 15 1
      src/modules/base/api.js
  11. 67 17
      src/modules/base/components/BusinessFields.vue
  12. 1 1
      src/modules/base/components/ModifyData.vue
  13. 128 22
      src/modules/base/components/RuleCard.vue
  14. 36 43
      src/modules/base/components/RuleWarning.vue
  15. 1 2
      src/modules/base/views/RuleManage.vue
  16. 22 21
      src/modules/base/views/UserEdit.vue
  17. 45 20
      src/modules/base/views/UserManage.vue
  18. 1 1
      src/modules/card/api.js
  19. 2 2
      src/modules/card/card.temp.json
  20. 4 4
      src/modules/card/components/CardConfigPropEdit.vue
  21. 2 2
      src/modules/card/components/SavePage.vue
  22. 5 5
      src/modules/card/components/elementEdit/CardHead.vue
  23. 4 3
      src/modules/card/components/elementEdit/cardHeadSpin/HeadDynamic.vue
  24. 1 1
      src/modules/card/components/elementEdit/cardHeadSpin/HeadNotice.vue
  25. 3 3
      src/modules/card/components/elementEdit/cardHeadSpin/HeadStdno.vue
  26. 1 1
      src/modules/card/components/elementPropEdit/EditComposition.vue
  27. 1 1
      src/modules/card/components/elementPropEdit/EditExplain.vue
  28. 1 1
      src/modules/card/components/elementPropEdit/EditFillLine.vue
  29. 1 1
      src/modules/card/components/elementPropEdit/EditFillQuestion.vue
  30. 1 1
      src/modules/card/components/elementPropEdit/EditText.vue
  31. 1 1
      src/modules/card/elementModel.js
  32. 1 1
      src/modules/card/views/CardPreview.vue
  33. 8 6
      src/modules/exam-center/api.js
  34. 172 0
      src/modules/exam-center/components/FileUploadView.vue
  35. 0 114
      src/modules/exam-center/components/ModifyData.vue
  36. 0 9
      src/modules/exam-center/views/CardAudit.vue
  37. 0 9
      src/modules/exam-center/views/CardManage.vue
  38. 6 12
      src/modules/exam-center/views/DoneTask.vue
  39. 87 18
      src/modules/exam-center/views/DoneTaskDetail.vue
  40. 20 15
      src/modules/exam-center/views/ExamManage.vue
  41. 0 9
      src/modules/exam-center/views/ExamRomeDetail.vue
  42. 0 9
      src/modules/exam-center/views/ExamRomeStudentDetail.vue
  43. 10 16
      src/modules/exam-center/views/PrintManage.vue
  44. 6 12
      src/modules/exam-center/views/WaitTask.vue
  45. 90 14
      src/modules/exam-center/views/WaitTaskDetail.vue
  46. 1 1
      src/modules/example/components/ModifyData.vue
  47. 4 1
      src/modules/login/api.js
  48. 22 24
      src/modules/login/views/Login.vue
  49. 1 1
      src/modules/score-paper/components/ModifyData.vue
  50. 22 15
      src/plugins/axios.js
  51. 43 0
      src/plugins/crypto.js
  52. 4 2
      src/views/Home.vue
  53. 5 0
      yarn.lock

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "axios": "^0.18.0",
     "core-js": "^2.6.5",
     "cropperjs": "^1.5.1",
+    "crypto-js": "^4.0.0",
     "deepmerge": "^3.2.0",
     "element-ui": "^2.13.1",
     "jsbarcode": "^3.11.0",

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

@@ -18,7 +18,7 @@
   }
 }
 .el-dialog__body {
-  padding: 30px 36px 20px 0;
+  padding: 30px 20px 20px;
   background-color: #f6f6f6;
   position: relative;
   border-top: 1px solid #e5e5e5;

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

@@ -292,6 +292,13 @@
     padding: 17px;
     line-height: 20px;
     border: 1px solid $--border-color-light;
+
+    &.td-link {
+      cursor: pointer;
+      &:hover {
+        color: $--color-text-primary;
+      }
+    }
   }
   .td-th {
     font-weight: 600;

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

@@ -11,5 +11,5 @@
 @import "./card-design.scss";
 
 @import "./element-ui-costom.scss";
-// @import "./common-comp.scss";
+@import "./common-comp.scss";
 @import "./adaptive.scss";

+ 134 - 0
src/components/UploadButton.vue

@@ -0,0 +1,134 @@
+<template>
+  <el-upload
+    :action="uploadUrl"
+    :headers="headers"
+    :max-size="maxSize"
+    :format="format"
+    :accept="accept"
+    :data="uploadData"
+    :before-upload="handleBeforeUpload"
+    :on-error="handleError"
+    :on-success="handleSuccess"
+    :show-file-list="false"
+    style="display:inline-block;margin: 0 18px;"
+    ref="UploadComp"
+  >
+    <slot></slot>
+  </el-upload>
+</template>
+
+<script>
+import { fileMd5 } from "../plugins/crypto";
+
+export default {
+  name: "import-file",
+  props: {
+    format: {
+      type: Array,
+      default() {
+        return ["jpg", "jpeg", "png"];
+      }
+    },
+    uploadUrl: {
+      type: String,
+      required: true
+    },
+    uploadData: {
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    maxSize: {
+      type: Number,
+      default: 10 * 1024 * 1024
+    },
+    addFilenameParam: {
+      type: String,
+      default: "filename"
+    }
+  },
+  data() {
+    return {
+      headers: {},
+      res: {}
+    };
+  },
+  created() {
+    this.headers = {
+      token: this.$ls.get("token"),
+      md5: ""
+    };
+  },
+  computed: {
+    accept() {
+      return this.format.map(el => `.${el}`).join();
+    }
+  },
+  methods: {
+    checkFileFormat(fileType) {
+      const _file_format = fileType
+        .split(".")
+        .pop()
+        .toLocaleLowerCase();
+      return this.format.some(
+        item => item.toLocaleLowerCase() === _file_format
+      );
+    },
+    async handleBeforeUpload(file) {
+      if (this.addFilenameParam)
+        this.uploadData[this.addFilenameParam] = file.name;
+
+      if (file.size > this.maxSize) {
+        this.handleExceededSize();
+        return Promise.reject();
+      }
+
+      if (!this.checkFileFormat(file.name)) {
+        this.handleFormatError();
+        return Promise.reject();
+      }
+
+      const md5 = await fileMd5(file);
+      this.headers["md5"] = md5;
+
+      return true;
+    },
+    handleError(error) {
+      this.res = {
+        success: false,
+        msg: error.message
+      };
+      this.$emit("upload-error", error);
+    },
+    handleSuccess(response) {
+      if (response.code === "200") {
+        this.res = {
+          success: true,
+          msg: "导入成功!"
+        };
+        this.$emit("upload-success", response);
+      } else {
+        this.handleError(response);
+      }
+    },
+    handleFormatError() {
+      const content = "只支持文件格式为" + this.format.join("/");
+      this.res = {
+        success: false,
+        msg: content
+      };
+      this.$emit("upload-error", content);
+    },
+    handleExceededSize() {
+      const content =
+        "文件大小不能超过" + Math.floor(this.maxSize / 1024) + "M";
+      this.res = {
+        success: false,
+        msg: content
+      };
+      this.$emit("upload-error", content);
+    }
+  }
+};
+</script>

+ 48 - 0
src/constants/enumerate.js

@@ -24,3 +24,51 @@ export const AUDITING_STATUS = {
   0: "未审核",
   1: "已审核"
 };
+
+export const EXAM_NUMBER_STYLE = {
+  0: "印刷条码",
+  1: "粘贴条码",
+  2: "卡号填涂"
+};
+export const EXAM_NUMBER_STYLE_MAP = {
+  0: "auto",
+  1: "empty",
+  2: "fill"
+};
+
+export const PAPER_TYPE = {
+  0: "印刷",
+  1: "填涂"
+};
+
+export const PAPER_TYPE_MAP = {
+  0: "auto",
+  1: "fill"
+};
+
+export const CARD_BUSINESS_FIELDS = {
+  must: [
+    {
+      name: "学号",
+      code: "studentCode"
+    },
+    {
+      name: "姓名",
+      code: "name"
+    },
+    {
+      name: "科目名称",
+      code: "courseName"
+    }
+  ],
+  extend: [
+    {
+      name: "教学班号",
+      code: "classNo"
+    },
+    {
+      name: "考场",
+      code: "examRoom"
+    }
+  ]
+};

+ 0 - 4
src/constants/navs.js

@@ -93,10 +93,6 @@ const navs = [
           }
         ]
       },
-      {
-        title: "密码管理",
-        router: "PswdManage"
-      },
       {
         title: "规则管理",
         router: "RuleManage"

+ 2 - 2
src/main.js

@@ -55,7 +55,7 @@ axios.interceptors.request.use(
     // 显示loading提示
     if (!queue.length) {
       load = ElementUI.Message({
-        iconClass: "el-icon-loading",
+        iconClass: "el-message__icon el-icon-loading",
         message: "Loading..."
       });
     }
@@ -69,7 +69,7 @@ axios.interceptors.request.use(
     // 为请求头添加token信息
     let token = Vue.ls.get("token");
     if (token) {
-      config.headers["Authorization"] = token;
+      config.headers["token"] = token;
     }
 
     // 设置延迟时效

+ 1 - 1
src/modules/analyze/components/ModifyData.vue

@@ -93,7 +93,7 @@ export default {
       this.modalIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       if (this.isSubmit) return;

+ 15 - 1
src/modules/base/api.js

@@ -2,7 +2,10 @@ import { $get, $post } from "@/plugins/axios";
 
 // user-manage
 export const userListPage = datas => {
-  return $get("/api/print/basic/user/listPage", datas);
+  return $get("/api/print/basic/user/list", datas);
+};
+export const userDetail = userId => {
+  return $get("/api/print/basic/sys/userQuery", { userId });
 };
 export const updateUser = datas => {
   if (datas.id) {
@@ -19,9 +22,15 @@ export const updatePwd = datas => {
 };
 
 // rule-manage
+export const cardRuleDetail = schoolId => {
+  return $get("/api/print/basic/cardRule/selectBySchoolId", { schoolId });
+};
 export const saveCardRule = datas => {
   return $post("/api/print/basic/cardRule/add", datas);
 };
+export const warningRuleDetail = schoolId => {
+  return $post("/api/print/basic/wranRule/listBySchoolId", { schoolId });
+};
 export const saveWarningRule = datas => {
   return $post("/api/print/basic/warnRule/add", datas);
 };
@@ -33,3 +42,8 @@ export const importExtendColums = datas => {
 export const uploadFile = datas => {
   return $post("/api/print/basic/sys/saveAttachment", datas);
 };
+
+// system
+export const roleList = datas => {
+  return $get("/api/print/basic/sys/roleList", datas);
+};

+ 67 - 17
src/modules/base/components/BusinessFields.vue

@@ -2,41 +2,91 @@
   <div class="business-fields">
     <el-form ref="ModalForm" label-width="90px">
       <el-form-item label="必选字段:">
-        <el-checkbox-group v-model="checkList">
-          <el-checkbox label="复选框 A"></el-checkbox>
-          <el-checkbox label="复选框 B"></el-checkbox>
-          <el-checkbox label="复选框 C"></el-checkbox>
-        </el-checkbox-group>
+        <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-group v-model="checkList">
-          <el-checkbox label="复选框 A"></el-checkbox>
-          <el-checkbox label="复选框 B"></el-checkbox>
-          <el-checkbox label="复选框 C"></el-checkbox>
-        </el-checkbox-group>
+        <el-checkbox
+          v-for="column in extendColumns"
+          :key="column.code"
+          v-model="column.select"
+          >{{ column.name }}</el-checkbox
+        >
       </el-form-item>
       <el-form-item>
-        <el-button
-          class="btn-table-icon"
-          icon="icon icon-share-gray"
-          @click="toImport"
-          >导入考务扩展字段</el-button
+        <upload-button
+          :upload-url="uploadUrl"
+          :format="['xls', 'xlsx']"
+          @upload-error="uplaodError"
+          @upload-success="uploadSuccess"
+          style="margin:10px 0 0;"
         >
+          <el-button class="btn-table-icon" icon="icon icon-share-gray"
+            >导入考务扩展字段</el-button
+          >
+        </upload-button>
       </el-form-item>
     </el-form>
   </div>
 </template>
 
 <script>
+import { CARD_BUSINESS_FIELDS } from "@/constants/enumerate";
+import UploadButton from "@/components/UploadButton";
+
 export default {
   name: "business-fields",
+  components: { UploadButton },
+  props: {
+    data: {
+      type: Object
+    }
+  },
   data() {
     return {
-      checkList: []
+      mustColumns: [],
+      extendColumns: [],
+      // import
+      uploadUrl:
+        this.GLOBAL.domain + "/api/print/basic/cardRule/impExtendColums"
     };
   },
+  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: {
-    toImport() {}
+    uplaodError(msg) {
+      this.$message.error(msg);
+    },
+    uploadSuccess(response) {
+      this.$message.success("导入成功!");
+      this.extendColumns = response.data.data.map(item => {
+        item.select = false;
+        return item;
+      });
+    },
+    getSelectColumns() {
+      return {
+        examMustColumn: JSON.stringify(this.mustColumns),
+        examExtendColumn: JSON.stringify(this.extendColumns)
+      };
+    }
   }
 };
 </script>

+ 1 - 1
src/modules/base/components/ModifyData.vue

@@ -93,7 +93,7 @@ export default {
       this.modalIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       if (this.isSubmit) return;

+ 128 - 22
src/modules/base/components/RuleCard.vue

@@ -1,30 +1,35 @@
 <template>
   <div class="rule-card rule-form">
-    <el-form ref="ModalForm1" label-width="90px" inline>
-      <el-form-item label="版号版式:">
+    <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.paperType"
+          v-model="modalForm.examNumberStyle"
           style="width: 142px;"
           placeholder="请选择"
-          clearable
         >
           <el-option
-            v-for="(val, key) in paperTypes"
+            v-for="(val, key) in EXAM_NUMBER_STYLE"
             :key="key"
             :value="key"
             :label="val"
           ></el-option>
         </el-select>
       </el-form-item>
-      <el-form-item label="AB卷版式:">
+      <el-form-item prop="paperType" label="AB卷版式:">
         <el-select
           v-model="modalForm.paperType"
           style="width: 142px;"
           placeholder="请选择"
-          clearable
         >
           <el-option
-            v-for="(val, key) in paperTypes"
+            v-for="(val, key) in PAPER_TYPE"
             :key="key"
             :value="key"
             :label="val"
@@ -32,27 +37,44 @@
         </el-select>
       </el-form-item>
       <el-form-item style="margin-left: 30px;">
-        <el-checkbox v-model="modalForm.absent">启用“缺考填涂”</el-checkbox>
+        <el-checkbox v-model="modalForm.examAbsent">启用“缺考填涂”</el-checkbox>
       </el-form-item>
       <el-form-item style="margin-left: 30px;">
-        <el-checkbox v-model="modalForm.write">启用“手写签名”</el-checkbox>
+        <el-checkbox v-model="modalForm.writeSign">启用“手写签名”</el-checkbox>
       </el-form-item>
     </el-form>
-    <el-form ref="ModalForm2" label-width="130px" style="max-width: 850px;">
+
+    <el-form
+      ref="ModalFormRow"
+      label-width="140px"
+      :rules="rulesRow"
+      :model="modalForm"
+      style="max-width: 850px;"
+    >
       <el-form-item label="考务字段:">
-        <business-fields></business-fields>
+        <business-fields
+          :data="modalForm"
+          ref="BusinessFields"
+          v-if="dataReady"
+        ></business-fields>
       </el-form-item>
-      <el-form-item label="注意事项:">
-        <el-input type="textarea" v-model="modalForm.tips"></el-input>
+      <el-form-item prop="attention" label="注意事项:">
+        <el-input type="textarea" v-model="modalForm.attention"></el-input>
       </el-form-item>
-      <el-form-item label="客观题注意事项:">
-        <el-input v-model="modalForm.tips"></el-input>
+      <el-form-item prop="objectiveAttention" label="客观题注意事项:">
+        <el-input v-model="modalForm.objectiveAttention"></el-input>
       </el-form-item>
-      <el-form-item label="主观题注意事项:">
-        <el-input v-model="modalForm.tips"></el-input>
+      <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="save">保存</el-button>
+        <el-button
+          type="primary"
+          @click="submit"
+          :disabled="isSubmit"
+          style="width:88px"
+          >保存</el-button
+        >
       </el-form-item>
     </el-form>
   </div>
@@ -60,6 +82,8 @@
 
 <script>
 import BusinessFields from "./BusinessFields";
+import { EXAM_NUMBER_STYLE, PAPER_TYPE } from "@/constants/enumerate";
+import { cardRuleDetail, saveCardRule } from "../api";
 
 export default {
   name: "rule-card",
@@ -69,13 +93,95 @@ export default {
   data() {
     return {
       modalForm: {
-        paperType: ""
+        examNumberStyle: "",
+        paperType: "",
+        examAbsent: true,
+        writeSign: true,
+        examMustColumn: "",
+        examExtendColumn: "",
+        attention: "",
+        objectiveAttention: "",
+        subjectiveAttention: ""
       },
-      paperTypes: []
+      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"
+          }
+        ],
+        objectiveAttention: [
+          {
+            required: true,
+            message: "请输入客观题注意事项",
+            trigger: "change"
+          }
+        ],
+        subjectiveAttention: [
+          {
+            required: true,
+            message: "请输入主观题注意事项",
+            trigger: "change"
+          }
+        ]
+      }
     };
   },
+  mounted() {
+    this.getCardRule();
+  },
   methods: {
-    save() {}
+    async getCardRule() {
+      const data = await cardRuleDetail(this.$ls.get("schoolId"));
+      this.modalForm = Object.assign(this.modalForm, data[0]);
+      this.modalForm.examNumberStyle += "";
+      this.modalForm.paperType += "";
+      this.dataReady = true;
+    },
+    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 *= 1;
+      modals.paperType *= 1;
+      const data = await saveCardRule(modals).catch(() => {
+        this.isSubmit = false;
+      });
+      if (!data) return;
+      this.$message.success("保存成功!");
+    }
   }
 };
 </script>

+ 36 - 43
src/modules/base/components/RuleWarning.vue

@@ -2,10 +2,14 @@
   <div class="rule-warning rule-form">
     <p class="rule-tips">题卡/试卷制作计划预警:以“印刷计划”时间为参照</p>
     <el-form ref="ModalForm" label-width="90px">
-      <el-form-item label="命题老师:">
+      <el-form-item
+        v-for="(ruleItem, index) in warnRules"
+        :key="index"
+        :label="`${ruleItem.roleName}:`"
+      >
         <span class="rule-spin">提前</span>
         <el-select
-          v-model="modalForm.topicTeacher"
+          v-model="ruleItem.unit"
           style="width: 156px;"
           placeholder="请选择"
           clearable
@@ -14,62 +18,51 @@
             v-for="item in times"
             :key="item"
             :value="item"
-            :label="item"
-          ></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="管理员:">
-        <span class="rule-spin">提前</span>
-        <el-select
-          v-model="modalForm.topicTeacher"
-          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-item label="印刷员:">
-        <span class="rule-spin">提前</span>
-        <el-select
-          v-model="modalForm.topicTeacher"
-          style="width: 156px;"
-          placeholder="请选择"
-          clearable
-        >
-          <el-option
-            v-for="item in times"
-            :key="item"
-            :value="item"
-            :label="item"
+            :label="`${item}天`"
           ></el-option>
         </el-select>
       </el-form-item>
     </el-form>
     <div class="rule-btns">
-      <el-button type="primary">保存</el-button>
+      <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 {
-      modalForm: {
-        topicTeacher: "",
-        admin: "",
-        printer: ""
-      },
-      times: []
+      warnRules: [],
+      times: [1, 3, 5],
+      isSubmit: false
     };
   },
-  methods: {}
+  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>

+ 1 - 2
src/modules/base/views/RuleManage.vue

@@ -39,8 +39,7 @@ export default {
   methods: {
     selectMenu(item) {
       this.curMenu = item;
-    },
-    save() {}
+    }
   }
 };
 </script>

+ 22 - 21
src/modules/base/views/UserEdit.vue

@@ -10,7 +10,7 @@
         <el-input
           style="width:282px;"
           v-model.trim="modalForm.loginName"
-          placeholder="请输入年级名称"
+          placeholder="请输入用户名"
           clearable
         ></el-input>
       </el-form-item>
@@ -18,21 +18,21 @@
         <el-input
           style="width:282px;"
           v-model.trim="modalForm.name"
-          placeholder="请输入年级名称"
+          placeholder="请输入姓名"
           clearable
         ></el-input>
       </el-form-item>
-      <el-form-item prop="roleId" label="管理员:">
+      <el-form-item prop="roleCode" label="角色:">
         <el-select
           style="width:142px;"
-          v-model="modalForm.roleId"
+          v-model="modalForm.roleCode"
           placeholder="请选择角色"
         >
           <el-option
             v-for="item in roles"
             :key="item.id"
-            :label="item.name"
-            :value="item.id"
+            :label="item.roleName"
+            :value="item.roleCode"
           >
           </el-option>
         </el-select>
@@ -52,16 +52,17 @@
 </template>
 
 <script>
-import { updateUser } from "../api";
+import { updateUser, userDetail, roleList } from "../api";
 
 export default {
   name: "user-edit",
   data() {
     return {
       modalForm: {
+        userId: "",
         name: "",
         loginName: "",
-        roleId: ""
+        roleCode: ""
       },
       rules: {
         name: [
@@ -74,11 +75,11 @@ export default {
         loginName: [
           {
             required: true,
-            message: "请输入用户名",
+            message: "请输入名",
             trigger: "change"
           }
         ],
-        roleId: [
+        roleCode: [
           {
             required: true,
             message: "请选择角色",
@@ -86,22 +87,22 @@ export default {
           }
         ]
       },
-      roles: [
-        {
-          id: "1",
-          name: "教师"
-        },
-        {
-          id: "2",
-          name: "主任"
-        }
-      ],
+      roles: [],
       isSubmit: false
     };
   },
+  created() {
+    this.init();
+  },
   methods: {
+    async init() {
+      this.roles = await roleList();
+      const user = await userDetail(this.$router.params.userId);
+      this.modalForm = Object.assign({}, this.modalForm, user);
+      this.modalForm.userId = user.id;
+    },
     async submit(name) {
-      const valid = await this.$refs[name].validate();
+      const valid = await this.$refs[name].validate().catch(() => {});
       if (!valid) return;
 
       if (this.isSubmit) return;

+ 45 - 20
src/modules/base/views/UserManage.vue

@@ -45,9 +45,15 @@
           <el-button type="primary" icon="icon icon-search" @click="toPage(1)"
             >查询</el-button
           >
-          <el-button type="warning" icon="icon icon-share" @click="toPage(1)"
-            >导入</el-button
+          <upload-button
+            :upload-url="uploadUrl"
+            :format="['xls', 'xlsx']"
+            :upload-data="uploadData"
+            @upload-error="uplaodError"
+            @upload-success="uploadSuccess"
           >
+            <el-button type="warning" icon="icon icon-share">导入</el-button>
+          </upload-button>
         </el-form-item>
       </el-form>
     </div>
@@ -66,7 +72,7 @@
         <el-table-column prop="roleName" label="角色"></el-table-column>
         <el-table-column prop="courseName" label="科目"></el-table-column>
         <el-table-column prop="enable" label="状态"></el-table-column>
-        <el-table-column label="操作" align="center">
+        <el-table-column label="操作" align="center" width="120px">
           <template slot-scope="scope">
             <el-button
               class="btn-table-icon"
@@ -76,7 +82,7 @@
                   ? 'icon icon-circle-stop'
                   : 'icon icon-circle-caret-right'
               "
-              @click="toEdit(scope.row)"
+              @click="toEnable(scope.row)"
               :title="scope.row.enable ? '禁用' : '启用'"
             ></el-button>
             <el-button
@@ -90,8 +96,8 @@
               class="btn-table-icon"
               type="text"
               icon="icon icon-circle-lock"
-              @click="toEdit(scope.row)"
-              title="确认"
+              @click="toResetPwd(scope.row)"
+              title="重置密码"
             ></el-button>
           </template>
         </el-table-column>
@@ -108,24 +114,17 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curUser"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { ABLE_TYPE } from "@/constants/enumerate";
-import { userListPage } from "../api";
-import ModifyData from "../components/ModifyData";
+import { userListPage, ableUser, updatePwd } from "../api";
+import UploadButton from "@/components/UploadButton";
 
 export default {
   name: "user-manage",
-  components: { ModifyData },
+  components: { UploadButton },
   data() {
     return {
       filter: {
@@ -139,12 +138,17 @@ export default {
       visible: false,
       ABLE_TYPE,
       roles: [],
-      users: [{ id: "1" }],
-      curUser: {}
+      users: [{ id: "1", enable: false }],
+      // import
+      uploadUrl: this.GLOBAL.domain + "/api/print/basic/user/add",
+      uploadData: {
+        schoolId: this.$ls.get("schoolId"),
+        userId: this.$ls.get("user", { id: "" }).id
+      }
     };
   },
   created() {
-    // this.getList();
+    this.getList();
   },
   methods: {
     indexMethod(index) {
@@ -156,7 +160,7 @@ export default {
         pageNumber: this.current,
         pageSize: this.size
       };
-      data.enable *= 1;
+      datas.enable *= 1;
       const data = await userListPage(datas);
       this.users = data.records;
       this.total = data.total;
@@ -165,6 +169,13 @@ export default {
       this.current = page;
       this.getList();
     },
+    async toEnable(row) {
+      await ableUser({
+        userId: row.id,
+        enable: !row.enable
+      });
+      row.enable = !row.enable;
+    },
     toEdit(row) {
       this.$router.push({
         name: "UserEdit",
@@ -172,6 +183,20 @@ export default {
           userId: row.id
         }
       });
+    },
+    async toResetPwd(row) {
+      await updatePwd({
+        userId: row.userId,
+        password: "123456"
+      });
+      this.$message.success("密码重置成功!");
+    },
+    uplaodError(msg) {
+      this.$message.error(msg);
+    },
+    uploadSuccess(res) {
+      this.$message.success("上传成功!");
+      this.getList();
     }
   }
 };

+ 1 - 1
src/modules/card/api.js

@@ -8,7 +8,7 @@ export const cardConfigInfos = datas => {
   return Promise.resolve({
     missAndFill: true,
     writeSign: true,
-    examNumberType: "auto", // auto:自动条码, empty:手动条码, fill:手动涂填
+    examNumberStyle: "auto", // auto:自动条码, empty:手动条码, fill:手动涂填
     aOrBSystem: true, // 后台附带的aOrB设置,如果有则使用这个值,如果没有则前台自动设置
     aOrBType: "auto", // fill:手动涂填,auto:自动条码
     schoolName: "河南财经政法大学",

+ 2 - 2
src/modules/card/card.temp.json

@@ -81,7 +81,7 @@
               "aOrBType": "auto",
               "missAndFill": true,
               "writeSign": true,
-              "examNumberType": "auto",
+              "examNumberStyle": "auto",
               "businessParams": [
                 {
                   "name": "学号",
@@ -201,7 +201,7 @@
     "showForbidArea": true,
     "missAndFill": true,
     "writeSign": true,
-    "examNumberType": "auto",
+    "examNumberStyle": "auto",
     "aOrBSystem": true,
     "aOrBType": "auto",
     "schoolName": "河南财经政法大学",

+ 4 - 4
src/modules/card/components/CardConfigPropEdit.vue

@@ -17,12 +17,12 @@
           </el-form-item>
           <el-form-item label="考号类型">
             <el-select
-              v-model="form.examNumberType"
+              v-model="form.examNumberStyle"
               placeholder="请选择学生考号类型"
               @change="editChange"
             >
               <el-option
-                v-for="item in examNumberTypeOptions"
+                v-for="item in examNumberStyleOptions"
                 :key="item.value"
                 :label="item.label"
                 :value="item.value"
@@ -78,7 +78,7 @@ export default {
   name: "card-config-prop-edit",
   data() {
     return {
-      examNumberTypeOptions: [
+      examNumberStyleOptions: [
         {
           label: "自动条码",
           value: "auto"
@@ -105,7 +105,7 @@ export default {
       drawer: false,
       form: {
         schoolName: "河南财经政法大学",
-        examNumberType: "fill",
+        examNumberStyle: "fill",
         aOrBType: "auto",
         aOrB: true,
         missAndFill: true,

+ 2 - 2
src/modules/card/components/SavePage.vue

@@ -108,7 +108,7 @@ export default {
       let fill_area = [];
       let barcode = [];
       // 学生考号
-      if (element.examNumberType === "fill") {
+      if (element.examNumberStyle === "fill") {
         // fill_area
         let listInfos = [];
         dom
@@ -135,7 +135,7 @@ export default {
             items: listInfos
           }
         ];
-      } else if (element.examNumberType === "auto") {
+      } else if (element.examNumberStyle === "auto") {
         // barcode
         barcode.push({
           field: "examNumber",

+ 5 - 5
src/modules/card/components/elementEdit/CardHead.vue

@@ -18,7 +18,7 @@
     </div>
 
     <template v-if="data.columnNumber === 2">
-      <div class="card-head-body" v-if="data.examNumberType !== 'fill'">
+      <div class="card-head-body" v-if="data.examNumberStyle !== 'fill'">
         <div class="grid-container">
           <div class="grid-row">
             <div class="grid-col grid-col-dash">
@@ -53,7 +53,7 @@
     </template>
 
     <template v-if="data.columnNumber > 2">
-      <div class="card-head-body" v-if="data.examNumberType !== 'fill'">
+      <div class="card-head-body" v-if="data.examNumberStyle !== 'fill'">
         <head-stdno class="card-head-part" :data="data"></head-stdno>
         <head-stdinfo class="card-head-part" :data="data"></head-stdinfo>
         <head-dynamic
@@ -119,15 +119,15 @@ export default {
         "card-head",
         {
           "card-head-narrow": this.data.columnNumber > 2,
-          "card-head-handle": this.data.examNumberType === "fill",
+          "card-head-handle": this.data.examNumberStyle === "fill",
           "card-head-normal":
-            this.data.examNumberType !== "fill" && this.data.columnNumber <= 2
+            this.data.examNumberStyle !== "fill" && this.data.columnNumber <= 2
         }
       ];
     },
     hasDynamicArea() {
       const noDynamic =
-        this.data.examNumberType === "fill"
+        this.data.examNumberStyle === "fill"
           ? !this.data.missAndFill && !this.data.aOrB
           : !this.data.missAndFill && !this.data.writeSign && !this.data.aOrB;
 

+ 4 - 3
src/modules/card/components/elementEdit/cardHeadSpin/HeadDynamic.vue

@@ -3,7 +3,7 @@
     <!-- write -->
     <div
       class="head-dynamic-part head-dynamic-write"
-      v-if="data.examNumberType !== 'fill' && data.writeSign"
+      v-if="data.examNumberStyle !== 'fill' && data.writeSign"
     >
       <div class="stdinfo-item">
         <span>手写签名</span>
@@ -101,7 +101,8 @@ export default {
   computed: {
     classes() {
       let partNum = 0;
-      if (this.data.examNumberType !== "fill" && this.data.writeSign) partNum++;
+      if (this.data.examNumberStyle !== "fill" && this.data.writeSign)
+        partNum++;
       if (this.data.missAndFill) partNum++;
       if (this.data.aOrB) partNum++;
 
@@ -113,7 +114,7 @@ export default {
   },
   methods: {
     initStyles() {
-      if (this.data.examNumberType === "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";

+ 1 - 1
src/modules/card/components/elementEdit/cardHeadSpin/HeadNotice.vue

@@ -29,7 +29,7 @@ export default {
         "head-notice",
         "card-head-body-spin",
         {
-          "head-notice-exam-number-fill": this.data.examNumberType === "fill"
+          "head-notice-exam-number-fill": this.data.examNumberStyle === "fill"
         }
       ];
     }

+ 3 - 3
src/modules/card/components/elementEdit/cardHeadSpin/HeadStdno.vue

@@ -1,9 +1,9 @@
 <template>
   <div :class="classes">
-    <div class="stdno-empty" v-if="data.examNumberType === 'empty'">
+    <div class="stdno-empty" v-if="data.examNumberStyle === 'empty'">
       <p class="">黏贴条形码区</p>
     </div>
-    <div class="stdno-auto" v-if="data.examNumberType === 'auto'">
+    <div class="stdno-auto" v-if="data.examNumberStyle === 'auto'">
       <div class="stdno-auto-barcode">
         <img
           :src="examNumberBarcodeSrc"
@@ -13,7 +13,7 @@
         <img src="@/assets/images/barcode-sample.png" alt="条形码" v-else />
       </div>
     </div>
-    <div class="stdno-fill" v-if="data.examNumberType === 'fill'">
+    <div class="stdno-fill" v-if="data.examNumberStyle === 'fill'">
       <div class="stdno-fill-head">
         <h5>准考证号</h5>
         <div class="stdno-fill-rect">

+ 1 - 1
src/modules/card/components/elementPropEdit/EditComposition.vue

@@ -95,7 +95,7 @@ export default {
       this.dialogIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       this.$emit("modified", this.modalForm);

+ 1 - 1
src/modules/card/components/elementPropEdit/EditExplain.vue

@@ -123,7 +123,7 @@ export default {
       this.dialogIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       this.modalForm.questionsCount =

+ 1 - 1
src/modules/card/components/elementPropEdit/EditFillLine.vue

@@ -150,7 +150,7 @@ export default {
       this.dialogIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       this.modalForm.questionsCount =

+ 1 - 1
src/modules/card/components/elementPropEdit/EditFillQuestion.vue

@@ -149,7 +149,7 @@ export default {
       this.dialogIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       this.modalForm.questionsCount =

+ 1 - 1
src/modules/card/components/elementPropEdit/EditText.vue

@@ -155,7 +155,7 @@ export default {
       this.dialogIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       this.$emit("modified", this.modalForm);

+ 1 - 1
src/modules/card/elementModel.js

@@ -42,7 +42,7 @@ const CARD_HEAD_PROP = {
   aOrBType: "fill", // fill:手动填涂,auto:自动条码
   missAndFill: true,
   writeSign: true,
-  examNumberType: "auto", // auto:自动条码, empty:手动条码, fill:手动填涂
+  examNumberStyle: "auto", // auto:自动条码, empty:手动条码, fill:手动填涂
   businessParams: [],
   noticeHead: [],
   columnNumber: 2,

+ 1 - 1
src/modules/card/views/CardPreview.vue

@@ -123,7 +123,7 @@ export default {
       cardConfig.businessParams.map(item => {
         fieldInfos[item.field] = stdInfo[item.field] || defContent;
       });
-      if (cardConfig.examNumberType === "auto")
+      if (cardConfig.examNumberStyle === "auto")
         fieldInfos.examNumber = this.getBase64Barcode(
           stdInfo["examNumber"] || defNumber
         );

+ 8 - 6
src/modules/exam-center/api.js

@@ -2,12 +2,12 @@ import { $get, $post } from "@/plugins/axios";
 
 // wait-manage
 export const waitTaskListPage = datas => {
-  return $get("/api/print/exam/notDone/listPage", datas);
+  return $get("/api/print/exam/examTask/listNotDonePage", datas);
 };
-export const waitTaskDetail = datas => {
-  return $get("/api/print/exam/notDone/detail", datas);
+export const waitTaskDetail = id => {
+  return $get("/api/print/exam/notDone/detail", { id });
 };
-export const updateWaitTask = datas => {
+export const saveWaitTask = datas => {
   return $post("/api/print/exam/notDone/draft", datas);
 };
 export const submitWaitTask = datas => {
@@ -16,7 +16,7 @@ export const submitWaitTask = datas => {
 
 // done-task
 export const doneTaskListPage = datas => {
-  return $get("/api/print/exam/done/listPage", datas);
+  return $get("/api/print/exam/examTask/listDonePage", datas);
 };
 export const doneTaskDetail = datas => {
   return $get("/api/print/exam/done/detail", datas);
@@ -53,5 +53,7 @@ export const allCardList = datas => {
 
 // print-manage
 export const printTaskListPage = datas => {
-  return $get("/api/print/manager/listPage", datas);
+  return $get("/api/print/manager/list", datas);
 };
+
+// card-audit

+ 172 - 0
src/modules/exam-center/components/FileUploadView.vue

@@ -0,0 +1,172 @@
+<template>
+  <el-dialog
+    class="file-upload-view"
+    :visible.sync="modalIsShow"
+    title="上传试卷文件"
+    top="10vh"
+    width="580px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <div class="file-upload-body">
+      <el-form label-width="75px" label-position="left">
+        <el-form-item label="试卷文件:">
+          <el-input
+            v-model="file.name"
+            style="width: 270px;"
+            readonly
+          ></el-input>
+          <el-upload
+            style="display:inline-block;margin: 0 26px 0 10px;"
+            :action="uploadUrl"
+            :headers="headers"
+            :max-size="maxSize"
+            :format="format"
+            :accept="accept"
+            :data="uploadData"
+            :before-upload="handleBeforeUpload"
+            :on-error="handleError"
+            :on-success="handleSuccess"
+            :on-remove="handleRemove"
+            ref="UploadComp"
+          >
+            <el-button type="primary">选择</el-button>
+          </el-upload>
+          <el-button @click="toPreview">预览</el-button>
+        </el-form-item>
+      </el-form>
+      <p
+        slot="tip"
+        :class="[
+          `cc-tips`,
+          {
+            'cc-tips-success': res.success,
+            'cc-tips-error': !res.success
+          }
+        ]"
+        v-if="res.msg"
+      >
+        {{ res.msg }}
+      </p>
+    </div>
+    <div slot="footer" style="text-align: right">
+      <el-button type="primary" @click="confirm">保存</el-button>
+      <el-button @click="cancel">返回</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: "file-upload-view",
+  data() {
+    return {
+      modalIsShow: false,
+      file: {},
+      uploadUrl: this.GLOBAL.domain + "/api/print/basic/sys/saveAttachment",
+      maxSize: 10 * 1024 * 1024,
+      addFilenameParam: "file",
+      headers: {},
+      uploadData: {},
+      format: ["doc", "docx"],
+      res: {
+        success: true,
+        msg: ""
+      }
+    };
+  },
+  computed: {
+    accept() {
+      return this.format.map(el => `.${el}`).join();
+    }
+  },
+  methods: {
+    visibleChange() {
+      this.res = {
+        success: true,
+        msg: ""
+      };
+    },
+    checkFileFormat(fileType) {
+      const _file_format = fileType
+        .split("/")
+        .pop()
+        .toLocaleLowerCase();
+      return this.format.some(
+        item => item.toLocaleLowerCase() === _file_format
+      );
+    },
+    handleBeforeUpload(file) {
+      this.file = {
+        id: "",
+        name: file.name
+      };
+
+      if (this.addFilenameParam)
+        this.uploadData[this.addFilenameParam] = file.name;
+
+      if (file.size > this.maxSize) {
+        this.handleExceededSize();
+        return Promise.reject();
+      }
+
+      if (!this.checkFileFormat(file.type)) {
+        this.handleFormatError();
+        return Promise.reject();
+      }
+
+      return true;
+    },
+    handleError(error) {
+      this.res = {
+        success: false,
+        msg: error.message
+      };
+      this.$emit("upload-error", error);
+    },
+    handleSuccess(response) {
+      this.res = {
+        success: true,
+        msg: "导入成功!"
+      };
+      this.$emit("upload-success", response);
+    },
+    handleFormatError() {
+      this.res = {
+        success: false,
+        msg: "只支持文件格式为" + this.format.join("/")
+      };
+      this.$refs.UploadComp.clearFiles();
+    },
+    handleExceededSize() {
+      this.res = {
+        success: false,
+        msg: "文件大小不能超过" + Math.floor(this.maxSize / 1024) + "M"
+      };
+      this.$refs.UploadComp.clearFiles();
+    },
+    handleRemove() {
+      this.$refs.UploadComp.abort();
+      this.$refs.UploadComp.clearFiles();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    confirm() {
+      this.$emit("confirm", this.file);
+    },
+    toPreview() {}
+  }
+};
+</script>
+
+<style lang="css" scoped>
+.file-upload-body {
+  min-height: 150px;
+}
+</style>

+ 0 - 114
src/modules/exam-center/components/ModifyData.vue

@@ -1,114 +0,0 @@
-<template>
-  <el-dialog
-    class="modify-data"
-    :visible.sync="modalIsShow"
-    :title="title"
-    top="10vh"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false"
-    append-to-body
-    @open="visibleChange"
-  >
-    <el-form
-      ref="modalFormComp"
-      :model="modalForm"
-      :rules="rules"
-      :key="modalForm.id"
-      label-width="100px"
-    >
-      <el-form-item prop="name" label="年级名称">
-        <el-input
-          v-model.trim="modalForm.name"
-          placeholder="请输入年级名称"
-          clearable
-        ></el-input>
-      </el-form-item>
-    </el-form>
-    <div slot="footer">
-      <el-button type="danger" @click="cancel" plain>取消</el-button>
-      <el-button type="primary" :disabled="isSubmit" @click="submit"
-        >确认</el-button
-      >
-    </div>
-  </el-dialog>
-</template>
-
-<script>
-import { updateWaitTask } from "../api";
-
-const initModalForm = {
-  id: "",
-  name: ""
-};
-
-export default {
-  name: "modify-data",
-  props: {
-    instance: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  computed: {
-    isEdit() {
-      return !!this.instance.id;
-    },
-    title() {
-      return (this.isEdit ? "编辑" : "新增") + "年级";
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      isSubmit: false,
-      modalForm: { ...initModalForm },
-      rules: {
-        name: [
-          {
-            required: true,
-            message: "请输入年级名称",
-            trigger: "change"
-          }
-        ]
-      }
-    };
-  },
-  methods: {
-    initData(val) {
-      if (val.id) {
-        this.modalForm = this.$objAssign(initModalForm, val);
-      } else {
-        this.modalForm = { ...initModalForm };
-      }
-    },
-    visibleChange() {
-      this.initData(this.instance);
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
-      if (!valid) return;
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      const data = await updateWaitTask(this.modalForm).catch(() => {
-        this.isSubmit = false;
-      });
-
-      if (!data) return;
-
-      this.isSubmit = false;
-      this.$message.success(this.title + "成功!");
-      this.$emit("modified");
-      this.cancel();
-    }
-  }
-};
-</script>

+ 0 - 9
src/modules/exam-center/views/CardAudit.vue

@@ -106,24 +106,15 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curExam"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { AUDITING_STATUS } from "@/constants/enumerate";
 import { printTaskListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "card-check",
-  components: { ModifyData },
   data() {
     return {
       filter: {

+ 0 - 9
src/modules/exam-center/views/CardManage.vue

@@ -110,24 +110,15 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curExam"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { AUDITING_STATUS } from "@/constants/enumerate";
 import { printTaskListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "card-check",
-  components: { ModifyData },
   data() {
     return {
       filter: {

+ 6 - 12
src/modules/exam-center/views/DoneTask.vue

@@ -63,23 +63,14 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curTask"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { doneTaskListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "done-task",
-  components: { ModifyData },
   data() {
     return {
       filter: {
@@ -90,14 +81,17 @@ export default {
       total: 0,
       visible: false,
       exams: [],
-      tasks: [{ id: "2" }],
-      curTask: {}
+      tasks: [{ id: "2" }]
     };
   },
   created() {
-    // this.getList();
+    // this.init();
   },
   methods: {
+    init() {
+      this.getExamList();
+      this.getList();
+    },
     async getList() {
       const datas = {
         ...this.filter,

+ 87 - 18
src/modules/exam-center/views/DoneTaskDetail.vue

@@ -2,8 +2,8 @@
   <div class="done-task-detail task-detail">
     <div class="task-title">
       <h2>
-        <span>考试名称: 这里是考试名称目前不知晓字数 </span>
-        <span>科目名称:语文</span>
+        <span>考试名称: {{ task.examName }} </span>
+        <span>科目名称:{{ task.courseName }}</span>
       </h2>
     </div>
     <div class="task-body">
@@ -15,26 +15,47 @@
           <th>标答</th>
           <th>试卷结构</th>
         </tr>
-        <tr>
-          <td>A卷</td>
-          <td>试卷名称在这里</td>
-          <td :rowspan="aOrB ? 2 : 1">
-            答题卡名称
+        <tr
+          v-for="(attachment, index) in paperAttachments"
+          :key="attachment.id"
+        >
+          <td>{{ attachment.name }}卷</td>
+          <td class="td-link">
+            <span @click="downloadPaper(attachment)" title="点击下载试卷">{{
+              `${task.examName}试卷${attachment.name}`
+            }}</span>
           </td>
-          <td><i class="icon icon-download-act"></i>A卷标答下载</td>
-          <td :rowspan="aOrB ? 2 : 1">
-            <i class="icon icon-download-act"></i>试卷结构下载
+          <td
+            class="td-link"
+            :rowspan="pTypeEnable ? paperAttachments.length : 1"
+            v-if="index === 0"
+          >
+            <span @click="toPreviewCard" title="点击预览答题卡内容">{{
+              task.cardTitle
+            }}</span>
+          </td>
+          <td class="td-link">
+            <span @click="downloadStdAns(attachment)"
+              ><i class="icon icon-download-act"></i
+              >{{ attachment.name }}卷标答下载</span
+            >
+          </td>
+          <td
+            class="td-link"
+            :rowspan="pTypeEnable ? paperAttachments.length : 1"
+            v-if="index === 0"
+          >
+            <span @click="downloadPaperStructure">
+              <i class="icon icon-download-act"></i>试卷结构下载
+            </span>
           </td>
-        </tr>
-        <tr v-if="aOrB">
-          <td>B卷</td>
-          <td>试卷名称在这里</td>
-          <td><i class="icon icon-download-act"></i>B卷标答下载</td>
         </tr>
       </table>
 
       <div class="task-action">
-        <el-button type="danger" style="width:88px;">撤回</el-button>
+        <el-button type="danger" @click="toRevoke" style="width:88px;"
+          >撤回</el-button
+        >
         <el-button @click="goback" style="width:88px;">返回</el-button>
       </div>
     </div>
@@ -42,14 +63,62 @@
 </template>
 
 <script>
+import { doneTaskDetail, revokeDoneTask } from "../api";
+
 export default {
   name: "done-task-detail",
   data() {
     return {
       taskId: this.$route.params.taskId,
-      aOrB: true
+      PAPER_TYPE_FIELDS: ["A", "B"],
+      task: {},
+      pTypeEnable: false,
+      paperAttachments: [],
+      curAttachment: {}
     };
   },
-  methods: {}
+  methods: {
+    async getData() {
+      this.task = await doneTaskDetail(this.taskId);
+      this.pTypeEnable = this.task.enablePaperType.split(",").length > 1;
+      this.parsePaperAttachment();
+    },
+    parsePaperAttachment() {
+      const paperAttachment =
+        this.task.paperAttachmentId && JSON.parse(this.task.paperAttachmentId);
+      if (!paperAttachment) return;
+
+      this.paperAttachments = paperAttachment.paper;
+    },
+    toRevoke() {
+      this.$confirm("确定要撤回当前任务吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(async () => {
+        await revokeDoneTask(this.taskId);
+        this.goback();
+      });
+    },
+    downloadPaper(attachment) {
+      window.open(attachment.path);
+    },
+    downloadStdAns(attachment) {
+      // TODO:
+      window.open(attachment.path);
+    },
+    downloadPaperStructure() {
+      // TODO:
+    },
+    toPreviewCard() {
+      this.$router.push({
+        name: "CardPreview",
+        params: {
+          cardId: this.task.cardId,
+          viewType: "view"
+        }
+      });
+    }
+  }
 };
 </script>

+ 20 - 15
src/modules/exam-center/views/ExamManage.vue

@@ -74,7 +74,7 @@
               class="btn-table-icon"
               type="text"
               icon="icon icon-delete"
-              @click="toEdit(scope.row)"
+              @click="toDelete(scope.row)"
               title="删除"
             ></el-button>
             <el-button
@@ -99,24 +99,15 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curExam"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { PRINT_STATUS } from "@/constants/enumerate";
-import { examListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
+import { examListPage, examList, deleteExam } from "../api";
 
 export default {
   name: "exam-manage",
-  components: { ModifyData },
   data() {
     return {
       filter: {
@@ -130,14 +121,17 @@ export default {
       visible: false,
       PRINT_STATUS,
       exams: [],
-      examPages: [{ id: "1" }],
-      curExam: {}
+      examPages: [{ id: "1" }]
     };
   },
   created() {
-    // this.getList();
+    // this.init();
   },
   methods: {
+    init() {
+      this.getList();
+      this.getExamList();
+    },
     async getList() {
       const datas = {
         ...this.filter,
@@ -161,6 +155,17 @@ export default {
         };
       });
     },
+    toDelete(row) {
+      this.$confirm("确定要删除当前任务吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(async () => {
+        await deleteExam(row.id);
+        this.$message.success("删除成功!");
+        this.deletePageLastItem();
+      });
+    },
     toAdd() {
       this.$router.push({
         name: "ExamAdd"
@@ -178,7 +183,7 @@ export default {
       this.$router.push({
         name: "ExamRomeDetail",
         params: {
-          examId: "1"
+          examId: row.id
         }
       });
     }

+ 0 - 9
src/modules/exam-center/views/ExamRomeDetail.vue

@@ -90,24 +90,15 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curExam"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { PRINT_STATUS } from "@/constants/enumerate";
 import { examListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "exam-room-detail",
-  components: { ModifyData },
   data() {
     return {
       filter: {

+ 0 - 9
src/modules/exam-center/views/ExamRomeStudentDetail.vue

@@ -115,24 +115,15 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curExam"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { PRINT_STATUS } from "@/constants/enumerate";
 import { examListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "exam-room-detail",
-  components: { ModifyData },
   data() {
     return {
       filter: {

+ 10 - 16
src/modules/exam-center/views/PrintManage.vue

@@ -62,7 +62,7 @@
               class="btn-table-icon"
               type="text"
               icon="icon icon-confirm"
-              @click="toEdit(scope.row)"
+              @click="toConfirm(scope.row)"
               title="确认"
             ></el-button>
           </template>
@@ -80,24 +80,15 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curExam"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { REVOKE_STATUS } from "@/constants/enumerate";
 import { printTaskListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "exam-manage",
-  components: { ModifyData },
   data() {
     return {
       filter: {
@@ -111,14 +102,17 @@ export default {
       visible: false,
       REVOKE_STATUS,
       exams: [],
-      examPages: [{ id: "" }],
-      curExam: {}
+      examPages: [{ id: "" }]
     };
   },
   created() {
-    // this.getList();
+    // this.init();
   },
   methods: {
+    init() {
+      this.getExamList();
+      this.getList();
+    },
     async getList() {
       const datas = {
         ...this.filter,
@@ -142,9 +136,9 @@ export default {
         };
       });
     },
-    toEdit(row) {
-      this.curExam = row;
-      this.$refs.ModifyData.open();
+    toConfirm(row) {
+      // TODO:
+      console.log(row);
     }
   }
 };

+ 6 - 12
src/modules/exam-center/views/WaitTask.vue

@@ -63,23 +63,14 @@
         </el-pagination>
       </div>
     </div>
-
-    <!-- modify-data -->
-    <modify-data
-      :instance="curTask"
-      @modified="getList"
-      ref="ModifyData"
-    ></modify-data>
   </div>
 </template>
 
 <script>
 import { waitTaskListPage, examList } from "../api";
-import ModifyData from "../components/ModifyData";
 
 export default {
   name: "wait-task",
-  components: { ModifyData },
   data() {
     return {
       filter: {
@@ -90,14 +81,17 @@ export default {
       total: 0,
       visible: false,
       exams: [],
-      tasks: [{ id: "1" }],
-      curTask: {}
+      tasks: [{ id: "1" }]
     };
   },
   created() {
-    // this.getList();
+    // this.init();
   },
   methods: {
+    init() {
+      this.getExamList();
+      this.getList();
+    },
     async getList() {
       const datas = {
         ...this.filter,

+ 90 - 14
src/modules/exam-center/views/WaitTaskDetail.vue

@@ -2,11 +2,13 @@
   <div class="wait-task-detail task-detail">
     <div class="task-title">
       <h2>
-        <span>考试名称: 这里是考试名称目前不知晓字数 </span>
-        <span>科目名称:语文</span>
+        <span>考试名称: {{ task.examName }} </span>
+        <span>科目名称:{{ task.courseName }}</span>
       </h2>
       <div class="task-title-infos">
-        <el-checkbox v-model="aOrB">启用A/B卷</el-checkbox>
+        <el-checkbox v-model="pTypeEnable" @change="pTypeEnableChange"
+          >启用{{ checkboxContent }}卷</el-checkbox
+        >
       </div>
     </div>
     <div class="task-body">
@@ -16,16 +18,26 @@
           <th>试卷文件</th>
           <th>答题卡</th>
         </tr>
-        <tr>
-          <td>A卷</td>
-          <td><i class="icon icon-files"></i>点击上传试卷文件</td>
-          <td :rowspan="aOrB ? 2 : 1">
-            <i class="icon icon-plus-act"></i>创建答题卡
+        <tr v-for="(attachment, index) in curPaperAttachments" :key="index">
+          <td>{{ attachment.name }}卷</td>
+          <td class="td-link">
+            <span @click="toUpload(attachment)">
+              <i
+                :class="[
+                  'icon',
+                  attachment.id ? 'icon-files-act' : 'icon-files'
+                ]"
+              ></i
+              >点击上传试卷文件
+            </span>
+          </td>
+          <td
+            class="td-link"
+            :rowspan="pTypeEnable ? curPaperAttachments.length : 1"
+            v-if="index === 0"
+          >
+            <span><i class="icon icon-plus-act"></i>创建答题卡</span>
           </td>
-        </tr>
-        <tr v-if="aOrB">
-          <td>B卷</td>
-          <td><i class="icon icon-files"></i>点击上传试卷文件</td>
         </tr>
       </table>
 
@@ -35,18 +47,82 @@
         <el-button @click="goback" style="width:88px;">取消</el-button>
       </div>
     </div>
+
+    <!-- file-upload-view -->
+    <file-upload-view ref="FileUploadView"></file-upload-view>
   </div>
 </template>
 
 <script>
+import { waitTaskDetail, saveWaitTask } from "../api";
+import FileUploadView from "../components/FileUploadView";
+
 export default {
   name: "wait-task-detail",
+  components: {
+    FileUploadView
+  },
   data() {
     return {
       taskId: this.$route.params.taskId,
-      aOrB: false
+      PAPER_TYPE_FIELDS: ["A", "B"],
+      task: {},
+      pTypeEnable: false,
+      paperAttachments: [],
+      curPaperAttachments: [],
+      curAttachment: {}
     };
   },
-  methods: {}
+  computed: {
+    checkboxContent() {
+      return this.PAPER_TYPE_FIELDS.join("/");
+    }
+  },
+  mounted() {
+    this.parsePaperAttachment();
+    this.pTypeEnableChange();
+  },
+  methods: {
+    async getData() {
+      this.task = await waitTaskDetail(this.taskId);
+      this.pTypeEnable = this.task.enablePaperType.split(",").length > 1;
+      this.parsePaperAttachment();
+    },
+    parsePaperAttachment() {
+      const paperAttachment =
+        this.task.paperAttachmentId && JSON.parse(this.task.paperAttachmentId);
+      const pagers = paperAttachment && paperAttachment.paper;
+      let pagerDict = {};
+      if (pagers) {
+        pagers.map(paper => {
+          pagerDict[paper.name] = paper;
+        });
+      }
+      this.paperAttachments = this.PAPER_TYPE_FIELDS.map(paperType => {
+        const paperInfo = pagerDict[paperType];
+        let paper = {
+          id: "",
+          name: paperType,
+          path: ""
+        };
+        return paperInfo ? Object.assign({}, paper, paperInfo) : paper;
+      });
+    },
+    pTypeEnableChange(val) {
+      this.curPaperAttachments = val
+        ? this.paperAttachments
+        : [this.paperAttachments[0]];
+    },
+    toUpload(attachment) {
+      this.curAttachment = attachment;
+      this.$refs.FileUploadView.open();
+    },
+    async save() {
+      let datas = { ...this.task };
+      if (this.pTypeEnable)
+        datas.enablePaperType = this.PAGE_TYPE_FIELDS.join();
+      await saveWaitTask(datas);
+    }
+  }
 };
 </script>

+ 1 - 1
src/modules/example/components/ModifyData.vue

@@ -93,7 +93,7 @@ export default {
       this.modalIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       if (this.isSubmit) return;

+ 4 - 1
src/modules/login/api.js

@@ -1,8 +1,11 @@
-import { $post } from "@/plugins/axios";
+import { $post, $get } from "@/plugins/axios";
 
 export const login = datas => {
   return $post("/api/print/basic/user/login", datas);
 };
+export const logout = userId => {
+  return $get("/api/print/basic/sys/logout", { userId });
+};
 export const sysMenu = datas => {
   return $post("/api/print/basic/sys/getMenu", datas);
 };

+ 22 - 24
src/modules/login/views/Login.vue

@@ -6,9 +6,9 @@
       </div>
       <div class="login-form">
         <el-form ref="loginForm" :model="loginModel" :rules="loginRules">
-          <el-form-item prop="username">
+          <el-form-item prop="loginName">
             <el-input
-              v-model.trim="loginModel.username"
+              v-model.trim="loginModel.loginName"
               placeholder="请输入账号"
               clearable
             >
@@ -25,18 +25,18 @@
               <i class="icon icon-lock" slot="prefix"></i
             ></el-input>
           </el-form-item>
-          <el-form-item prop="roleId">
+          <el-form-item prop="roleCode">
             <el-select
               style="width:175px;"
-              v-model="loginModel.roleId"
+              v-model="loginModel.roleCode"
               placeholder="请选择角色"
             >
               <i class="icon icon-role" slot="prefix"></i>
               <el-option
                 v-for="item in roles"
                 :key="item.id"
-                :label="item.name"
-                :value="item.id"
+                :label="item.roleName"
+                :value="item.roleCode"
               >
               </el-option>
             </el-select>
@@ -61,25 +61,26 @@
 <script>
 import { password } from "@/plugins/formRules";
 import { login } from "../api";
+import { roleList } from "@/modules/base/api";
 
 export default {
   name: "login",
   data() {
     return {
       loginModel: {
-        username: "",
-        password: "",
-        roleId: ""
+        loginName: "admin",
+        password: "123456",
+        roleCode: ""
       },
       loginRules: {
-        username: [
+        loginName: [
           {
             required: true,
             message: "请输入用户名",
             trigger: "change"
           }
         ],
-        roleId: [
+        roleCode: [
           {
             required: true,
             message: "请选择角色",
@@ -88,25 +89,21 @@ export default {
         ],
         password
       },
-      roles: [
-        {
-          id: "1",
-          name: "教师"
-        },
-        {
-          id: "2",
-          name: "主任"
-        }
-      ],
+      roles: [],
       isSubmit: false
     };
   },
   mounted() {
+    this.getRoleList();
     this.$ls.clear();
   },
   methods: {
+    async getRoleList() {
+      const data = await roleList();
+      this.roles = data.records;
+    },
     async submit(name) {
-      const valid = await this.$refs[name].validate();
+      const valid = await this.$refs[name].validate().catch(() => {});
       if (!valid) return;
 
       if (this.isSubmit) return;
@@ -118,8 +115,9 @@ export default {
 
       this.isSubmit = false;
       this.$ls.set("token", data.token, this.GLOBAL.authTimeout);
-      this.$ls.set("user", data.user, this.GLOBAL.authTimeout);
-      this.$store.commit("setUser", data.user);
+      this.$ls.set("schoolId", data.account.schoolId, this.GLOBAL.authTimeout);
+      this.$ls.set("user", data.account, this.GLOBAL.authTimeout);
+      this.$store.commit("setUser", data.account);
       this.$router.push({
         name: "Home"
       });

+ 1 - 1
src/modules/score-paper/components/ModifyData.vue

@@ -93,7 +93,7 @@ export default {
       this.modalIsShow = true;
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate();
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
       if (!valid) return;
 
       if (this.isSubmit) return;

+ 22 - 15
src/plugins/axios.js

@@ -4,6 +4,14 @@ import { MessageBox, Notification } from "element-ui";
 import router from "../router";
 import Vue from "vue";
 
+const mdData = datas => {
+  return {
+    ...datas,
+    schoolId: Vue.ls.get("schoolId"),
+    userId: Vue.ls.get("user", { id: "" }).id
+  };
+};
+
 /**
  * errorCallback 请求失败的回调
  * @param {Object} error 请求失败时的错误信息
@@ -36,9 +44,10 @@ const errorDataCallback = error => {
   message = message.indexOf("###") !== -1 ? "参数错误" : message;
 
   // TODO:自定义处理逻辑,以下为epcc实例
-  if (error.code === -100) {
+  if (error.code === "105" || error.code === "106") {
     message = "身份验证失效,请重新登录";
     MessageBox.confirm(message, "重新登陆?", {
+      type: "error",
       callback: action => {
         if (action !== "confirm") return;
         Vue.ls.clear();
@@ -64,7 +73,7 @@ const errorDataCallback = error => {
  * @param {Object} data Response中的data信息
  */
 const successCallback = data => {
-  if (data.code === 0) {
+  if (data.code === "200") {
     return data.data;
   } else {
     throw new Error(errorDataCallback(data));
@@ -77,13 +86,11 @@ const successCallback = data => {
  * @param {Object} datas 请求数据
  */
 const $get = (url, datas) => {
-  let sqDatas = "";
-  if (datas) {
-    sqDatas = qs.stringify(datas, {
-      arrayFormat: "brackets"
-    });
-    url += "?" + sqDatas;
-  }
+  const sqDatas = qs.stringify(mdData(datas), {
+    arrayFormat: "brackets"
+  });
+  url += "?" + sqDatas;
+
   return axios
     .get(url)
     .then(rep => {
@@ -100,12 +107,12 @@ const $get = (url, datas) => {
  * @param {Object} datas 请求数据
  */
 const $post = (url, datas) => {
-  let sqDatas = "";
-  if (datas.constructor === Object) {
-    sqDatas = qs.stringify(datas, { allowDots: true });
-  } else {
-    sqDatas = datas;
-  }
+  const sqDatas = mdData(datas);
+  // if (datas.constructor === Object) {
+  //   sqDatas = qs.stringify(datas, { allowDots: true });
+  // } else {
+  //   sqDatas = datas;
+  // }
 
   return axios
     .post(url, sqDatas)

+ 43 - 0
src/plugins/crypto.js

@@ -0,0 +1,43 @@
+const CryptoJS = require("crypto-js");
+
+/**
+ *
+ * @param {String} str 字符串
+ */
+export const md5 = str => {
+  return CryptoJS.MD5(str + "").toString();
+};
+
+/**
+ *
+ * @param {File} file 二进制文件
+ */
+export const fileMd5 = file => {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.onloadend = function() {
+      const arrayBuffer = reader.result;
+      resolve(CryptoJS.MD5(arrayBuffer).toString());
+    };
+    reader.onerror = function(err) {
+      reject(err);
+    };
+    reader.readAsArrayBuffer(file);
+  });
+};
+
+/**
+ *
+ * @param {String} key 编码的key值
+ * @param {String} content 需要编码的内容
+ */
+export const aes = (key, content) => {
+  const encodeKey = CryptoJS.enc.Utf8.parse(key);
+
+  const enstr = CryptoJS.AES.encrypt(content + "", encodeKey, {
+    mode: CryptoJS.mode.ECB,
+    padding: CryptoJS.pad.Pkcs7
+  }).toString();
+
+  return encodeURIComponent(enstr);
+};

+ 4 - 2
src/views/Home.vue

@@ -27,7 +27,7 @@
               <span>账户设置</span>
             </div>
           </li>
-          <li @click="logout">
+          <li @click="toLogout">
             <div class="menu-item">
               <i class="icon icon-shut"></i>
               <span>退出登录</span>
@@ -97,6 +97,7 @@
 
 <script>
 import navs from "@/constants/navs";
+import { logout } from "../modules/login/api";
 
 export default {
   name: "home",
@@ -170,7 +171,8 @@ export default {
         name: elem.router
       });
     },
-    logout() {
+    async toLogout() {
+      await logout(this.$ls.get("user", { id: "" }).id);
       this.$ls.clear();
       this.$router.push({ name: "Login" });
     }

+ 5 - 0
yarn.lock

@@ -2546,6 +2546,11 @@ crypto-browserify@^3.11.0:
     randombytes "^2.0.0"
     randomfill "^1.0.3"
 
+crypto-js@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcrypto-js%2Fdownload%2Fcrypto-js-4.0.0.tgz#2904ab2677a9d042856a2ea2ef80de92e4a36dcc"
+  integrity sha1-KQSrJnep0EKFai6i74DekuSjbcw=
+
 css-color-names@0.0.4, css-color-names@^0.0.4:
   version "0.0.4"
   resolved "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"