From cbef0e8f5cf8538fb942879372e38c5b2fa09109 Mon Sep 17 00:00:00 2001
From: liuyg <376836862@qq.com>
Date: Wed, 28 Jul 2021 14:53:35 +0800
Subject: [PATCH] Merge branch 'master' of http://192.168.0.105:10010/r/zhba_enterprises

---
 src/views/trainExam/index.vue                        |  287 ++
 src/components/Subjects/Choices/index.vue            |   89 
 src/const/constant.js                                |   10 
 vue.config.js                                        |    4 
 src/assets/css/_responsive.scss                      |   11 
 src/api/examapi/performance.js                       |   21 
 src/components/Subjects/Judgement/index.vue          |   81 
 src/api/exam/knowledge.js                            |   18 
 src/api/exam/exam.js                                 |   84 
 src/api/examapi/examination.js                       |   39 
 src/api/exam/course.js                               |   57 
 src/assets/css/subject.scss                          |   81 
 src/api/exam/subjectCategory.js                      |   41 
 src/const/errorCode.js                               |   12 
 src/api/examapi/subject.js                           |   23 
 src/config/iconList.js                               |   11 
 src/components/Subjects/PracticalOperation/index.vue |  190 +
 src/components/Tinymce/toolbar.js                    |    6 
 src/views/exam/subject.vue                           |  263 ++
 src/views/singleperformance/index.vue                |  398 +++
 src/views/exam/startexam.vue                         |  388 +++
 src/api/exam/subject.js                              |   74 
 src/components/Subjects/ShortAnswer/index.vue        |   73 
 src/views/trainExam/data.js                          |  160 +
 src/views/exam/examination.vue                       |  478 +++
 src/views/applyexam/index.vue                        |  505 ++++
 src/assets/css/style.scss                            | 1084 ++++++++
 src/assets/css/transition.scss                       |   12 
 package-lock.json                                    |  176 
 src/assets/css/_fonts.scss                           |    3 
 src/router/views/index.js                            |   14 
 src/components/Tinymce/components/editorImage.vue    |  103 
 src/assets/css/_theme_color.scss                     |   29 
 src/components/Subjects/MultipleChoices/index.vue    |   99 
 src/views/exam/topicDetails.vue                      |  211 +
 src/views/startexam/index.vue                        |  663 +++++
 src/views/exam/performance.vue                       |  398 +++
 src/api/exam/answer.js                               |  124 +
 src/components/Tinymce/index.vue                     |  162 +
 src/components/Tinymce/plugins.js                    |    7 
 src/api/applyexam/applyexam.js                       |  120 
 src/api/exam/examRecord.js                           |   58 
 src/api/trainExam/trainExam.js                       |   62 
 src/config/env.js                                    |    2 
 src/views/exam/examSubjects.vue                      |  328 ++
 src/assets/css/mixin.scss                            |   79 
 src/api/examapi/applyexam.js                         |   47 
 package.json                                         |    4 
 src/api/examapi/examSubjects.js                      |   37 
 49 files changed, 7,139 insertions(+), 87 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 3290c05..ff99a2c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1705,7 +1705,7 @@
     },
     "amdefine": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz",
       "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
       "dev": true
     },
@@ -1808,7 +1808,7 @@
     },
     "array-find-index": {
       "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "resolved": "https://registry.npm.taobao.org/array-find-index/download/array-find-index-1.0.2.tgz",
       "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
       "dev": true
     },
@@ -1927,7 +1927,7 @@
     },
     "async-foreach": {
       "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+      "resolved": "https://registry.npm.taobao.org/async-foreach/download/async-foreach-0.1.3.tgz",
       "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
       "dev": true
     },
@@ -2270,7 +2270,7 @@
     },
     "block-stream": {
       "version": "0.0.9",
-      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+      "resolved": "https://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz",
       "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
       "dev": true,
       "requires": {
@@ -2676,7 +2676,7 @@
     },
     "camelcase-keys": {
       "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+      "resolved": "https://registry.nlark.com/camelcase-keys/download/camelcase-keys-2.1.0.tgz?cache=0&sync_timestamp=1624609060222&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcamelcase-keys%2Fdownload%2Fcamelcase-keys-2.1.0.tgz",
       "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
       "dev": true,
       "requires": {
@@ -2686,7 +2686,7 @@
       "dependencies": {
         "camelcase": {
           "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+          "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz?cache=0&sync_timestamp=1603921884289&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-2.1.1.tgz",
           "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
           "dev": true
         }
@@ -3845,7 +3845,7 @@
     },
     "currently-unhandled": {
       "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/currently-unhandled/download/currently-unhandled-0.4.1.tgz",
       "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
       "dev": true,
       "requires": {
@@ -5419,8 +5419,8 @@
     },
     "fstream": {
       "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
-      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "resolved": "https://registry.nlark.com/fstream/download/fstream-1.0.12.tgz",
+      "integrity": "sha1-Touo7i1Ivk99DeUFRVVI6uWTIEU=",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -5459,8 +5459,8 @@
     },
     "gaze": {
       "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
-      "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+      "resolved": "https://registry.npm.taobao.org/gaze/download/gaze-1.1.3.tgz",
+      "integrity": "sha1-xEFzPhO5J6yMD/C0w7Az8ogSkko=",
       "dev": true,
       "requires": {
         "globule": "^1.0.0"
@@ -5497,7 +5497,7 @@
     },
     "get-stdin": {
       "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/get-stdin/download/get-stdin-4.0.1.tgz?cache=0&sync_timestamp=1618557641950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fget-stdin%2Fdownload%2Fget-stdin-4.0.1.tgz",
       "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
       "dev": true
     },
@@ -5585,8 +5585,8 @@
     },
     "globule": {
       "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
-      "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
+      "resolved": "https://registry.npm.taobao.org/globule/download/globule-1.3.2.tgz",
+      "integrity": "sha1-2L3Z6eTu+PluJFmZpd7n612FKcQ=",
       "dev": true,
       "requires": {
         "glob": "~7.1.1",
@@ -6217,13 +6217,13 @@
     },
     "in-publish": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz",
-      "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==",
+      "resolved": "https://registry.nlark.com/in-publish/download/in-publish-2.0.1.tgz?cache=0&sync_timestamp=1618847140402&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fin-publish%2Fdownload%2Fin-publish-2.0.1.tgz",
+      "integrity": "sha1-lIsaU1yAMFYc6lIvc/ePS+NX4Aw=",
       "dev": true
     },
     "indent-string": {
       "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "resolved": "https://registry.nlark.com/indent-string/download/indent-string-2.1.0.tgz?cache=0&sync_timestamp=1618847038277&other_urls=https%3A%2F%2Fregistry.nlark.com%2Findent-string%2Fdownload%2Findent-string-2.1.0.tgz",
       "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
       "dev": true,
       "requires": {
@@ -6557,8 +6557,8 @@
     },
     "is-finite": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
-      "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+      "resolved": "https://registry.npm.taobao.org/is-finite/download/is-finite-1.1.0.tgz?cache=0&sync_timestamp=1617779324274&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-finite%2Fdownload%2Fis-finite-1.1.0.tgz",
+      "integrity": "sha1-kEE1x3+0LAZB1qobzbxNqo2ggvM=",
       "dev": true
     },
     "is-fullwidth-code-point": {
@@ -6705,7 +6705,7 @@
     },
     "is-utf8": {
       "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/is-utf8/download/is-utf8-0.2.1.tgz",
       "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
       "dev": true
     },
@@ -6930,7 +6930,7 @@
     },
     "load-json-file": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz",
       "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
       "dev": true,
       "requires": {
@@ -6943,7 +6943,7 @@
       "dependencies": {
         "parse-json": {
           "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1610966642419&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz",
           "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
           "dev": true,
           "requires": {
@@ -6952,7 +6952,7 @@
         },
         "pify": {
           "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz?cache=0&sync_timestamp=1593529716831&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-2.3.0.tgz",
           "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
           "dev": true
         }
@@ -7120,7 +7120,7 @@
     },
     "loud-rejection": {
       "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+      "resolved": "https://registry.npm.taobao.org/loud-rejection/download/loud-rejection-1.6.0.tgz",
       "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
       "dev": true,
       "requires": {
@@ -7168,7 +7168,7 @@
     },
     "map-obj": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/map-obj/download/map-obj-1.0.1.tgz",
       "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
       "dev": true
     },
@@ -7216,7 +7216,7 @@
     },
     "meow": {
       "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+      "resolved": "https://registry.nlark.com/meow/download/meow-3.7.0.tgz?cache=0&sync_timestamp=1626387893385&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmeow%2Fdownload%2Fmeow-3.7.0.tgz",
       "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
       "dev": true,
       "requires": {
@@ -7471,6 +7471,11 @@
         "commander": "*"
       }
     },
+    "moment": {
+      "version": "2.29.1",
+      "resolved": "https://registry.nlark.com/moment/download/moment-2.29.1.tgz",
+      "integrity": "sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M="
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -7665,8 +7670,8 @@
     },
     "node-sass": {
       "version": "4.14.1",
-      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
-      "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==",
+      "resolved": "https://registry.nlark.com/node-sass/download/node-sass-4.14.1.tgz",
+      "integrity": "sha1-mch+wu+3BH7WOPtMnbfzpC4iF7U=",
       "dev": true,
       "requires": {
         "async-foreach": "^0.1.3",
@@ -7690,13 +7695,13 @@
       "dependencies": {
         "ansi-styles": {
           "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-2.2.1.tgz?cache=0&sync_timestamp=1618995625950&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-2.2.1.tgz",
           "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
           "dev": true
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "https://registry.nlark.com/chalk/download/chalk-1.1.3.tgz?cache=0&sync_timestamp=1618995297666&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -7709,7 +7714,7 @@
         },
         "cross-spawn": {
           "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+          "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-3.0.1.tgz",
           "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
           "dev": true,
           "requires": {
@@ -7719,8 +7724,8 @@
         },
         "lru-cache": {
           "version": "4.1.5",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-          "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+          "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.5.tgz",
+          "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=",
           "dev": true,
           "requires": {
             "pseudomap": "^1.0.2",
@@ -7729,8 +7734,8 @@
         },
         "node-gyp": {
           "version": "3.8.0",
-          "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
-          "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+          "resolved": "https://registry.nlark.com/node-gyp/download/node-gyp-3.8.0.tgz?cache=0&sync_timestamp=1622168102506&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnode-gyp%2Fdownload%2Fnode-gyp-3.8.0.tgz",
+          "integrity": "sha1-VAMEJhwzDoDQ1e3OJTpoyzlkIYw=",
           "dev": true,
           "requires": {
             "fstream": "^1.0.0",
@@ -7749,7 +7754,7 @@
         },
         "nopt": {
           "version": "3.0.6",
-          "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+          "resolved": "https://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz?cache=0&sync_timestamp=1597649942437&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnopt%2Fdownload%2Fnopt-3.0.6.tgz",
           "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
           "dev": true,
           "requires": {
@@ -7758,20 +7763,20 @@
         },
         "semver": {
           "version": "5.3.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.3.0.tgz?cache=0&sync_timestamp=1616463641178&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.3.0.tgz",
           "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
           "dev": true
         },
         "supports-color": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "resolved": "https://registry.nlark.com/supports-color/download/supports-color-2.0.0.tgz?cache=0&sync_timestamp=1626703342506&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-2.0.0.tgz",
           "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
           "dev": true
         },
         "tar": {
           "version": "2.2.2",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
-          "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+          "resolved": "https://registry.nlark.com/tar/download/tar-2.2.2.tgz?cache=0&sync_timestamp=1627081165740&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftar%2Fdownload%2Ftar-2.2.2.tgz",
+          "integrity": "sha1-DKiEhWLHKZuLRG/2pNYM27I+3EA=",
           "dev": true,
           "requires": {
             "block-stream": "*",
@@ -7781,7 +7786,7 @@
         },
         "yallist": {
           "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+          "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
           "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
           "dev": true
         }
@@ -9403,7 +9408,7 @@
     },
     "read-pkg-up": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-1.0.1.tgz",
       "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
       "dev": true,
       "requires": {
@@ -9413,7 +9418,7 @@
       "dependencies": {
         "find-up": {
           "version": "1.1.2",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+          "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz",
           "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
           "dev": true,
           "requires": {
@@ -9423,7 +9428,7 @@
         },
         "path-exists": {
           "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz",
           "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
           "dev": true,
           "requires": {
@@ -9432,7 +9437,7 @@
         },
         "path-type": {
           "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-1.1.0.tgz?cache=0&sync_timestamp=1611752058913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-type%2Fdownload%2Fpath-type-1.1.0.tgz",
           "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
           "dev": true,
           "requires": {
@@ -9443,13 +9448,13 @@
         },
         "pify": {
           "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz?cache=0&sync_timestamp=1593529716831&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-2.3.0.tgz",
           "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
           "dev": true
         },
         "read-pkg": {
           "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz?cache=0&sync_timestamp=1616914988083&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg%2Fdownload%2Fread-pkg-1.1.0.tgz",
           "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
           "dev": true,
           "requires": {
@@ -9486,7 +9491,7 @@
     },
     "redent": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+      "resolved": "https://registry.nlark.com/redent/download/redent-1.0.0.tgz",
       "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
       "dev": true,
       "requires": {
@@ -9496,7 +9501,7 @@
       "dependencies": {
         "strip-indent": {
           "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+          "resolved": "https://registry.nlark.com/strip-indent/download/strip-indent-1.0.1.tgz?cache=0&sync_timestamp=1620053310624&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-indent%2Fdownload%2Fstrip-indent-1.0.1.tgz",
           "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
           "dev": true,
           "requires": {
@@ -9695,7 +9700,7 @@
     },
     "repeating": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+      "resolved": "https://registry.nlark.com/repeating/download/repeating-2.0.1.tgz",
       "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
       "dev": true,
       "requires": {
@@ -9935,8 +9940,8 @@
     },
     "sass-graph": {
       "version": "2.2.5",
-      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz",
-      "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==",
+      "resolved": "https://registry.npm.taobao.org/sass-graph/download/sass-graph-2.2.5.tgz",
+      "integrity": "sha1-qYHIdEa4MZ2W3OBnHkh4eb0kwug=",
       "dev": true,
       "requires": {
         "glob": "^7.0.0",
@@ -9947,20 +9952,20 @@
       "dependencies": {
         "ansi-regex": {
           "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz",
+          "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
           "dev": true
         },
         "emoji-regex": {
           "version": "7.0.3",
-          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-          "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+          "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz",
+          "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=",
           "dev": true
         },
         "find-up": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz",
+          "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=",
           "dev": true,
           "requires": {
             "locate-path": "^3.0.0"
@@ -9968,14 +9973,14 @@
         },
         "is-fullwidth-code-point": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz?cache=0&sync_timestamp=1618552489864&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-fullwidth-code-point%2Fdownload%2Fis-fullwidth-code-point-2.0.0.tgz",
           "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
           "dev": true
         },
         "locate-path": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz",
+          "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=",
           "dev": true,
           "requires": {
             "p-locate": "^3.0.0",
@@ -9984,8 +9989,8 @@
         },
         "p-limit": {
           "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1606288352885&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz",
+          "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=",
           "dev": true,
           "requires": {
             "p-try": "^2.0.0"
@@ -9993,8 +9998,8 @@
         },
         "p-locate": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz",
+          "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=",
           "dev": true,
           "requires": {
             "p-limit": "^2.0.0"
@@ -10002,14 +10007,14 @@
         },
         "p-try": {
           "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz",
+          "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=",
           "dev": true
         },
         "string-width": {
           "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-          "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+          "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz",
+          "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=",
           "dev": true,
           "requires": {
             "emoji-regex": "^7.0.1",
@@ -10019,8 +10024,8 @@
         },
         "strip-ansi": {
           "version": "5.2.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1618553299612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz",
+          "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
           "dev": true,
           "requires": {
             "ansi-regex": "^4.1.0"
@@ -10028,8 +10033,8 @@
         },
         "yargs": {
           "version": "13.3.2",
-          "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-          "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+          "resolved": "https://registry.nlark.com/yargs/download/yargs-13.3.2.tgz?cache=0&sync_timestamp=1626358476652&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fyargs%2Fdownload%2Fyargs-13.3.2.tgz",
+          "integrity": "sha1-rX/+/sGqWVZayRX4Lcyzipwxot0=",
           "dev": true,
           "requires": {
             "cliui": "^5.0.0",
@@ -10046,8 +10051,8 @@
         },
         "yargs-parser": {
           "version": "13.1.2",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-          "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+          "resolved": "https://registry.nlark.com/yargs-parser/download/yargs-parser-13.1.2.tgz",
+          "integrity": "sha1-Ew8JcC667vJlDVTObj5XBvek+zg=",
           "dev": true,
           "requires": {
             "camelcase": "^5.0.0",
@@ -10104,7 +10109,7 @@
     },
     "scss-tokenizer": {
       "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+      "resolved": "https://registry.npm.taobao.org/scss-tokenizer/download/scss-tokenizer-0.2.3.tgz",
       "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
       "dev": true,
       "requires": {
@@ -10114,7 +10119,7 @@
       "dependencies": {
         "source-map": {
           "version": "0.4.4",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+          "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz",
           "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
           "dev": true,
           "requires": {
@@ -10800,8 +10805,8 @@
     },
     "stdout-stream": {
       "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
-      "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
+      "resolved": "https://registry.npm.taobao.org/stdout-stream/download/stdout-stream-1.4.1.tgz",
+      "integrity": "sha1-WsF0zdXNcmEEqgwLK9g4FdjVNd4=",
       "dev": true,
       "requires": {
         "readable-stream": "^2.0.1"
@@ -10928,7 +10933,7 @@
     },
     "strip-bom": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "resolved": "https://registry.nlark.com/strip-bom/download/strip-bom-2.0.0.tgz",
       "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
       "dev": true,
       "requires": {
@@ -11432,14 +11437,14 @@
     },
     "trim-newlines": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+      "resolved": "https://registry.nlark.com/trim-newlines/download/trim-newlines-1.0.0.tgz?cache=0&sync_timestamp=1623341669040&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftrim-newlines%2Fdownload%2Ftrim-newlines-1.0.0.tgz",
       "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
       "dev": true
     },
     "true-case-path": {
       "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
-      "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
+      "resolved": "https://registry.nlark.com/true-case-path/download/true-case-path-1.0.3.tgz",
+      "integrity": "sha1-+BO1qMhrQNpZYGcisUTjIleZ9H0=",
       "dev": true,
       "requires": {
         "glob": "^7.1.2"
@@ -11938,6 +11943,11 @@
       "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
       "dev": true
     },
+    "vue2-countdown": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npm.taobao.org/vue2-countdown/download/vue2-countdown-1.0.8.tgz",
+      "integrity": "sha1-4PILava62zPPmcjMPfUdLHfy7zU="
+    },
     "vuex": {
       "version": "3.6.2",
       "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
diff --git a/package.json b/package.json
index e30a89c..4662c34 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "js-cookie": "^2.2.0",
     "js-md5": "^0.7.3",
     "mockjs": "^1.0.1-beta3",
+    "moment": "^2.29.1",
     "node-gyp": "^5.0.6",
     "nprogress": "^0.2.0",
     "portfinder": "^1.0.23",
@@ -29,6 +30,7 @@
     "vue-axios": "^2.1.2",
     "vue-i18n": "^8.7.0",
     "vue-router": "^3.0.1",
+    "vue2-countdown": "^1.0.8",
     "vuex": "^3.1.1"
   },
   "devDependencies": {
@@ -36,7 +38,7 @@
     "@vue/cli-plugin-eslint": "^3.1.5",
     "@vue/cli-service": "^3.1.4",
     "chai": "^4.1.2",
-    "node-sass": "^4.12.0",
+    "node-sass": "^4.14.1",
     "sass-loader": "^7.0.1",
     "vue-template-compiler": "^2.5.17",
     "webpack-bundle-analyzer": "^3.0.3"
diff --git a/src/api/applyexam/applyexam.js b/src/api/applyexam/applyexam.js
new file mode 100644
index 0000000..14e597d
--- /dev/null
+++ b/src/api/applyexam/applyexam.js
@@ -0,0 +1,120 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params, deptId) => {
+  return request({
+    url: '/api/blade-user/page',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+      deptId,
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/blade-user/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/blade-user/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/blade-user/update',
+    method: 'post',
+    data: row
+  })
+}
+
+export const updatePlatform = (userId, userType, userExt) => {
+  return request({
+    url: '/api/blade-user/update-platform',
+    method: 'post',
+    params: {
+      userId,
+      userType,
+      userExt,
+    }
+  })
+}
+
+export const getUser = (id) => {
+  return request({
+    url: '/api/blade-user/detail',
+    method: 'get',
+    params: {
+      id,
+    }
+  })
+}
+
+export const getUserPlatform = (id) => {
+  return request({
+    url: '/api/blade-user/platform-detail',
+    method: 'get',
+    params: {
+      id,
+    }
+  })
+}
+
+export const getUserInfo = () => {
+  return request({
+    url: '/api/blade-user/info',
+    method: 'get',
+  })
+}
+
+export const resetPassword = (userIds) => {
+  return request({
+    url: '/api/blade-user/reset-password',
+    method: 'post',
+    params: {
+      userIds,
+    }
+  })
+}
+
+export const updatePassword = (oldPassword, newPassword, newPassword1) => {
+  return request({
+    url: '/api/blade-user/update-password',
+    method: 'post',
+    params: {
+      oldPassword,
+      newPassword,
+      newPassword1,
+    }
+  })
+}
+
+export const updateInfo = (row) => {
+  return request({
+    url: '/api/blade-user/update-info',
+    method: 'post',
+    data: row
+  })
+}
+
+export const grant = (userIds, roleIds) => {
+  return request({
+    url: '/api/blade-user/grant',
+    method: 'post',
+    params: {
+      userIds,
+      roleIds,
+    }
+  })
+}
diff --git a/src/api/exam/answer.js b/src/api/exam/answer.js
new file mode 100644
index 0000000..42de680
--- /dev/null
+++ b/src/api/exam/answer.js
@@ -0,0 +1,124 @@
+import request from '@/router/axios'
+
+const baseAnswerUrl = '/api/exam/v1/answer/'
+
+export function fetchAnswerList(query) {
+  return request({
+    url: baseAnswerUrl + 'answerList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getAnswer(id) {
+  return request({
+    url: baseAnswerUrl + id,
+    method: 'get'
+  })
+}
+
+export function getAnswerInfo(id, query) {
+  return request({
+    url: baseAnswerUrl + id + '/info',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getAnswerListInfo(id, query) {
+  return request({
+    url: baseAnswerUrl + 'record/' + id + '/answerListInfo',
+    method: 'get',
+    params: query
+  })
+}
+
+export function addAnswer(obj) {
+  return request({
+    url: baseAnswerUrl,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function putAnswer(obj) {
+  return request({
+    url: baseAnswerUrl,
+    method: 'put',
+    data: obj
+  })
+}
+
+export function delAnswer(id) {
+  return request({
+    url: baseAnswerUrl + id,
+    method: 'delete'
+  })
+}
+
+export function save(obj) {
+  return request({
+    url: baseAnswerUrl + 'save',
+    method: 'post',
+    data: obj
+  })
+}
+
+export const saveAndNext = (params) => {
+  return request({
+    url: '/api/examScore/saveExamScore',
+    method: 'post',
+    data: {
+      // "allGrade": 0,
+      "allScore": 200,
+      "candidateNo": params.securityId + '  ',
+      "company": params.company,
+      "examName": params.examName,
+      "examResultVOS": params.examResultVOS,
+      "examTime": params.examTime,
+      "examType": Number(params.examType),
+      "learnGrade": 0,
+      "papersId": Number(params.papersId),
+      "securityName": params.securityName
+    }
+  })
+}
+
+export function anonymousUserSaveAndNext(obj, nextType, nextSubjectId, nextSubjectType) {
+  let url = baseAnswerUrl + 'anonymousUser/saveAndNext?nextType=' + nextType
+  if (nextSubjectId !== undefined) {
+    url += '&nextSubjectId=' + nextSubjectId
+  }
+  if (nextSubjectType !== undefined) {
+    url += '&nextSubjectType=' + nextSubjectType
+  }
+  return request({
+    url: url,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function submit(obj) {
+  return request({
+    url: baseAnswerUrl + 'submit',
+    method: 'post',
+    data: obj
+  })
+}
+
+export function anonymousUserSubmit(obj) {
+  return request({
+    url: baseAnswerUrl + 'anonymousUser/submit',
+    method: 'post',
+    data: obj
+  })
+}
+
+export function anonymousUserSubmitAll(obj, examinationId, identifier) {
+  return request({
+    url: baseAnswerUrl + 'anonymousUser/submitAll/' + examinationId + '?identifier=' + identifier,
+    method: 'post',
+    data: obj
+  })
+}
diff --git a/src/api/exam/course.js b/src/api/exam/course.js
new file mode 100644
index 0000000..612c969
--- /dev/null
+++ b/src/api/exam/course.js
@@ -0,0 +1,57 @@
+import request from '@/router/axios'
+
+const baseCourseUrl = '/api/exam/v1/course/'
+
+export function courseList (query) {
+  return request({
+    url: baseCourseUrl + 'courseList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchCourseList (query) {
+  return request({
+    url: baseCourseUrl + 'courseList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getObj (id) {
+  return request({
+    url: baseCourseUrl + id,
+    method: 'get'
+  })
+}
+
+export function addObj (obj) {
+  return request({
+    url: baseCourseUrl,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function putObj (obj) {
+  return request({
+    url: baseCourseUrl,
+    method: 'put',
+    data: obj
+  })
+}
+
+export function delObj (id) {
+  return request({
+    url: baseCourseUrl + id,
+    method: 'delete'
+  })
+}
+
+export function delAllObj (obj) {
+  return request({
+    url: baseCourseUrl + 'deleteAll',
+    method: 'post',
+    data: obj
+  })
+}
diff --git a/src/api/exam/exam.js b/src/api/exam/exam.js
new file mode 100644
index 0000000..b87bfe5
--- /dev/null
+++ b/src/api/exam/exam.js
@@ -0,0 +1,84 @@
+import request from '@/router/axios'
+
+const baseExaminationUrl = '/api/exam/v1/examination/'
+
+export function fetchList (query) {
+  return request({
+    url: baseExaminationUrl + 'examinationList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function fetchAllSubjectList (query) {
+  return request({
+    url: baseExaminationUrl + 'anonymousUser/allSubjectList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getObj (id, query) {
+  return request({
+    url: baseExaminationUrl + id,
+    method: 'get',
+    params: query
+  })
+}
+
+export function anonymousUserGetObj (id, query) {
+  return request({
+    url: baseExaminationUrl + 'anonymousUser/' + id,
+    method: 'get',
+    params: query
+  })
+}
+
+export const getSubjectIds = (param) => {
+  return request({
+    url: '/api/exampaper/queryPagerSubject/',
+    method: 'get',
+    params: {
+      ...param
+    }
+  })
+}
+
+export function anonymousUserGetSubjectIds (id, query) {
+  return request({
+    url: baseExaminationUrl + 'anonymousUser/' + id + '/subjectIds',
+    method: 'get',
+    params: query
+  })
+}
+
+export function addObj (obj) {
+  return request({
+    url: baseExaminationUrl,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function putObj (obj) {
+  return request({
+    url: baseExaminationUrl,
+    method: 'put',
+    data: obj
+  })
+}
+
+export function delObj (id) {
+  return request({
+    url: baseExaminationUrl + id,
+    method: 'delete'
+  })
+}
+
+export function delAllObj (obj) {
+  return request({
+    url: baseExaminationUrl + 'deleteAll',
+    method: 'post',
+    data: obj
+  })
+}
diff --git a/src/api/exam/examRecord.js b/src/api/exam/examRecord.js
new file mode 100644
index 0000000..b1e407b
--- /dev/null
+++ b/src/api/exam/examRecord.js
@@ -0,0 +1,58 @@
+import request from '@/router/axios'
+
+const baseExamRecordUrl = '/api/exam/v1/examRecord/'
+
+export function fetchList (query) {
+  return request({
+    url: baseExamRecordUrl + 'examRecordList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getObj (id, query) {
+  return request({
+    url: baseExamRecordUrl + id,
+    method: 'get',
+    params: query
+  })
+}
+
+export function addObj (obj) {
+  return request({
+    url: baseExamRecordUrl,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function start (obj) {
+  return request({
+    url: baseExamRecordUrl + 'start',
+    method: 'post',
+    data: obj
+  })
+}
+
+export function anonymousUserStart (obj) {
+  return request({
+    url: baseExamRecordUrl + 'anonymousUser/start',
+    method: 'post',
+    params: obj
+  })
+}
+
+export function getCurrentTime () {
+  return request({
+    url: '/api/exampaper/getdate',
+    method: 'get'
+  })
+}
+
+// 查询成绩详情
+export function examRecordDetails (id) {
+  return request({
+    url: baseExamRecordUrl + id + '/details',
+    method: 'get'
+  })
+}
diff --git a/src/api/exam/knowledge.js b/src/api/exam/knowledge.js
new file mode 100644
index 0000000..673b9ad
--- /dev/null
+++ b/src/api/exam/knowledge.js
@@ -0,0 +1,18 @@
+import request from '@/router/axios'
+
+const baseKnowledgeUrl = '/api/exam/v1/knowledge/'
+
+export function fetchKnowledgeList (query) {
+  return request({
+    url: baseKnowledgeUrl + 'knowledgeList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getObj (id) {
+  return request({
+    url: baseKnowledgeUrl + id,
+    method: 'get'
+  })
+}
diff --git a/src/api/exam/subject.js b/src/api/exam/subject.js
new file mode 100644
index 0000000..3eefe79
--- /dev/null
+++ b/src/api/exam/subject.js
@@ -0,0 +1,74 @@
+import request from '@/router/axios'
+
+const baseSubjectUrl = '/api/exam/v1/subject/'
+
+export function subjectList () {
+  return request({
+    url: baseSubjectUrl + 'subjectList',
+    method: 'get'
+  })
+}
+
+export function fetchSubjectList (query) {
+  return request({
+    url: baseSubjectUrl + 'subjectList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getObj (id, query) {
+  return request({
+    url: baseSubjectUrl + id,
+    method: 'get',
+    params: query
+  })
+}
+
+export function addSubject (obj) {
+  return request({
+    url: baseSubjectUrl,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function putSubject (obj) {
+  return request({
+    url: baseSubjectUrl,
+    method: 'put',
+    data: obj
+  })
+}
+
+export function delSubject (id) {
+  return request({
+    url: baseSubjectUrl + id,
+    method: 'delete'
+  })
+}
+
+export function delAllSubject (obj) {
+  return request({
+    url: baseSubjectUrl + 'deleteAll',
+    method: 'post',
+    data: obj
+  })
+}
+
+export function getSubjectAnswer (obj) {
+  return request({
+    url: '/api/examSubjectChoices/details',
+    method: 'get',
+    params: obj
+  })
+}
+
+
+export function anonymousUserGetSubjectAnswer (obj) {
+  return request({
+    url: baseSubjectUrl + 'anonymousUser/subjectAnswer',
+    method: 'get',
+    params: obj
+  })
+}
diff --git a/src/api/exam/subjectCategory.js b/src/api/exam/subjectCategory.js
new file mode 100644
index 0000000..0c095e1
--- /dev/null
+++ b/src/api/exam/subjectCategory.js
@@ -0,0 +1,41 @@
+import request from '@/router/axios'
+
+const baseSubjectCategoryUrl = '/api/exam/v1/subjectCategory/'
+
+export function fetchTree (query) {
+  return request({
+    url: baseSubjectCategoryUrl + 'categories',
+    method: 'get',
+    params: query
+  })
+}
+
+export function addObj (obj) {
+  return request({
+    url: baseSubjectCategoryUrl,
+    method: 'post',
+    data: obj
+  })
+}
+
+export function getObj (id) {
+  return request({
+    url: baseSubjectCategoryUrl + id,
+    method: 'get'
+  })
+}
+
+export function delObj (id) {
+  return request({
+    url: baseSubjectCategoryUrl + id,
+    method: 'delete'
+  })
+}
+
+export function putObj (obj) {
+  return request({
+    url: baseSubjectCategoryUrl,
+    method: 'put',
+    data: obj
+  })
+}
diff --git a/src/api/examapi/applyexam.js b/src/api/examapi/applyexam.js
new file mode 100644
index 0000000..08c81f2
--- /dev/null
+++ b/src/api/examapi/applyexam.js
@@ -0,0 +1,47 @@
+import request from '@/router/axios';
+
+
+export const getApplyList = (current, size, params) => {
+  return request({
+    url: '/api/apply/page',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size
+    }
+  })
+}
+
+export const addApply = (row) => {
+  return request({
+    url: '/api/apply/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/apply/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+
+
+
+export const getMenu = (id) => {
+  return request({
+    url: '/api/apply/detail',
+    method: 'get',
+    params: {
+      id,
+    }
+  })
+}
diff --git a/src/api/examapi/examSubjects.js b/src/api/examapi/examSubjects.js
new file mode 100644
index 0000000..36f863b
--- /dev/null
+++ b/src/api/examapi/examSubjects.js
@@ -0,0 +1,37 @@
+import request from '@/router/axios';
+
+export const getPaperList = (current, size, params) => {
+  return request({
+    url: '/api/examSubjectChoices/getEexPaperChoices',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size
+    }
+  })
+}
+
+
+export const updatePaper = (row) => {
+  return request({
+    url: '/api/examSubjectChoices/updateChoicesValue',
+    method: 'post',
+    params: {
+      ...row
+    }
+  })
+}
+
+
+
+
+export const remove = (params) => {
+  return request({
+    url: '/api/exampaper/UnbindSubject',
+    method: 'get',
+    params: {
+      ...params
+    }
+  })
+}
diff --git a/src/api/examapi/examination.js b/src/api/examapi/examination.js
new file mode 100644
index 0000000..c1fe666
--- /dev/null
+++ b/src/api/examapi/examination.js
@@ -0,0 +1,39 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/exampaper/page',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/exampaper/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/exampaper/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/exampaper/update',
+    method: 'post',
+    data: row
+  })
+}
diff --git a/src/api/examapi/performance.js b/src/api/examapi/performance.js
new file mode 100644
index 0000000..ba130f1
--- /dev/null
+++ b/src/api/examapi/performance.js
@@ -0,0 +1,21 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/examScore/page',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size
+    }
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/examScore/updateExamScore',
+    method: 'post',
+    data: row
+  })
+}
diff --git a/src/api/examapi/subject.js b/src/api/examapi/subject.js
new file mode 100644
index 0000000..29867db
--- /dev/null
+++ b/src/api/examapi/subject.js
@@ -0,0 +1,23 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/examSubjectChoices/page',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/examSubjectChoices/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
diff --git a/src/api/trainExam/trainExam.js b/src/api/trainExam/trainExam.js
new file mode 100644
index 0000000..d9455ae
--- /dev/null
+++ b/src/api/trainExam/trainExam.js
@@ -0,0 +1,62 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+    return request({
+        url: '/api/trainExam/page',
+        method: 'get',
+        params: {
+            ...params,
+            current,
+            size
+        }
+    })
+}
+
+export const remove = (ids) => {
+    return request({
+        url: '/api/trainExam/remove',
+        method: 'post',
+        params: {
+            ids,
+        }
+    })
+}
+
+export const add = (row) => {
+    return request({
+        url: '/api/trainExam/submit',
+        method: 'post',
+        data: row
+    })
+}
+
+export const update = (row) => {
+    return request({
+        url: '/api/trainExam/update',
+        method: 'post',
+        data: row
+    })
+}
+
+
+export const updateAudit = (row) => {
+    return request({
+        url: '/api/trainExam/update-audit',
+        method: 'post',
+        data: row
+    })
+}
+
+
+
+
+
+export const getDetail = (id) => {
+    return request({
+        url: '/api/trainExam/detail',
+        method: 'get',
+        params: {
+            id,
+        }
+    })
+}
\ No newline at end of file
diff --git a/src/assets/css/_fonts.scss b/src/assets/css/_fonts.scss
new file mode 100644
index 0000000..980c47f
--- /dev/null
+++ b/src/assets/css/_fonts.scss
@@ -0,0 +1,3 @@
+// Fonts
+$opensans-font: 'Open Sans', sans-serif;
+$raleway-font: 'Raleway', sans-serif;
diff --git a/src/assets/css/_responsive.scss b/src/assets/css/_responsive.scss
new file mode 100644
index 0000000..6cce9d1
--- /dev/null
+++ b/src/assets/css/_responsive.scss
@@ -0,0 +1,11 @@
+$breakpoint-xl: 'only screen and (min-width:1200px)';
+
+$breakpoint-lg: 'only screen and (min-width:992px) and (max-width:1199px)';
+
+$breakpoint-md: 'only screen and (min-width:768px) and (max-width:991px)';
+
+$breakpoint-sm: 'only screen and (min-width:576px) and (max-width:767px)';
+
+$breakpoint-xs: 'only screen and (max-width:767px)';
+
+$breakpoint-xs-landscape: 'only screen and (min-width:480px) and (max-width:767px)';
diff --git a/src/assets/css/_theme_color.scss b/src/assets/css/_theme_color.scss
new file mode 100644
index 0000000..3dae507
--- /dev/null
+++ b/src/assets/css/_theme_color.scss
@@ -0,0 +1,29 @@
+// Heading Color
+$heading-color: rgba(0, 0, 0, 0.8);
+
+// Text Color
+$text-color: #5a5a5a;
+
+// Default Background
+$bg-default: #3762f0;
+
+// Gray Background
+$bg-gray: #f7f7f7;
+
+// White Color
+$white-color: #ffffff;
+
+// Dark Color
+$dark-color: #1b1b1b;
+
+// Border Color
+$border-color: #ebebeb;
+
+// Hover Color
+$hover-color: #2c56df;
+
+// Footer Color
+$footer-color: #252525;
+
+// Border Color
+$border-color: #ebebeb;
diff --git a/src/assets/css/mixin.scss b/src/assets/css/mixin.scss
new file mode 100644
index 0000000..1593d5a
--- /dev/null
+++ b/src/assets/css/mixin.scss
@@ -0,0 +1,79 @@
+@mixin wh($w,$h:$w) {
+  width: $w;
+  height: $h;
+}
+
+@mixin trans-duration($time) {
+  -webkit-transition-duration: $time;
+  transition-duration: $time;
+}
+
+@mixin transition($value) {
+  -webkit-transition: $value;
+  transition: $value;
+}
+
+@mixin transform($value) {
+  -webkit-transform: $value;
+  transform: $value;
+}
+
+@mixin animation($value) {
+  -webkit-animation: $value;
+  animation: $value;
+}
+
+@mixin flex-direction($value) {
+  -webkit-box-orient: horizontal;
+  -webkit-box-direction: reverse;
+  -ms-flex-direction: $value;
+  flex-direction: $value;
+}
+
+@mixin align-items($value) {
+  -webkit-box-align: $value;
+  -ms-flex-align: $value;
+  -ms-grid-row-align: $value;
+  align-items: $value;
+}
+
+@mixin display-flex($value) {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: $value;
+}
+
+@mixin justify-content-between {
+  -webkit-box-pack: justify;
+  -ms-flex-pack: justify;
+  justify-content: space-between;
+}
+
+@mixin justify-content($value) {
+  -webkit-box-pack: center;
+  -ms-flex-pack: center;
+  justify-content: center;
+}
+
+@mixin justify-content-end {
+  -webkit-box-pack: end;
+  -ms-flex-pack: end;
+  justify-content: flex-end;
+}
+
+@mixin flex($value) {
+  -webkit-box-flex: 0;
+  -ms-flex: $value;
+  flex: $value;
+}
+
+@mixin flex-wrap($value) {
+  -ms-flex-wrap: $value;
+  flex-wrap: $value;
+}
+
+@mixin bg-gradients {
+  background: #0d104d;
+  background: -webkit-linear-gradient(to right, #0d104d, #28408b);
+  background: linear-gradient(to right, #0d104d, #28408b);
+}
diff --git a/src/assets/css/style.scss b/src/assets/css/style.scss
new file mode 100644
index 0000000..f6e8340
--- /dev/null
+++ b/src/assets/css/style.scss
@@ -0,0 +1,1084 @@
+@import 'theme_color';
+@import '_fonts';
+@import 'mixin';
+@import 'responsive';
+@import 'transition';
+
+* {
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  font-family: $opensans-font;
+  font-size: 14px;
+  font-weight: 400;
+  margin: 0;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  color: $heading-color;
+  line-height: 1.3;
+  font-weight: 700;
+
+}
+
+p {
+  font-family: $raleway-font;
+  color: $text-color;
+  font-size: 14px;
+  line-height: 1.8;
+  font-weight: 400;
+}
+
+a,
+a:hover,
+a:focus {
+  @include trans-duration(500ms);
+  text-decoration: none;
+  outline: 0 solid transparent;
+  color: $heading-color;
+  font-weight: 600;
+  font-size: 14px;
+}
+
+ul,
+ol {
+  margin: 0;
+  li {
+    list-style: none;
+  }
+}
+
+img {
+  height: auto;
+  max-width: 100%;
+}
+
+.padding-80-0 {
+  padding-top: 80px;
+  padding-bottom: 0;
+}
+
+.mb-80 {
+  margin-bottom: 80px;
+}
+
+.mb-12 {
+  margin-bottom: 12px;
+}
+
+.mr-100 {
+  margin-right: 100px;
+}
+
+.ml-100 {
+  margin-left: 100px;
+}
+
+.padding-80 {
+  padding-top: 80px;
+  padding-bottom: 80px;
+}
+
+.mb-30 {
+  margin-bottom: 30px;
+}
+.w-100 {
+  width: 100%;
+}
+.justify-content-center {
+  @include justify-content(center);
+}
+
+.align-items-center {
+  @include align-items(center)
+}
+
+.d-flex {
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.text-center {
+  text-align: center;
+}
+
+.fade-enter-active, .fade-leave-active {
+  transition: opacity .5s;
+}
+.fade-enter, .fade-leave-to {
+  opacity: 0;
+}
+
+.justify-content-between {
+  @include justify-content-between
+}
+
+.header-area.vue-fixed-header--isFixed {
+  position: fixed;
+  left: 0;
+  top: 0;
+  width: 100vw;
+}
+
+.header-area {
+  z-index: 1500 !important;
+  background-color: $white-color;
+  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
+  .clever-main-menu {
+    position: relative;
+    width: 100%;
+    height: 70px;
+    .classy-navbar {
+      padding: .5em 2em;
+      display: flex;
+      align-items: center;
+      justify-content: space-between!important;
+      .nav-brand {
+        color: #565656;
+        display: inline-block;
+        margin-right: 30px;
+        font-size: 30px;
+        font-weight: 600;
+      }
+      .nav-brand:focus, .classy-navbar .nav-brand:hover {
+        font-size: 26px;
+        font-weight: 500;
+      }
+    }
+    .classynav {
+      .el-menu--horizontal {
+        border-bottom: none;
+        .el-menu-item {
+          padding: 0 12px;
+          display: block;
+          border-bottom: none;
+        }
+        .el-submenu {
+          .el-submenu__title {
+            border-bottom: none !important;
+          }
+        }
+      }
+    }
+    .classynav ul li a {
+      color: rgba(0, 0, 0, 0.45);
+      font-weight: 600;
+      @media #{$breakpoint-lg} {
+        padding: 0 8px;
+      }
+      &:hover,
+      &:focus {
+        color: $heading-color;
+      }
+    }
+    .classy-nav-container a {
+      @include trans-duration(500ms);
+      color: #232323;
+      display: inline-block;
+      text-decoration: none;
+      outline: 0;
+    }
+    .search-area {
+      position: relative;
+      width: 230px;
+      height: 40px;
+      margin: 0 50px;
+      @media #{$breakpoint-lg} {
+        width: 170px;
+        margin: 0 15px;
+      }
+      @media #{$breakpoint-md} {
+        margin: 15px auto;
+      }
+      @media #{$breakpoint-xs} {
+        margin: 15px auto;
+      }
+      input {
+        width: 100%;
+        height: 40px;
+        border-radius: 6px;
+        border: 1px solid $border-color;
+        padding: 0 15px 0 50px;
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.35);
+        font-weight: 600;
+        @include trans-duration(500ms);
+        &:focus {
+          border: 1px solid rgba(0, 0, 0, 0.5);
+        }
+      }
+    }
+  }
+}
+.classy-nav-container * {
+  box-sizing: border-box;
+}
+
+.classy-navbar-toggler {
+  border: none;
+  background-color: transparent;
+  cursor: pointer;
+  display: none;
+}
+
+@media only screen and (min-width: 992px) and (max-width: 1199px) {
+  .clever-main-menu .classynav ul li a {
+    padding: 0 8px;
+  }
+}
+
+.clever-main-menu .classynav ul li a:hover, .clever-main-menu .classynav ul li a:focus {
+  color: rgba(0, 0, 0, 0.8);
+}
+
+@media only screen and (min-width: 992px) and (max-width: 1199px) {
+  .clever-main-menu .search-area form {
+    width: 170px;
+    margin: 0 15px;
+  }
+}
+
+@media only screen and (min-width: 768px) and (max-width: 991px) {
+  .clever-main-menu .search-area form {
+    margin: 15px auto;
+  }
+}
+
+@media only screen and (max-width: 767px) {
+  .clever-main-menu .search-area form {
+    margin: 15px auto;
+  }
+}
+
+.classycloseIcon, .dd-trigger {
+  position: absolute;
+  display: none;
+}
+
+.breakpoint-off .classynav {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex;
+  -ms-flex-align: center;
+  align-items: center;
+}
+
+.breakpoint-off .classynav, .classy-navbar {
+  -webkit-box-align: center;
+  -ms-grid-row-align: center;
+}
+
+.register-login-area {
+  position: relative;
+  z-index: 1;
+}
+
+.btn:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+
+.register-login-area a {
+  position: relative;
+  display: inline-block;
+  padding: 0 20px;
+  height: 40px;
+  font-weight: 600;
+  text-transform: uppercase;
+  letter-spacing: 1px;
+  font-size: 14px;
+  color: #3762f0;
+  line-height: 40px;
+}
+
+.classy-nav-container a, .classy-nav-container a:focus, .classy-nav-container a:hover {
+  @include trans-duration(500ms);
+  text-decoration: none;
+  outline: 0;
+  font-size: 14px;
+  font-weight: 400;
+}
+
+.btn:not(:disabled):not(.disabled).active, .btn:not(:disabled):not(.disabled):active {
+  background-image: none;
+}
+
+.btn:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+
+.register-login-area a.active, .register-login-area a:hover, .register-login-area a:focus {
+  background-color: #d7e0fc;
+  font-weight: 600;
+  color: #3762f0;
+}
+
+.register-login-area a {
+  position: relative;
+  display: inline-block;
+  padding: 0 20px;
+  height: 40px;
+  font-weight: 600;
+  text-transform: uppercase;
+  letter-spacing: 1px;
+  font-size: 14px;
+  color: #3762f0;
+  line-height: 40px;
+}
+
+.classy-nav-container a, .classy-nav-container a:focus, .classy-nav-container a:hover {
+  @include trans-duration(500ms);
+  text-decoration: none;
+  outline: 0;
+  font-size: 14px;
+  font-weight: 400;
+}
+
+.el-menu-link {
+  color: rgba(0, 0, 0, 0.45)!important;
+  font-size: 14px;
+  padding: 0 20px;
+  cursor: pointer;
+}
+
+/* 首页 */
+.hero-area {
+  position: relative;
+  z-index: 2;
+  width: 100%;
+  height: 325px;
+  align-items: center!important;
+  background-image: url("/static/img/bg-img/bg1.jpg");
+  background-attachment: fixed;
+  background-position: center center;
+  background-size: cover;
+  background-repeat: no-repeat;
+  ::after {
+    background-color: rgba(0, 0, 0, 0.1);
+    position: absolute;
+    z-index: -1;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    content: "";
+  }
+  .hero-content {
+    text-align: center;
+    h2 {
+      font-size: 40px;
+      margin-bottom: 10px;
+      font-weight: 700;
+      color: $white-color;
+    }
+    h4 {
+      font-size: 22px;
+      margin-bottom: 20px;
+      font-weight: 500;
+      color: $white-color;
+    }
+  }
+}
+.btn:not(:disabled):not(.disabled) {
+  cursor: pointer;
+}
+.clever-btn {
+  @include trans-duration(300ms);
+  display: inline-block;
+  min-width: 160px;
+  height: 40px;
+  background-color: #3762f0;
+  font-weight: 600;
+  text-transform: uppercase;
+  letter-spacing: 1px;
+  font-size: 14px;
+  color: $white-color;
+  border: 1px solid transparent;
+  border-radius: 6px;
+  padding: 0 30px;
+  line-height: 40px;
+  text-align: center;
+}
+.single-cool-facts-area {
+  text-align: center;
+  position: relative;
+  z-index: 1;
+  padding: 30px;
+  border: 1px solid #ebebeb;
+  border-radius: 6px;
+  margin-bottom: 80px !important;
+  cursor: pointer;
+}
+.popular-courses-area {
+  position: relative;
+  background-repeat: repeat;
+  background-image: url(/static/img/core-img/texture.png);
+  height: 600px;
+}
+
+.section-heading {
+  position: relative;
+  z-index: 1;
+  margin-bottom: 70px;
+  text-align: center;
+  h3 {
+    font-size: 30px;
+    margin-bottom: 0;
+    @media #{$breakpoint-xs} {
+      font-size: 24px;
+    }
+  }
+  &.text-left {
+    text-align: left !important;
+  }
+  &.white {
+    h3 {
+      color: $white-color;
+    }
+  }
+}
+
+.single-popular-course {
+  position: relative;
+  z-index: 1;
+  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
+  border-radius: 6px;
+  background-color: $white-color;
+  cursor: pointer;
+  img {
+    display: block;
+    width: 100%;
+    border-radius: 6px 6px 0 0;
+  }
+  .course-content {
+    padding: 25px;
+    h4 {
+      margin-bottom: 5px;
+    }
+    .meta {
+      margin-bottom: 15px;
+      span {
+        color: rgba(0, 0, 0, 0.4);
+        font-size: 5px;
+        margin-right: 10px;
+      }
+      a {
+        color: rgba(0, 0, 0, 0.4);
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        margin-right: 10px;
+        &:hover {
+          color: #000;
+        }
+      }
+    }
+    p {
+      margin-bottom: 0;
+    }
+  }
+  .seat-rating-fee {
+    display: inline-flex;
+    width: 100%;
+    height: 40px;
+    background-color: $bg-gray;
+    border-radius: 0 0 6px 6px;
+    .seat-rating {
+      font-size: 12px;
+      color: rgba(0, 0, 0, 0.3);
+      font-weight: 600;
+      height: 100%;
+      align-items: center;
+      div {
+        display: inline-block;
+        padding: 0 20px;
+        border-right: 1px solid $border-color;
+        height: 100%;
+        line-height: 40px;
+      }
+      i {
+        font-size: 13px;
+        color: rgba(0, 0, 0, 0.3);
+      }
+    }
+    .course-fee {
+      a {
+        display: inline-block;
+        width: 70px;
+        height: 40px;
+        border-radius: 0 0 6px 0;
+        background-color: #e3d21b;
+        text-align: center;
+        line-height: 40px;
+        font-size: 12px;
+        font-weight: 700;
+        text-transform: uppercase;
+        color: $white-color;
+        letter-spacing: 0.75px;
+        &.free {
+          background-color: $bg-default;
+        }
+      }
+    }
+  }
+}
+
+.single-blog-area {
+  position: relative;
+  z-index: 1;
+  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
+  border-radius: 6px;
+  cursor: pointer;
+  img {
+    display: block;
+    width: 100%;
+    border-radius: 6px 6px 0 0;
+  }
+  .blog-content {
+    padding: 25px;
+    .blog-headline {
+      display: block;
+      h4 {
+        margin-bottom: 5px;
+        margin-left: -1px;
+        @include trans-duration(500ms);
+        &:hover,
+        &:focus {
+          color: $hover-color;
+        }
+      }
+    }
+    .meta {
+      margin-bottom: 15px;
+      span {
+        color: rgba(0, 0, 0, 0.4);
+        font-size: 5px;
+        margin-right: 10px;
+      }
+      a {
+        color: rgba(0, 0, 0, 0.4);
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        margin-right: 10px;
+        @media #{$breakpoint-xs} {
+          font-size: 12px;
+        }
+        &:hover {
+          color: #000;
+        }
+      }
+    }
+    p {
+      margin-bottom: 0;
+    }
+  }
+}
+
+/* 返回顶部 */
+.go-top-box {
+  background-color: $white-color;
+  position: fixed;
+  right: 50px;
+  bottom: 150px;
+  width: 40px;
+  height: 40px;
+  border-radius: 20px;
+  cursor: pointer;
+  transition: .3s;
+  box-shadow: 0 0 6px rgba(0,0,0,.12);
+  z-index: 5;
+}
+.top-icon {
+  color: #409eff;
+  display: block !important;
+  line-height: 40px !important;
+  text-align: center;
+  font-size: 18px;
+}
+
+.content-container {
+  margin-top: 2rem;
+  margin-left: 100px;
+  margin-right: 100px;
+}
+
+
+.single-course-intro {
+  position: relative;
+  z-index: 1;
+  width: 100%;
+  height: 350px;
+  .single-course-intro-content {
+    width: 425px;
+    height: auto;
+    padding: 30px;
+    background-color: $white-color;
+    border-radius: 6px;
+    @media #{$breakpoint-xs} {
+      width: 280px;
+    }
+    .ratings {
+      margin-bottom: 20px;
+      i {
+        color: #e3d21b;
+        font-size: 13px;
+        padding: 0 3px;
+        display: inline-block;
+      }
+    }
+    h3 {
+      font-size: 30px;
+      margin-bottom: 10px;
+      @media #{$breakpoint-xs} {
+        font-size: 24px;
+      }
+    }
+    .meta {
+      margin-bottom: 30px;
+      span {
+        color: rgba(0, 0, 0, 0.4);
+        font-size: 5px;
+        margin-right: 10px;
+      }
+      a {
+        color: rgba(0, 0, 0, 0.4);
+        display: inline-block;
+        font-size: 14px;
+        font-weight: 400;
+        margin-right: 10px;
+        &:hover {
+          color: #000;
+        }
+      }
+    }
+    .price {
+      font-size: 12px;
+      text-transform: uppercase;
+      color: $bg-default;
+      letter-spacing: 0.75px;
+      font-weight: 700;
+    }
+  }
+}
+
+.clever-description {
+  position: relative;
+  z-index: 1;
+  .about-course {
+    padding: 40px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+    h4 {
+      margin-bottom: 20px;
+      display: block;
+    }
+    p {
+      font-size: 16px;
+      line-height: 1.9;
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+    @media #{$breakpoint-xs} {
+      padding: 30px;
+    }
+  }
+  .all-instructors {
+    padding: 40px 40px 10px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+    @media #{$breakpoint-xs} {
+      padding: 30px 30px 0;
+    }
+    h4 {
+      margin-bottom: 25px;
+      display: block;
+    }
+    .single-instructor {
+      position: relative;
+      z-index: 1;
+      background-color: $bg-gray;
+      border-radius: 6px;
+      .instructor-thumb {
+        @include flex(0 0 80px);
+        width: 80px;
+        max-width: 80px;
+        height: 80px;
+      }
+      .instructor-info {
+        padding-left: 25px;
+        h5 {
+          font-size: 18px;
+          margin-bottom: 5px;
+          @media #{$breakpoint-xs} {
+            font-size: 14px;
+          }
+        }
+        span {
+          font-weight: 400;
+          color: rgba(0, 0, 0, 0.4);
+          font-size: 14px;
+        }
+      }
+    }
+  }
+  .clever-faqs {
+    padding: 40px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+    h4 {
+      margin-bottom: 25px;
+      display: block;
+    }
+    @media #{$breakpoint-xs} {
+      padding: 30px;
+    }
+  }
+}
+
+.about-curriculum {
+  padding: 40px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  h4 {
+    margin-bottom: 20px;
+    display: block;
+  }
+  p {
+    font-size: 16px;
+    line-height: 1.9;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+  @media #{$breakpoint-xs} {
+    padding: 30px;
+  }
+}
+.curriculum-level {
+  padding: 40px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  h4 {
+    margin-bottom: 20px;
+    display: block;
+  }
+  h5 {
+    color: rgba(0, 0, 0, 0.6);
+    font-size: 18px;
+  }
+  .curriculum-list {
+    li {
+      display: block;
+      margin-bottom: 10px;
+      font-family: $raleway-font;
+      font-size: 14px;
+      font-weight: 400;
+      color: rgba(0, 0, 0, 0.5);
+      &:last-child {
+        margin-bottom: 0;
+      }
+      i {
+        color: #e3d21b;
+        margin-right: 5px;
+        display: inline-block;
+      }
+      ul {
+        display: block;
+        margin-top: 10px;
+        padding-left: 25px;
+        li {
+          margin-bottom: 0;
+          @include display-flex(flex);
+          @include justify-content-between;
+          padding: 10px 0;
+          border-bottom: 1px solid $border-color;
+          span {
+            span {
+              text-decoration: underline;
+            }
+          }
+        }
+      }
+    }
+  }
+  @media #{$breakpoint-xs} {
+    padding: 30px;
+  }
+}
+
+.about-review {
+  padding: 40px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  h4 {
+    margin-bottom: 20px;
+    display: block;
+  }
+  p {
+    font-size: 16px;
+    line-height: 1.9;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+  @media #{$breakpoint-xs} {
+    padding: 30px;
+  }
+}
+.clever-ratings {
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  @media #{$breakpoint-xs} {
+    @include flex-wrap(wrap);
+  }
+  .total-ratings {
+    @include flex(0 0 235px);
+    min-width: 235px;
+    width: 235px;
+    border-right: 1px solid $border-color;
+    height: 250px;
+    @media #{$breakpoint-xs} {
+      @include flex(0 0 100%);
+      min-width: 100%;
+      width: 100%;
+      border-right: none;
+      border-bottom: 1px solid $border-color;
+    }
+    h2 {
+      font-size: 60px;
+      margin-bottom: 5px;
+    }
+    .ratings-- {
+      margin-bottom: 10px;
+      i {
+        font-size: 18px;
+        display: inline-block;
+        padding: 0 5px;
+        color: #e3d21b;
+      }
+    }
+    span {
+      font-size: 12px;
+      color: rgba(0, 0, 0, 0.3);
+    }
+  }
+  .rating-viewer {
+    padding: 50px 40px 35px;
+    @media #{$breakpoint-xs} {
+      padding: 40px 30px 25px;
+    }
+    span {
+      color: rgba(0, 0, 0, 0.3);
+      font-size: 12px;
+      text-transform: uppercase;
+      padding-right: 15px;
+      @media #{$breakpoint-lg} {
+        padding-right: 5px;
+        font-size: 11px;
+      }
+      @media #{$breakpoint-xs} {
+        padding-right: 5px;
+        font-size: 11px;
+      }
+    }
+    .progress {
+      width: 300px;
+      margin-right: 15px;
+      height: 10px;
+      border-radius: 0;
+      background-color: #f1f1f1;
+      @media #{$breakpoint-lg} {
+        width: 200px;
+      }
+      @media #{$breakpoint-md} {
+        width: 140px;
+      }
+      @media #{$breakpoint-xs} {
+        width: 140px;
+      }
+      .progress-bar {
+        background-color: #b3b3b3;
+      }
+    }
+  }
+  .single-review {
+    padding: 40px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+    @media #{$breakpoint-xs} {
+      padding: 30px;
+    }
+    p {
+      margin-bottom: 0;
+    }
+    .review-admin {
+      .thumb {
+        @include flex(0 0 40px);
+        max-width: 40px;
+        width: 40px;
+      }
+      .text {
+        padding-left: 15px;
+        h6 {
+          font-size: 14px;
+          margin-bottom: 0;
+        }
+        span {
+          font-size: 12px;
+          color: rgba(0, 0, 0, 0.4);
+        }
+      }
+    }
+    .ratings {
+      i {
+        font-size: 14px;
+        display: inline-block;
+        padding: 0 3px;
+        color: #e3d21b;
+      }
+    }
+  }
+}
+
+.about-members {
+  padding: 40px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  @media #{$breakpoint-xs} {
+    padding: 30px;
+  }
+  h4 {
+    margin-bottom: 20px;
+    display: block;
+  }
+  p {
+    font-size: 16px;
+    line-height: 1.9;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+.all-instructors {
+  padding: 40px 40px 10px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  @media #{$breakpoint-xs} {
+    padding: 30px 30px 0;
+  }
+  h4 {
+    margin-bottom: 25px;
+    display: block;
+  }
+  .single-instructor {
+    position: relative;
+    z-index: 1;
+    background-color: $bg-gray;
+    border-radius: 6px;
+    .instructor-thumb {
+      @include flex(0 0 80px);
+      width: 80px;
+      max-width: 80px;
+      height: 80px;
+    }
+    .instructor-info {
+      padding-left: 25px;
+      h5 {
+        font-size: 18px;
+        margin-bottom: 5px;
+        @media #{$breakpoint-xs} {
+          font-size: 14px;
+        }
+      }
+      span {
+        font-weight: 400;
+        color: rgba(0, 0, 0, 0.4);
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.sidebar-widget {
+  position: relative;
+  z-index: 1;
+  padding: 35px 30px;
+  border: 1px solid $border-color;
+  border-bottom: none;
+  &:last-child {
+    border-bottom: 1px solid $border-color;
+  }
+  h4 {
+    margin-bottom: 20px;
+    font-size: 24px;
+    display: block;
+  }
+  .features-list {
+    li {
+      @include display-flex(flex);
+      @include justify-content-between;
+      margin-bottom: 5px;
+      h6 {
+        color: rgba(0, 0, 0, 0.3);
+        font-size: 14px;
+        @media #{$breakpoint-xs} {
+          font-size: 14px;
+        }
+        i {
+          margin-right: 10px;
+        }
+      }
+    }
+  }
+  .single--courses {
+    position: relative;
+    z-index: 1;
+    margin-bottom: 20px;
+    &:last-child {
+      margin-bottom: 0;
+    }
+    .thumb {
+      @include flex(0 0 80px);
+      width: 80px;
+      max-width: 80px;
+      height: 50px;
+      border-radius: 6px;
+      cursor: pointer;
+      img {
+        border-radius: 6px;
+      }
+    }
+    .content {
+      padding-left: 20px;
+      h5 {
+        font-size: 18px;
+        margin-bottom: 5px;
+        color: rgba(0, 0, 0, 0.35);
+        @media #{$breakpoint-xs} {
+          font-size: 14px;
+        }
+      }
+      h6 {
+        font-size: 12px;
+        color: #e3d21b;
+        margin-bottom: 0;
+      }
+    }
+  }
+}
+
+.single-course-content {
+  .el-tabs__nav {
+    margin-bottom: 20px;
+  }
+  .el-tabs__active-bar {
+    height: 0!important;
+  }
+  .el-tabs__nav-wrap::after {
+    height: 0;
+  }
+  .el-tab-pane {
+    margin: 20px;
+  }
+  .el-tabs__header {
+    margin-left: 30px;
+  }
+}
diff --git a/src/assets/css/subject.scss b/src/assets/css/subject.scss
new file mode 100644
index 0000000..caa2d53
--- /dev/null
+++ b/src/assets/css/subject.scss
@@ -0,0 +1,81 @@
+.subject-exam-title{
+  font-size: 18px;
+  line-height: 25px;
+  padding: 18px 20px;
+  border-bottom: 1px solid #DEDEDE;
+  margin-bottom: 12px;
+}
+.subject {
+  padding-left: 30px;
+  padding-right: 75px;
+}
+.subject-content{
+  margin-top: 18px;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  font-weight: 300;
+  background: #fff;
+  z-index: 1;
+  position: relative;
+}
+/* 题目 */
+.subject-title {
+  font-size: 18px;
+  line-height: 22px;
+  .subject-title-number {
+    display: inline-block;
+    line-height: 22px;
+  }
+  .subject-title-content {
+    // display: inline-block;
+  }
+}
+.subject-options {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  > li {
+    position: relative;
+    font-size: 24px;
+    .toggle {
+      opacity: 0;
+      text-align: center;
+      width: 35px;
+      /* auto, since non-WebKit browsers doesn't support input styling */
+      height: auto;
+      position: absolute;
+      top: 0;
+      bottom: 0;
+      margin: auto 0;
+      border: none;
+      /* Mobile Safari */
+      -webkit-appearance: none;
+      appearance: none;
+    }
+    .toggle+label {
+      background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
+      background-repeat: no-repeat;
+      background-position: center left;
+      background-size: 30px;
+    }
+    .toggle:checked+label {
+      background-size: 30px;
+      background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
+    }
+    label {
+      word-break: break-all;
+      padding: 10px 10px 10px 45px;
+      display: block;
+      line-height: 1.0;
+      transition: color 0.4s;
+    }
+    /* 选项名称 */
+    .subject-option-prefix {
+      font-size: 16px;
+      display: inline-block
+    }
+  }
+}
+.subject-answer {
+  padding: 16px;
+}
diff --git a/src/assets/css/transition.scss b/src/assets/css/transition.scss
new file mode 100644
index 0000000..d37186a
--- /dev/null
+++ b/src/assets/css/transition.scss
@@ -0,0 +1,12 @@
+.fade-transform-leave-active,
+.fade-transform-enter-active {
+  transition: all .5s;
+}
+.fade-transform-enter {
+  opacity: 0;
+  transform: translateY(30px);
+}
+.fade-transform-leave-to {
+  opacity: 0;
+  transform: translateY(30px);
+}
diff --git a/src/components/Subjects/Choices/index.vue b/src/components/Subjects/Choices/index.vue
new file mode 100644
index 0000000..2297745
--- /dev/null
+++ b/src/components/Subjects/Choices/index.vue
@@ -0,0 +1,89 @@
+<template>
+    <div>
+        <div class="subject-content">
+            <div class="subject-title">
+                {{ index }}
+                <span class="subject-title-content"
+                      v-html="subjectInfo.subjectName" />
+                <span class="subject-title-content">
+                    (&nbsp;单选题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
+                </span>
+            </div>
+
+            <ul class="subject-options"
+                v-for="option in options"
+                :key="option.id">
+                <li class="subject-option">
+                    <input class="toggle"
+                           type="checkbox"
+                           :checked="userAnswer === option.optionName"
+                           :id="'option' + option.id"
+                           @change="toggleOption(option)">
+                    <label :for="'option' + option.id">
+                        <span class="subject-option-prefix">{{ option.optionName + '.' }}&nbsp;</span>
+                        <span v-html="option.optionContent"
+                              class="subject-option-prefix" />
+                    </label>
+                </li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'Choices',
+    data () {
+        return {
+            subjectCount: 0,
+            subjectInfo: {
+                subjectName: '',
+                score: 0
+            },
+            options: [],
+            userAnswer: '',
+            index: ''
+        }
+    },
+    methods: {
+        getAnswer () {
+            return this.userAnswer
+        },
+        setAnswer (answer) {
+            this.userAnswer = answer
+        },
+        setSubjectInfo (subject, subjectCount, index) {
+            this.subjectCount = subjectCount
+            this.subjectInfo = subject
+            if (subject.hasOwnProperty('examSubjectOptions')) {
+                this.options = subject.examSubjectOptions
+
+                console.log(this.options)
+            }
+            if (subject.hasOwnProperty('answer')) {
+                console.log(subject.answer);
+                this.setAnswer(subject.answer)
+            }
+            this.index = index + '.'
+
+            console.log(subject, subjectCount, index, this.options, 5656565656)
+        },
+        getSubjectInfo () {
+            this.subjectInfo.options = this.options
+            return this.subjectInfo
+        },
+        // 选中选项
+        toggleOption (option) {
+            this.userAnswer = option.optionName
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../../assets/css/subject.scss';
+.subject-options > li label {
+    height: 36px;
+    line-height: 28px !important;
+}
+</style>
diff --git a/src/components/Subjects/Judgement/index.vue b/src/components/Subjects/Judgement/index.vue
new file mode 100644
index 0000000..f1cae2f
--- /dev/null
+++ b/src/components/Subjects/Judgement/index.vue
@@ -0,0 +1,81 @@
+<template>
+    <div>
+        <div class="subject-content">
+            <div class="subject-title">
+                {{ index }}
+                <span class="subject-title-content"
+                      v-html="subjectInfo.subjectName" />
+                <span class="subject-title-content">
+                    (&nbsp;判断题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
+                </span>
+            </div>
+            <ul class="subject-options"
+                v-for="option in options"
+                :key="option.id">
+                <li class="subject-option">
+                    <input class="toggle"
+                           type="checkbox"
+                           :checked="userAnswer === option.optionName"
+                           :id="'option' + option.id"
+                           @change="toggleOption(option)">
+                    <label :for="'option' + option.id">
+                        <span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span>
+                    </label>
+                </li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'Judgement',
+    data () {
+        return {
+            subjectCount: 0,
+            subjectInfo: {
+                subjectName: '',
+                score: 0
+            },
+            options: [
+                { id: 1, optionName: '正确' },
+                { id: 2, optionName: '错误' }
+            ],
+            userAnswer: '',
+            index: ''
+        }
+    },
+    methods: {
+        getAnswer () {
+            return this.userAnswer
+        },
+        setAnswer (answer) {
+            this.userAnswer = answer
+        },
+        setSubjectInfo (subject, subjectCount, index) {
+            this.subjectCount = subjectCount
+            this.subjectInfo = subject
+            if (subject.hasOwnProperty('answer')) {
+                this.setAnswer(subject.answer)
+            }
+            this.index = index + '.'
+        },
+        getSubjectInfo () {
+            this.subjectInfo.options = this.options
+            return this.subjectInfo
+        },
+        // 选中选项
+        toggleOption (option) {
+            this.userAnswer = option.optionName
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../../assets/css/subject.scss';
+.subject-options > li label {
+    height: 36px;
+    line-height: 28px !important;
+}
+</style>
diff --git a/src/components/Subjects/MultipleChoices/index.vue b/src/components/Subjects/MultipleChoices/index.vue
new file mode 100644
index 0000000..91975ba
--- /dev/null
+++ b/src/components/Subjects/MultipleChoices/index.vue
@@ -0,0 +1,99 @@
+<template>
+    <div>
+        <div class="subject-content">
+            <div class="subject-title">
+                {{ index }}
+                <span class="subject-title-content"
+                      v-html="subjectInfo.subjectName" />
+                <span class="subject-title-content">
+                    (&nbsp;多选题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
+                </span>
+            </div>
+
+            <ul class="subject-options"
+                v-for="option in options"
+                :key="option.id">
+                <li class="subject-option">
+                    <input class="toggle"
+                           type="checkbox"
+                           :checked="isChecked(option.optionName)"
+                           :id="'option' + option.id"
+                           @change="toggleOption($event, option)">
+                    <label :for="'option' + option.id">
+                        <span class="subject-option-prefix">{{ option.optionName + '.' }}&nbsp;</span>
+                        <span v-html="option.optionContent"
+                              class="subject-option-prefix" />
+                    </label>
+                </li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'MultipleChoices',
+    data () {
+        return {
+            subjectCount: 0,
+            subjectInfo: {
+                subjectName: '',
+                score: 0
+            },
+            options: [],
+            userAnswer: [],
+            index: ''
+        }
+    },
+    watch: {
+
+    },
+    methods: {
+        getAnswer () {
+            return this.userAnswer.join(',')
+        },
+        setAnswer (answer) {
+            // if (isNotEmpty(answer)) {
+            this.userAnswer = answer.split(',')
+            // }
+        },
+        setSubjectInfo (subject, subjectCount, index) {
+            this.subjectCount = subjectCount
+            this.subjectInfo = subject
+            if (subject.hasOwnProperty('examSubjectOptions')) {
+                this.options = subject.examSubjectOptions
+            }
+            if (subject.hasOwnProperty('answer')) {
+                this.setAnswer(subject.answer)
+            }
+            this.index = index + '.'
+        },
+        getSubjectInfo () {
+            this.subjectInfo.options = this.options
+            return this.subjectInfo
+        },
+        // 选中选项
+        toggleOption ($event, option) {
+
+            if ($event.target.checked) {
+                if (!this.userAnswer.includes(option.optionName)) {
+                    this.userAnswer.push(option.optionName)
+                }
+            } else {
+                this.userAnswer.splice(this.userAnswer.findIndex(item => item === option.optionName), 1)
+            }
+        },
+        isChecked (optionName) {
+            return this.userAnswer.includes(optionName)
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../../assets/css/subject.scss';
+.subject-options > li label {
+    height: 36px;
+    line-height: 28px !important;
+}
+</style>
diff --git a/src/components/Subjects/PracticalOperation/index.vue b/src/components/Subjects/PracticalOperation/index.vue
new file mode 100644
index 0000000..83ce13c
--- /dev/null
+++ b/src/components/Subjects/PracticalOperation/index.vue
@@ -0,0 +1,190 @@
+<template>
+    <div>
+        <div class="subject-content">
+            <div class="subject-title">
+                {{ index }}
+                <span class="subject-title-content"
+                      v-html="subjectInfo.subjectName" />
+                <span class="subject-title-content">
+                    (&nbsp;实操题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
+                </span>
+            </div>
+
+            <ul class="subject-options"
+                v-for="(option, index) in options"
+                :key="option.id">
+                <li class="subject-option pbox">
+
+                    <span class="num"
+                          @click="selectCheckbox($event, option)"> {{ userAnswer[index].value }} </span>
+
+                    <label :for="'option' + option.id">
+                        <span class="subject-option-prefix">{{ option.optionName + '.' }}&nbsp;</span>
+                        <span v-html="option.optionContent"
+                              class="subject-option-prefix" />
+                    </label>
+
+                </li>
+            </ul>
+
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'MultipleChoices',
+    data () {
+        return {
+            subjectCount: 0,
+            subjectInfo: {
+                subjectName: '',
+                score: 0
+            },
+            options: [],
+            userAnswer: [],
+            index: ''
+        }
+    },
+    watch: {
+
+    },
+    methods: {
+        getAnswer () {
+            return this.userAnswer
+        },
+        setAnswer (answer, option) {
+            console.log(answer);
+            if (answer != '') {
+
+                this.userAnswer = answer
+
+            } else {
+                this.userAnswer = []
+                option.forEach(item => {
+                    this.userAnswer.push({ key: item.optionName, value: '' })
+                })
+            }
+        },
+        setSubjectInfo (subject, subjectCount, index) {
+            this.subjectCount = subjectCount
+            this.subjectInfo = subject
+            if (subject.hasOwnProperty('examSubjectOptions')) {
+                this.options = subject.examSubjectOptions
+            }
+            if (subject.hasOwnProperty('answer')) {
+                this.setAnswer(subject.answer, subject.examSubjectOptions)
+            }
+            this.index = index + '.'
+        },
+        getSubjectInfo () {
+            this.subjectInfo.options = this.options
+            return this.subjectInfo
+        },
+
+        selectCheckbox ($event, option) {
+
+            var flag = false;
+
+            this.userAnswer.forEach(item => {
+                if (item.value != "") {
+                    flag = true
+                }
+            })
+
+            this.userAnswer
+
+            if (flag == true) {
+                // 其中最少有一个有值的
+                var onlyFlag = false;
+                var onlyValue = '';
+                var ind = 0;
+                this.userAnswer.forEach(item => {
+                    if (item.value != '' && item.value > ind) {
+                        ind = item.value
+                    }
+                })
+
+                this.userAnswer.forEach(item => {
+                    if (item.key == option.optionName) {
+                        if (item.value != '') {
+                            onlyValue = item.value
+                            onlyFlag = true
+                            item.value = ''
+                        } else {
+                            item.value = ind + 1
+                        }
+                    }
+                })
+
+                this.userAnswer.forEach(item => {
+                    if (onlyFlag == true) {
+
+                        if (item.value > onlyValue) {
+                            item.value -= 1
+                        }
+
+                    }
+                })
+
+
+            } else {
+                // 全部都为空
+                this.userAnswer.forEach(item => {
+                    if (item.key == option.optionName) {
+                        item.value = 1
+                    }
+                })
+            }
+
+
+            console.log(this.userAnswer)
+
+        },
+
+        isChecked (optionName) {
+            return this.userAnswer.includes(optionName)
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../../assets/css/subject.scss';
+
+.pbox .num {
+    // margin: 2px;
+    // text-align: center;
+    // vertical-align: middle;
+    // display: inline-block;
+    // width: 20px;
+    // height: 20px;
+    // border: 1px solid #999;
+    width: 26px;
+    height: 26px;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    margin: auto 0;
+    // opacity: 0;
+    text-align: center;
+    font-size: 18px;
+    font-weight: bold;
+    border: 1px solid #cfcfcf;
+    background-color: #ff9;
+    cursor: pointer;
+}
+
+.subject-options > li label {
+    height: 36px;
+    line-height: 28px !important;
+}
+.pbox.checked {
+    border: 1px solid #99f;
+    background-color: #ccf;
+}
+.pbox.checked .num {
+    border: 1px solid #ff0;
+    background-color: #ff9;
+}
+</style>
diff --git a/src/components/Subjects/ShortAnswer/index.vue b/src/components/Subjects/ShortAnswer/index.vue
new file mode 100644
index 0000000..3e29254
--- /dev/null
+++ b/src/components/Subjects/ShortAnswer/index.vue
@@ -0,0 +1,73 @@
+<template>
+  <div>
+    <div class="subject-content">
+      <div class="subject-title">
+        {{ index }}
+        <span class="subject-title-content" v-html="subjectInfo.subjectName"/>
+        <span class="subject-title-content" v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;({{subjectInfo.score}})分</span>
+        <div class="subject-tinymce">
+          <tinymce ref="editor" :height="height" v-model="userAnswer"/>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Tinymce from '@/components/Tinymce'
+
+export default {
+  name: 'ShortAnswer',
+  components: {
+    Tinymce
+  },
+  props: {
+    height: {
+      type: Number,
+      required: false,
+      default: 300
+    }
+  },
+  data () {
+    return {
+      subjectCount: 0,
+      subjectInfo: {
+        subjectName: '',
+        score: 0
+      },
+      userAnswer: '',
+      index: ''
+    }
+  },
+  methods: {
+    getAnswer () {
+      return this.userAnswer
+    },
+    setAnswer (answer) {
+      this.userAnswer = answer
+    },
+    setSubjectInfo (subject, subjectCount, index) {
+      this.subjectCount = subjectCount
+      this.subjectInfo = subject
+      if (subject.hasOwnProperty('answer')) {
+        this.setAnswer(subject.answer.answer)
+      }
+      this.index = index + '.'
+    },
+    getSubjectInfo () {
+      return this.subjectInfo
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  @import "../../../assets/css/subject.scss";
+  .subject-tinymce {
+    margin: 12px;
+  }
+  .subject-options > li label {
+    height: 36px;
+    line-height: 28px !important;
+}
+</style>
diff --git a/src/components/Tinymce/components/editorImage.vue b/src/components/Tinymce/components/editorImage.vue
new file mode 100644
index 0000000..6a743a6
--- /dev/null
+++ b/src/components/Tinymce/components/editorImage.vue
@@ -0,0 +1,103 @@
+<template>
+  <div class="upload-container">
+    <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">上传图片
+    </el-button>
+    <el-dialog :visible.sync="dialogVisible">
+      <el-upload
+        :multiple="true"
+        :file-list="fileList"
+        :show-file-list="true"
+        :on-remove="handleRemove"
+        :on-success="handleSuccess"
+        :before-upload="beforeUpload"
+        class="editor-slide-upload"
+        action="https://httpbin.org/post"
+        list-type="picture-card">
+        <el-button size="small" type="primary">点击上传</el-button>
+      </el-upload>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+      <el-button type="primary" @click="handleSubmit">确 定</el-button>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// import { getToken } from 'api/qiniu'
+
+export default {
+  name: 'EditorSlideUpload',
+  props: {
+    color: {
+      type: String,
+      default: '#1890ff'
+    }
+  },
+  data () {
+    return {
+      dialogVisible: false,
+      listObj: {},
+      fileList: []
+    }
+  },
+  methods: {
+    checkAllSuccess () {
+      return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
+    },
+    handleSubmit () {
+      const arr = Object.keys(this.listObj).map(v => this.listObj[v])
+      if (!this.checkAllSuccess()) {
+        this.$message('请等待所有图片上传成功 或 出现了网络问题,请刷新页面重新上传!')
+        return
+      }
+      this.$emit('successCBK', arr)
+      this.listObj = {}
+      this.fileList = []
+      this.dialogVisible = false
+    },
+    handleSuccess (response, file) {
+      const uid = file.uid
+      const objKeyArr = Object.keys(this.listObj)
+      for (let i = 0, len = objKeyArr.length; i < len; i++) {
+        if (this.listObj[objKeyArr[i]].uid === uid) {
+          this.listObj[objKeyArr[i]].url = response.files.file
+          this.listObj[objKeyArr[i]].hasSuccess = true
+          return
+        }
+      }
+    },
+    handleRemove (file) {
+      const uid = file.uid
+      const objKeyArr = Object.keys(this.listObj)
+      for (let i = 0, len = objKeyArr.length; i < len; i++) {
+        if (this.listObj[objKeyArr[i]].uid === uid) {
+          delete this.listObj[objKeyArr[i]]
+          return
+        }
+      }
+    },
+    beforeUpload (file) {
+      const _self = this
+      const _URL = window.URL || window.webkitURL
+      const fileName = file.uid
+      this.listObj[fileName] = {}
+      return new Promise((resolve, reject) => {
+        const img = new Image()
+        img.src = _URL.createObjectURL(file)
+        img.onload = function () {
+          _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
+        }
+        resolve(true)
+      })
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.editor-slide-upload {
+  margin-bottom: 20px;
+  /deep/ .el-upload--picture-card {
+    width: 100%;
+  }
+}
+</style>
diff --git a/src/components/Tinymce/index.vue b/src/components/Tinymce/index.vue
new file mode 100644
index 0000000..768d04c
--- /dev/null
+++ b/src/components/Tinymce/index.vue
@@ -0,0 +1,162 @@
+<template>
+  <div :class="{fullscreen:fullscreen}" class="tinymce-container editor-container">
+    <textarea :id="tinymceId" class="tinymce-textarea"/>
+  </div>
+</template>
+
+<script>
+import editorImage from './components/editorImage'
+import plugins from './plugins'
+import toolbar from './toolbar'
+
+export default {
+  name: 'Tinymce',
+  components: { editorImage },
+  props: {
+    id: {
+      type: String,
+      default: function () {
+        return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
+      }
+    },
+    value: {
+      type: String,
+      default: ''
+    },
+    toolbar: {
+      type: Array,
+      required: false,
+      default () {
+        return []
+      }
+    },
+    menubar: {
+      type: String,
+      default: 'file edit insert view format table'
+    },
+    height: {
+      type: Number,
+      required: false,
+      default: 360
+    }
+  },
+  data () {
+    return {
+      hasChange: false,
+      hasInit: false,
+      tinymceId: this.id,
+      fullscreen: false,
+      languageTypeList: {
+        'en': 'en',
+        'zh': 'zh_CN'
+      }
+    }
+  },
+  computed: {
+    language () {
+      return this.languageTypeList['zh']
+    }
+  },
+  watch: {
+    value (val) {
+      if (!this.hasChange && this.hasInit) {
+        this.$nextTick(() =>
+          window.tinymce.get(this.tinymceId).setContent(val || ''))
+      }
+    },
+    language () {
+      this.destroyTinymce()
+      this.$nextTick(() => this.initTinymce())
+    }
+  },
+  mounted () {
+    this.initTinymce()
+  },
+  activated () {
+    this.initTinymce()
+  },
+  deactivated () {
+    this.destroyTinymce()
+  },
+  destroyed () {
+    this.destroyTinymce()
+  },
+  methods: {
+    initTinymce () {
+      const _this = this
+      window.tinymce.init({
+        language: this.language,
+        selector: `#${this.tinymceId}`,
+        height: this.height,
+        body_class: 'panel-body ',
+        object_resizing: false,
+        toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
+        menubar: this.menubar,
+        plugins: plugins,
+        end_container_on_empty_block: true,
+        powerpaste_word_import: 'clean',
+        code_dialog_height: 450,
+        code_dialog_width: 1000,
+        advlist_bullet_styles: 'square',
+        advlist_number_styles: 'default',
+        imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
+        default_link_target: '_blank',
+        link_title: false,
+        nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
+        init_instance_callback: editor => {
+          if (_this.value) {
+            editor.setContent(_this.value)
+          }
+          _this.hasInit = true
+          editor.on('NodeChange Change KeyUp SetContent', () => {
+            this.hasChange = true
+            this.$emit('input', editor.getContent())
+          })
+        },
+        setup (editor) {
+          editor.on('FullscreenStateChanged', (e) => {
+            _this.fullscreen = e.state
+          })
+        }
+      })
+    },
+    destroyTinymce () {
+      if (window.tinymce.get(this.tinymceId)) {
+        window.tinymce.get(this.tinymceId).destroy()
+      }
+    },
+    setContent (value) {
+      window.tinymce.get(this.tinymceId).setContent(value)
+    },
+    getContent () {
+      return window.tinymce.get(this.tinymceId).getContent()
+    }
+  }
+}
+</script>
+
+<style scoped>
+.tinymce-container {
+  position: relative;
+}
+.tinymce-container>>>.mce-fullscreen {
+  z-index: 10000;
+}
+.tinymce-textarea {
+  visibility: hidden;
+  z-index: -1;
+}
+.editor-custom-btn-container {
+  position: absolute;
+  right: 4px;
+  top: 4px;
+  /*z-index: 2005;*/
+}
+.fullscreen .editor-custom-btn-container {
+  z-index: 10000;
+  position: fixed;
+}
+.editor-upload-btn {
+  display: inline-block;
+}
+</style>
diff --git a/src/components/Tinymce/plugins.js b/src/components/Tinymce/plugins.js
new file mode 100644
index 0000000..8fc207e
--- /dev/null
+++ b/src/components/Tinymce/plugins.js
@@ -0,0 +1,7 @@
+// Any plugins you want to use has to be imported
+// Detail plugins list see https://www.tinymce.com/docs/plugins/
+// Custom builds see https://www.tinymce.com/download/custom-builds/
+
+const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
+
+export default plugins
diff --git a/src/components/Tinymce/toolbar.js b/src/components/Tinymce/toolbar.js
new file mode 100644
index 0000000..7d6c2c7
--- /dev/null
+++ b/src/components/Tinymce/toolbar.js
@@ -0,0 +1,6 @@
+// Here is a list of the toolbar
+// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
+
+const toolbar = ['bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
+
+export default toolbar
diff --git a/src/config/env.js b/src/config/env.js
index 5270f73..1398ad9 100644
--- a/src/config/env.js
+++ b/src/config/env.js
@@ -1,5 +1,5 @@
 // 阿里矢量图标库配置
-let iconfontVersion = ['567566_pwc3oottzol'];
+let iconfontVersion = ['567566_pwc3oottzol', '2680691_r9wggg2tnk'];
 let iconfontUrl = `//at.alicdn.com/t/font_$key.css`;
 
 let baseUrl = '';
diff --git a/src/config/iconList.js b/src/config/iconList.js
index e79647e..40463a8 100644
--- a/src/config/iconList.js
+++ b/src/config/iconList.js
@@ -66,6 +66,17 @@
       "iconfont iconicon_add",
       "iconfont icongithub",
       "iconfont icongitee2",
+
+
+
+
+
+      "iconfont icon-baoming",
+      "iconfont icon-tiku",
+      "iconfont icon-duoxiaoliankaokaowuguanli",
+      "iconfont icon-kaoshi",
+      "iconfont icon-shijuan",
+      "iconfont icon-chengji",
     ]
   },
   {
diff --git a/src/const/constant.js b/src/const/constant.js
new file mode 100644
index 0000000..b50ef68
--- /dev/null
+++ b/src/const/constant.js
@@ -0,0 +1,10 @@
+export const nextSubjectType = {
+  last: 1,
+  next: 0,
+  current: 2
+}
+
+export const answerType = {
+  'true': 'right',
+  'false': 'incorrect'
+}
diff --git a/src/const/errorCode.js b/src/const/errorCode.js
new file mode 100644
index 0000000..032a908
--- /dev/null
+++ b/src/const/errorCode.js
@@ -0,0 +1,12 @@
+export default {
+  '478': '验证码错误,请重新输入',
+  '479': '验证码已过期,请重新输入',
+  '401': '当前操作没有权限',
+  '403': '当前操作没有权限',
+  '400': '用户名不存在或密码错误',
+  '500': '服务器内部错误,请反馈给管理员',
+  '4015': '服务不可用',
+  '4020': '验证码错误',
+  '4026': '验证码已过期,请重新获取',
+  'default': '系统未知错误,请反馈给管理员'
+}
diff --git a/src/router/views/index.js b/src/router/views/index.js
index aa2510c..62849a4 100644
--- a/src/router/views/index.js
+++ b/src/router/views/index.js
@@ -633,5 +633,19 @@
             component: () =>
                 import ( /* webpackChunkName: "views" */ '@/views/trainingRegistration/index')
         }]
+    },
+    {
+        path: '/trainExam',
+        component: Layout,
+        redirect: '/trainExam/index',
+        children: [{
+            path: 'index',
+            name: '考试申请',
+            meta: {
+                i18n: 'dict'
+            },
+            component: () =>
+                import ( /* webpackChunkName: "views" */ '@/views/trainExam/index')
+        }]
     }
 ]
\ No newline at end of file
diff --git a/src/views/applyexam/index.vue b/src/views/applyexam/index.vue
new file mode 100644
index 0000000..e6819f1
--- /dev/null
+++ b/src/views/applyexam/index.vue
@@ -0,0 +1,505 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-19 19:39:45
+ * menu-name 报名考试
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud v-model="obj"
+                               class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange"
+                               @row-save="questionBankRowSave"
+                               @row-del="questionBankRowDel">
+
+                        <!-- 自定义按钮 -->
+                        <!-- <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">新增
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">删除
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">导出
+                            </el-button>
+                        </template> -->
+
+                        <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="small"
+                                       icon="el-icon-delete"
+                                       @click="questionBankHandleDelete">删 除
+                            </el-button>
+                        </template>
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+
+import {
+    getApplyList,
+    addApply,
+    remove
+} from "@/api/examapi/applyexam";
+import { mapState } from 'vuex'
+
+
+
+
+export default {
+    data () {
+
+        return {
+            obj: {
+                name: '张三',
+            },
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: true,
+                editBtn: false,
+                addBtn: true,
+                selection: true,
+                menu: true,
+                // 导出按钮
+                excelBtn: true,
+                viewBtn: false,
+
+                // title: '题库',
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                indexLabel: '序号',
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+                // 操作栏宽度
+                menuWidth: 100,
+
+                column: [
+                    {
+                        label: "保安姓名",
+                        prop: "name",
+                        type: 'tree',
+                        dicUrl: '',
+                        search: true,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        props: {
+                            label: "title",
+                            value: "id",
+                        },
+                        rules: [{
+                            required: true,
+                            message: "请选择保安姓名",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "试卷名称",
+                        prop: "examName",
+                        type: 'tree',
+                        dicUrl: '/api/exampaper/page-tree',
+                        // search: true,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        props: {
+                            label: "examName",
+                            value: "id",
+                        },
+                        rules: [{
+                            required: true,
+                            message: "请选择试卷名称",
+                            trigger: "blur"
+                        }],
+                        width: 220
+                    },
+                    {
+                        label: "所属公司",
+                        prop: "deptName",
+                        search: true,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请选择所属公司",
+                            trigger: "blur"
+                        }],
+                        width: 220
+                    },
+                    {
+                        label: "准考证号",
+                        prop: "candidateNo",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请选择准考证号",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "身份证号",
+                        prop: "idCardNo",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请选择准考证号",
+                            trigger: "blur"
+                        }],
+                        width: 200
+                    },
+                    {
+                        label: "报考证件",
+                        prop: "applyCard", 
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请选择准考证号",
+                            trigger: "blur"
+                        }],
+                    },
+                    {
+                        label: "试卷分数",
+                        prop: "paperScore",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false
+                    },
+                    {
+                        label: "报名时间",
+                        prop: "applyTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        // 表单新增时是否禁止
+                        addDisabled: true,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        value: (new Date().getFullYear() + '-' + (new Date().getMonth() + 1 < 10
+                            ? "0" + (new Date().getMonth() + 1)
+                            : new Date().getMonth() + 1) + '-' + (new Date().getDate() < 10
+                                ? "0" + new Date().getDate()
+                                : new Date().getDate()) + ' ' + (new Date().getHours() < 10
+                                    ? "0" + new Date().getHours()
+                                    : new Date().getHours()) + ':' + (new Date().getMinutes() < 10
+                                        ? "0" + new Date().getMinutes()
+                                        : new Date().getMinutes()) + ':' + (new Date().getSeconds() < 10
+                                            ? "0" + new Date().getSeconds()
+                                            : new Date().getSeconds())),
+
+                        width: 180
+                    },
+                    {
+                        label: "考试时间",
+                        prop: "examTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 180
+                    }
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [
+
+            ],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+
+    watch: {
+        "form.examname": {
+            // form是表单或者表格绑定的数据集,v-model='form'
+            handler (val) {
+                if (val) {
+                    //地址截取,从县/区开始截取,并且取从县区第一个出现的位置开始
+                    var address = val.formattedAddress.toString();
+                    if (address.search("县") != -1) {
+                        this.form.address = address.substring(
+                            address.indexOf("县") + 1,
+                            address.length
+                        );
+                    }
+                    if (address.search("区") != -1) {
+                        this.form.address = address.substring(
+                            address.indexOf("区") + 1,
+                            address.length
+                        );
+                    }
+                }
+            },
+            immediate: true,
+        },
+    },
+    created () {
+
+      console.log(this.userInfo)
+
+      if (this.userInfo.role_name.indexOf('ksxtadmin') != -1) {
+
+        this.questionBankOption.column[0].dicUrl = "/api/blade-system/dept/lazy-tree-user?parentId="
+      } else {
+        this.questionBankOption.column[0].dicUrl = "/api/blade-system/dept/lazy-tree-user?parentId=" + this.userInfo.dept_id
+
+      }
+
+
+    },
+    mounted () {
+
+
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.user.userInfo
+        }),
+        ids () {
+            let ids = [];
+            this.questionBankSelectionList.forEach(ele => {
+                ids.push(ele.id);
+            });
+            return ids.join(",");
+        },
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+            getApplyList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        // 新增
+        questionBankRowSave (row, done, loading) {
+
+            addApply({ userId: row.name, examId: row.examName, applyTime: row.applyTime }).then(() => {
+                this.questionBankOnLoad(this.questionBankPage);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+
+        questionBankRowDel (row) {
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove(row.id);
+                })
+                .then(() => {
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                });
+        },
+
+        questionBankHandleDelete () {
+            if (this.questionBankSelectionList.length === 0) {
+                this.$message.warning("请选择至少一条数据");
+                return;
+            }
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove(this.ids);
+                })
+                .then(() => {
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                    this.$refs.questionBankCrud.toggleSelection();
+                });
+        },
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>
diff --git a/src/views/exam/examSubjects.vue b/src/views/exam/examSubjects.vue
new file mode 100644
index 0000000..5948425
--- /dev/null
+++ b/src/views/exam/examSubjects.vue
@@ -0,0 +1,328 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-18 15:47:06
+ * menu-name 题目管理
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud v-model="obj"
+                               class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange"
+                               @row-save="questionBankRowSave"
+                               @row-update="questionBankRowUpdate"
+                               @row-del="questionBankRowDel">
+
+                        <!-- 自定义按钮 -->
+                        <!-- <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">新增
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">删除
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">导出
+                            </el-button>
+                        </template> -->
+
+                        <template slot-scope="{row}"
+                                  slot="examstate">
+                            <el-tag>{{row.examstate == 0 ? '已发布' : '草稿'}}</el-tag>
+                        </template>
+
+                        <!-- <template slot="menu">
+                            <el-button type="text"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       @click="questionBankHandleDel">删除
+                            </el-button>
+                        </template> -->
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+
+import {
+    getPaperList,
+    updatePaper,
+    remove
+} from "@/api/examapi/examSubjects";
+
+
+
+export default {
+    data () {
+
+        var validatePass = (rule, value, callback) => {
+            console.log(value)
+            if (value == undefined || value == '') {
+                callback(new Error('请输入分数'));
+                return;
+            } else if (value !== '' && isNaN(value) == true) {
+                callback(new Error('请输入数字'));
+            } else if (value <= 0) {
+                callback(new Error('分数设置请大于0'));
+            } else {
+                callback();
+            }
+        };
+
+        return {
+            obj: {
+                name: '张三',
+            },
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: true,
+                editBtn: true,
+                addBtn: false,
+                selection: false,
+                // 导出按钮
+                excelBtn: false,
+                viewBtn: false,
+
+
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                  indexLabel: '序号',
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+
+                // 操作栏宽度
+                menu: true,
+                menuWidth: 180,
+
+                column: [
+                    {
+                        label: "题目名称",
+                        prop: "subjectName",
+                        span: 24,
+                        search: true,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        row: true,
+                        rules: [{
+                            required: true,
+                            message: "请输入考试名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "题目类型",
+                        prop: "choicesType",
+                        type: "select",
+                        search: true,
+                        searchSpan: 4,
+                        searchLabelWidth: 80,
+                        value: 0,
+                        dicData: [{
+                            label: '单选题',
+                            value: 0
+                        }, {
+                            label: '多选题',
+                            value: 1,
+                        }, {
+                            label: '判断题',
+                            value: 2,
+                        }],
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 106
+                    },
+                    {
+                        label: "分值",
+                        prop: "score",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+
+
+                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
+                        width: 106
+                    }
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+    created () {
+
+
+    },
+    mounted () {
+
+
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+
+            this.questionBankQuery.id = this.$route.query.id;
+
+            getPaperList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        questionBankRowDel (row) {
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove({ paperid: this.$route.query.id, subjectid: row.id });
+                })
+                .then(() => {
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                });
+        },
+
+        questionBankRowSave (row, done, loading) {
+            console.log(row, 898989);
+
+            add(row).then(() => {
+                this.initFlag = false;
+                this.onLoad(this.page);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+        questionBankRowUpdate (row, index, done, loading) {
+
+            updatePaper({ value: row.score, id: row.id }).then(() => {
+                this.questionBankOnLoad(this.questionBankPage);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>
diff --git a/src/views/exam/examination.vue b/src/views/exam/examination.vue
new file mode 100644
index 0000000..4a8b01b
--- /dev/null
+++ b/src/views/exam/examination.vue
@@ -0,0 +1,478 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-18 17:11:18
+ * menu-name 试卷管理
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud v-model="form"
+                               class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange"
+                               @row-save="questionBankRowSave"
+                               @row-update="questionBankRowUpdate"
+                               @row-del="questionBankRowDel">
+
+                        <!-- 自定义按钮 -->
+                        <!-- <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">新增
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">删除
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">导出
+                            </el-button>
+                        </template> -->
+
+                        <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="small"
+                                       icon="el-icon-delete"
+                                       @click="questionBankHandleDelete">删 除
+                            </el-button>
+                        </template>
+
+                        <template slot-scope="{row}"
+                                  slot="examStatus">
+                            <el-tag>{{row.examStatus == 0 ? '已发布' : '草稿'}}</el-tag>
+                        </template>
+
+                        <template slot-scope="{row}"
+                                  slot="menu">
+                            <el-button type="text"
+                                       size="mini"
+                                       icon="el-icon-document"
+                                       @click="subjectManagement(row)">题目管理
+                            </el-button>
+                        </template>
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+import {
+    getList,
+    add,
+    remove,
+    update
+} from "@/api/examapi/examination";
+
+
+export default {
+    data () {
+
+        var validatePass = (rule, value, callback) => {
+            console.log(value)
+            if (value == undefined || value == '') {
+                callback(new Error('请输入分数'));
+                return;
+            } else if (value !== '' && isNaN(value) == true) {
+                callback(new Error('请输入数字'));
+            } else if (value <= 0) {
+                callback(new Error('分数设置请大于0'));
+            } else {
+                callback();
+            }
+        };
+
+        return {
+            form: {},
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: true,
+                editBtn: true,
+                addBtn: true,
+                selection: true,
+                menu: true,
+                // 导出按钮
+                excelBtn: false,
+                viewBtn: true,
+
+                // title: '题库',
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                indexLabel: '序号',
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+                // 操作栏宽度
+                menuWidth: 284,
+
+                labelWidth: 140,
+
+                column: [
+                    {
+                        label: "试卷名称",
+                        prop: "examName",
+                        search: true,
+                        searchSpan: 4,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入试卷名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "试卷分数",
+                        prop: "totalScore",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+
+                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
+                        width: 100
+                    },
+                    {
+                        label: "考试时间",
+                        prop: "examTime",
+                        type: "daterange",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        startPlaceholder: '考试开始时间',
+                        endPlaceholder: '考试结束时间',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        // display: false,
+                        hide: true,
+                        rules: [{
+                            required: true,
+                            message: "请选择考试时间",
+                            trigger: "blur"
+                        }],
+                        width: 250
+                    },
+                    {
+                        label: "考试开始时间",
+                        prop: "startTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: false,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 180
+                    },
+                    {
+                        label: "考试结束时间",
+                        prop: "endTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: false,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 180
+                    },
+                    {
+                        label: "创建人",
+                        prop: "creator",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: true,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: false,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        hide: true,
+                        display: false,
+                    },
+                    {
+                        label: "备注",
+                        prop: "remark",
+                        span: 24,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false
+                    },
+                    {
+                        label: "注意事项",
+                        prop: "examAttention",
+                        type: "textarea",
+                        span: 24,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 240
+                    },
+
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [
+            ],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+    created () {
+
+
+    },
+    mounted () {
+
+
+    },
+    computed: {
+        ids () {
+            let ids = [];
+            this.questionBankSelectionList.forEach(ele => {
+                ids.push(ele.id);
+            });
+            return ids.join(",");
+        },
+    },
+    watch: {
+
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+            getList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        // 新增
+        questionBankRowSave (row, done, loading) {
+            row.startTime = row.examTime[0]
+            row.endTime = row.examTime[1]
+            row.examTime = JSON.stringify(row.examTime)
+            add(row).then(() => {
+                this.questionBankOnLoad(this.questionBankPage);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+        questionBankRowUpdate (row, index, done, loading) {
+            if (Array.isArray(row.examTime) != true) {
+                row.examTime = row.examTime.split(",")
+            }
+            row.startTime = row.examTime[0]
+            row.endTime = row.examTime[1]
+            row.examTime = JSON.stringify(row.examTime)
+            update(row).then(() => {
+                this.questionBankOnLoad(this.questionBankPage);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+
+        questionBankRowDel (row) {
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove(row.id);
+                })
+                .then(() => {
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                });
+        },
+
+        questionBankHandleDelete () {
+            if (this.questionBankSelectionList.length === 0) {
+                this.$message.warning("请选择至少一条数据");
+                return;
+            }
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove(this.ids);
+                })
+                .then(() => {
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                    this.$refs.questionBankCrud.toggleSelection();
+                });
+        },
+
+        subjectManagement (row) {
+            this.$router.push({
+                path: `/exam/subjects/${row.id}`,
+                query: row
+            })
+
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>
diff --git a/src/views/exam/performance.vue b/src/views/exam/performance.vue
new file mode 100644
index 0000000..78bc56d
--- /dev/null
+++ b/src/views/exam/performance.vue
@@ -0,0 +1,398 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-18 19:44:47
+ * menu-name 成绩管理
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud v-model="obj"
+                               class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange"
+                               @row-update="questionBankRowUpdate">
+
+                        <template slot-scope="{ row }"
+                                  slot="learnGrade">
+                            {{ row.learnGrade == -1 ? "暂未录入" : row.learnGrade }}
+                        </template>
+
+                        <!-- 自定义按钮 -->
+                        <!-- <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">新增
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">删除
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">导出
+                            </el-button>
+                        </template> -->
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+import {
+    getList,
+    update
+} from "@/api/examapi/performance";
+
+
+
+export default {
+
+
+    data () {
+
+        var validatePass = (rule, value, callback) => {
+            console.log(value)
+            if (value == undefined || value == '') {
+                callback(new Error('请输入实操成绩'));
+                return;
+            } else if (value !== '' && isNaN(value) == true) {
+                callback(new Error('请输入数字'));
+            } else if (value <= 0) {
+                callback(new Error('分数设置请大于0'));
+            } else if (value > 100) {
+                callback(new Error('分数设置请小于100'));
+            } else {
+                callback();
+            }
+        };
+
+        return {
+            obj: {
+                name: '张三',
+            },
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: false,
+                editBtn: true,
+                addBtn: false,
+                selection: false,
+                // 导出按钮
+                excelBtn: true,
+                excelBtnText: '成绩导出',
+                viewBtn: true,
+                title: '成绩',
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                indexLabel: '序号',
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+                // 操作栏宽度
+                menu: true,
+                menuWidth: 136,
+                labelWidth: 120,
+
+                column: [
+                    {
+                        label: "试卷名称",
+                        prop: "examName",
+                        search: true,
+                        searchSpan: 4,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入试卷名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "保安姓名",
+                        prop: "securityName",
+                        search: true,
+                        searchSpan: 4,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入保安姓名",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "所属公司",
+                        prop: "company",
+                        search: true,
+                        searchSpan: 4,
+                        dicUrl: '/api/blade-system/dept/tree',
+                        props: {
+                            label: "title",
+                            value: "id",
+                        },
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入所属公司",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "考试时间",
+                        prop: "examTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        width: 250,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                    },
+                    {
+                        label: "理论成绩",
+                        prop: "theoryGrade",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+
+                    },
+                    {
+                        label: "实操成绩",
+                        prop: "learnGrade",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
+                    },
+                    {
+                        label: "总成绩",
+                        prop: "allGrade",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入考试名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "是否合格",
+                        prop: "qualified",
+                        type: 'select',
+                        slot: true,
+                        search: true,
+                        searchSpan: 4,
+                        dicData: [{
+                            label: '合格',
+                            value: 0
+                        }, {
+                            label: '不合格',
+                            value: 1,
+                        }, {
+                            label: '暂未录实操成绩',
+                            value: 2,
+                        }],
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入考试名称",
+                            trigger: "blur"
+                        }]
+                    },
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [
+            ],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+    created () {
+
+
+    },
+    mounted () {
+
+
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+            getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        questionBankRowUpdate (row, index, done, loading) {
+
+            update({ theoryGrade: row.theoryGrade, learnGrade: row.learnGrade, id: row.id }).then(() => {
+                this.questionBankOnLoad(this.questionBankPage);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>
diff --git a/src/views/exam/startexam.vue b/src/views/exam/startexam.vue
new file mode 100644
index 0000000..36b593e
--- /dev/null
+++ b/src/views/exam/startexam.vue
@@ -0,0 +1,388 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-18 17:09:52
+ * menu-name 考试管理
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud v-model="form"
+                               class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange">
+
+                        <!-- 自定义按钮 -->
+                        <!-- <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">新增
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">删除
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">导出
+                            </el-button>
+                        </template> -->
+
+                        <template slot-scope="{row}"
+                                  slot="examStatus">
+                            <el-tag>{{row.examStatus == 0 ? '已发布' : '草稿'}}</el-tag>
+                        </template>
+
+                        <template slot-scope="{row}"
+                                  slot="menu">
+
+                            <el-button type="text"
+                                       size="mini"
+                                       icon="icon-kaoshi"
+                                       class="start-kaoshi"
+
+                                       @click="startExam(row)">开始考试
+                            </el-button>
+                        </template>
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+import {
+    getList,
+} from "@/api/examapi/examination";
+
+
+export default {
+    data () {
+
+        var validatePass = (rule, value, callback) => {
+            console.log(value)
+            if (value == undefined || value == '') {
+                callback(new Error('请输入分数'));
+                return;
+            } else if (value !== '' && isNaN(value) == true) {
+                callback(new Error('请输入数字'));
+            } else if (value <= 0) {
+                callback(new Error('分数设置请大于0'));
+            } else {
+                callback();
+            }
+        };
+
+        return {
+            form: {},
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: false,
+                editBtn: false,
+                addBtn: false,
+                selection: false,
+                menu: true,
+                // 导出按钮
+                excelBtn: false,
+                viewBtn: true,
+
+                // title: '题库',
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                indexLabel: '序号',
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+                // 操作栏宽度
+                menuWidth: 246,
+
+                labelWidth: 140,
+
+                column: [
+                    {
+                        label: "试卷名称",
+                        prop: "examName",
+                        search: true,
+                        searchSpan: 4,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入试卷名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "试卷分数",
+                        prop: "totalScore",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+
+                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
+                        width: 100
+                    },
+                    {
+                        label: "考试时间",
+                        prop: "examTime",
+                        type: "daterange",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        startPlaceholder: '考试开始时间',
+                        endPlaceholder: '考试结束时间',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        // display: false,
+                        hide: true,
+                        rules: [{
+                            required: true,
+                            message: "请选择考试时间",
+                            trigger: "blur"
+                        }],
+                        width: 250
+                    },
+                    {
+                        label: "考试开始时间",
+                        prop: "startTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: false,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 180
+                    },
+                    {
+                        label: "考试结束时间",
+                        prop: "endTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: false,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 180
+                    },
+                    {
+                        label: "创建人",
+                        prop: "creator",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: true,
+                        // 表单新增时是否可见
+                        addDisplay: false,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: false,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        hide: true,
+                        display: false,
+                    },
+                    {
+                        label: "备注",
+                        prop: "remark",
+                        span: 24,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false
+                    },
+                    {
+                        label: "注意事项",
+                        prop: "examAttention",
+                        type: "textarea",
+                        span: 24,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        width: 240
+                    },
+
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [
+            ],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+    created () {
+
+
+    },
+    mounted () {
+
+
+    },
+    computed: {
+        ids () {
+            let ids = [];
+            this.questionBankSelectionList.forEach(ele => {
+                ids.push(ele.id);
+            });
+            return ids.join(",");
+        },
+    },
+    watch: {
+
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+            getList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        startExam (row) {
+            this.$router.push({
+                path: `/startexam/${row.id}`,
+                query: row
+            })
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>
diff --git a/src/views/exam/subject.vue b/src/views/exam/subject.vue
new file mode 100644
index 0000000..cac637c
--- /dev/null
+++ b/src/views/exam/subject.vue
@@ -0,0 +1,263 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-18 16:04:26
+ * menu-name 题库查询
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange"
+                               @row-del="questionBankHandleDel">
+
+                        <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="small"
+                                       icon="el-icon-delete"
+                                       @click="questionBankHandleDelete">删 除
+                            </el-button>
+                        </template>
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+import {
+    getList,
+    remove,
+} from "@/api/examapi/subject";
+
+
+export default {
+    data () {
+        return {
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: true,
+
+                editBtn: false,
+
+                addBtn: false,
+
+                selection: true,
+                menu: true,
+                // 导出按钮
+                excelBtn: true,
+                excelBtnText: '题库导出',
+                title: '题库',
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                indexLabel: '序号',
+                viewBtn: true,
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+                // 操作栏宽度
+                menuWidth: 226,
+
+                column: [
+                    {
+                        label: "题目名称",
+                        prop: "subjectName",
+                        search: true,
+                        slot: true,
+                    },
+                    {
+                        label: "题目类型",
+                        prop: "choicesType",
+                        search: true,
+                        type: "select",
+                        dicData: [{
+                            label: '单选题',
+                            value: 0
+                        }, {
+                            label: '多选题',
+                            value: 1,
+                        }, {
+                            label: '判断题',
+                            value: 2,
+                        }],
+                        slot: true,
+                        width: 96,
+                    },
+                    {
+                        label: "题目分值",
+                        prop: "score",
+                        slot: true,
+                        width: 96,
+                    },
+                    {
+                        label: "参考答案",
+                        prop: "answer",
+                        slot: true,
+                        width: 96,
+                    },
+                    {
+                        label: "创建人",
+                        prop: "creator",
+                        slot: true,
+                        width: 96,
+                    },
+                    {
+                        label: "创建时间",
+                        prop: "createDate",
+                        slot: true,
+                        width: 130,
+                    },
+                    {
+                        label: "修改人",
+                        prop: "modifier",
+                        slot: true,
+                        width: 96,
+                    },
+                    {
+                        label: "修改时间",
+                        prop: "modifyDate",
+                        slot: true,
+                        width: 130,
+                    }
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [
+
+            ],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+    created () {
+
+
+    },
+    mounted () {
+
+
+    },
+     computed: {
+        ids () {
+            let ids = [];
+            this.questionBankSelectionList.forEach(ele => {
+                ids.push(ele.id);
+            });
+            return ids.join(",");
+        },
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+            getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        questionBankHandleDel (row) {
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove(row.id);
+                })
+                .then(() => {
+
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                });
+        },
+
+        questionBankHandleDelete () {
+            if (this.questionBankSelectionList.length === 0) {
+                this.$message.warning("请选择至少一条数据");
+                return;
+            }
+            this.$confirm("确定将选择数据删除?", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            })
+                .then(() => {
+                    return remove(this.ids);
+                })
+                .then(() => {
+                    this.questionBankOnLoad(this.questionBankPage);
+                    this.$message({
+                        type: "success",
+                        message: "操作成功!"
+                    });
+                    this.$refs.questionBankCrud.toggleSelection();
+                });
+        },
+
+
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>
diff --git a/src/views/exam/topicDetails.vue b/src/views/exam/topicDetails.vue
new file mode 100644
index 0000000..ddbe726
--- /dev/null
+++ b/src/views/exam/topicDetails.vue
@@ -0,0 +1,211 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-13 11:19:28
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-15 16:40:40
+ */
+<template>
+    <div class="app-container">
+
+        <el-tabs v-model="activeName"
+                 @tab-click="handleClick">
+            <el-tab-pane label="单选题"
+                         name="first">
+
+                <div>
+
+                    <el-row>
+                        <el-col :span="12">
+                        </el-col>
+                    </el-row>
+
+                </div>
+
+                <avue-form v-model="form"
+                           :option="option">
+
+                    <template slot-scope="scope"
+                              slot="text">
+                        <div>
+                            <el-input v-model="form.text"
+                                      placeholder="这里是自定的表单"></el-input>
+                        </div>
+                    </template>
+
+                    <template slot-scope="scope"
+                              slot="rate">
+                        <div>
+                            <avue-rate v-model="form.rate"></avue-rate>
+
+                        </div>
+                    </template>
+
+                    <template slot="provinceType"
+                              slot-scope="{item,value,label}">
+                        <span>{{ item }}</span>
+                    </template>
+
+                </avue-form>
+
+            </el-tab-pane>
+            <el-tab-pane label="多选题"
+                         name="second">多选题</el-tab-pane>
+            <el-tab-pane label="判断题"
+                         name="third">判断题</el-tab-pane>
+        </el-tabs>
+    </div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+            activeName: 'first',
+
+            rateObj: {
+                state: '一般',
+                value: 4
+            },
+
+            tempSubject: {
+
+            },
+            dialogStatus: '',
+            dialogStatusType: {
+
+            },
+            subjectsType:
+                '',
+            form: {
+                text: '',
+                rate: 4
+            },
+            option: {
+                labelWidth: 120,
+                column: [
+                    {
+                        label: '分值',
+                        prop: 'text',
+                        formslot: true,
+                        labelslot: true,
+                        errorslot: true,
+                        rules: [{
+                            required: true,
+                            message: "请输入姓名",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: '难度',
+                        prop: 'rate',
+                        formslot: true,
+                        labelslot: true,
+                    },
+                    {
+                        label: "参考答案",
+                        prop: "sex",
+                        span: 6,
+                        type: "radio",
+                        dicData: [{
+                            label: 'A',
+                            value: 0
+                        }, {
+                            label: 'B',
+                            value: 1
+                        }, {
+                            label: 'C',
+                            value: 2
+                        }, {
+                            label: 'D',
+                            value: 3
+                        }],
+                        errorslot: true,
+                        rules: [{
+                            required: true,
+                            message: "请选择答案",
+                            trigger: "blur"
+                        }],
+                        mock: {
+                            type: 'dic'
+                        }
+                    },
+                    {
+                        type: 'ueditor',
+                        component: 'AvueUeditor',
+                        label: '题目名称',
+                        span: 24,
+                        display: true,
+                        action: '',
+                        oss: '',
+                        props: {},
+                        ali: {},
+                        qiniu: {},
+                        prop: 'titleName',
+                        rules: [{
+                            required: true,
+                            message: "请输入题目名称",
+                            trigger: "blur"
+                        }],
+                    },
+                    {
+                        label: '',
+                        labelWidth: 40,
+                        prop: 'divider',
+                        component: 'elDivider',//ele分割线
+                        span: 24,
+                        event: {
+                            click: () => {
+                                this.$message.success('点击方法')
+                            },
+                        },
+                        params: {
+                            html: '<h2 style="font-size: 16px; font-weight: normal"> 选项列表 </h2>',
+                            contentPosition: "center",
+                        }
+                    },
+                    {
+                        label: "题目名称",
+                        prop: "content",
+                        component: 'AvueUeditor',
+                        options: {
+                            action: '/api/blade-resource/oss/endpoint/put-file',
+                            props: {
+                                res: "data",
+                                url: "link",
+                            }
+                        },
+                        hide: true,
+                        minRows: 6,
+                        span: 24,
+                        rules: [{
+                            required: true,
+                            message: "请输入题目名称",
+                            trigger: "blur"
+                        }],
+                    }
+                ]
+            }
+        }
+    },
+    methods: {
+        handleTabChange () { },
+        handleSelectSubject () { },
+        dialogSubjectFormVisible () { },
+        createSubjectData () { },
+        updateSubjectData () { },
+        updateAndAddSubjectData () { },
+        handleClick (tab, event) {
+            console.log(tab, event);
+        }
+
+    }
+}
+
+</script>
+
+
+<style lang="scss" scoped>
+.dialog-footer {
+    margin-top: 20px;
+}
+</style>
diff --git a/src/views/singleperformance/index.vue b/src/views/singleperformance/index.vue
new file mode 100644
index 0000000..792827c
--- /dev/null
+++ b/src/views/singleperformance/index.vue
@@ -0,0 +1,398 @@
+/*
+ * @Author: Morpheus
+ * @Date: 2021-07-05 16:31:54
+ * @Last Modified by: Morpheus
+ * @Last Modified time: 2021-07-18 21:02:10
+ * menu-name 成绩管理
+ */
+<template>
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <avue-crud v-model="obj"
+                               class="company-box"
+                               :option="questionBankOption"
+                               :search.sync="questionBankSearch"
+                               :table-loading="questionBankLoading"
+                               :data="questionBankData"
+                               ref="questionBankCrud"
+                               :page.sync="questionBankPage"
+                               @on-load="questionBankOnLoad"
+                               @selection-change="questionBankSelectionChange"
+                               @search-change="questionBankSearchChange"
+                               @search-reset="questionBankSearchReset"
+                               @current-change="questionBankCurrentChange"
+                               @size-change="questionBankSizeChange"
+                               @row-update="questionBankRowUpdate">
+
+                        <template slot-scope="{ row }"
+                                  slot="learnGrade">
+                            {{ row.learnGrade == -1 ? "暂未录入" : row.learnGrade }}
+                        </template>
+
+                        <!-- 自定义按钮 -->
+                        <!-- <template slot="menuLeft">
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">新增
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">删除
+                            </el-button>
+                            <el-button type="danger"
+                                       size="mini"
+                                       icon="el-icon-delete"
+                                       plain
+                                       @click="handleDelete">导出
+                            </el-button>
+                        </template> -->
+
+                    </avue-crud>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+import {
+    getList,
+    update
+} from "@/api/examapi/performance";
+
+
+
+export default {
+
+
+    data () {
+
+        var validatePass = (rule, value, callback) => {
+            console.log(value)
+            if (value == undefined || value == '') {
+                callback(new Error('请输入实操成绩'));
+                return;
+            } else if (value !== '' && isNaN(value) == true) {
+                callback(new Error('请输入数字'));
+            } else if (value <= 0) {
+                callback(new Error('分数设置请大于0'));
+            } else if (value > 100) {
+                callback(new Error('分数设置请小于100'));
+            } else {
+                callback();
+            }
+        };
+
+        return {
+            obj: {
+                name: '张三',
+            },
+            questionBankOption: {
+                // 操作栏多余按钮去除
+                delBtn: false,
+                editBtn: true,
+                addBtn: false,
+                selection: false,
+                // 导出按钮
+                excelBtn: true,
+                excelBtnText: '成绩导出',
+                viewBtn: true,
+                title: '成绩',
+
+                align: 'center',
+                height: 'auto',
+                calcHeight: 80,
+                tip: false,
+                searchShow: true,
+                searchMenuSpan: 4,
+                index: true,
+                indexLabel: '序号',
+                //dialogType: 'drawer',
+                dialogClickModal: false,
+                // 操作栏宽度
+                menu: false,
+                menuWidth: 136,
+                labelWidth: 120,
+
+                column: [
+                    {
+                        label: "试卷名称",
+                        prop: "examName",
+                        search: true,
+                        searchSpan: 4,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入试卷名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "保安姓名",
+                        prop: "securityName",
+                        search: true,
+                        searchSpan: 4,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入保安姓名",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "所属公司",
+                        prop: "company",
+                        search: true,
+                        searchSpan: 4,
+                        dicUrl: '/api/blade-system/dept/tree',
+                        props: {
+                            label: "title",
+                            value: "id",
+                        },
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入所属公司",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "考试时间",
+                        prop: "examTime",
+                        type: "datetime",
+                        // span: 24,
+                        format: 'yyyy-MM-dd HH:mm:ss',
+                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
+                        width: 250,
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                    },
+                    {
+                        label: "理论成绩",
+                        prop: "theoryGrade",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+
+                    },
+                    {
+                        label: "实操成绩",
+                        prop: "learnGrade",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: false,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
+                    },
+                    {
+                        label: "总成绩",
+                        prop: "allGrade",
+                        slot: true,
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入考试名称",
+                            trigger: "blur"
+                        }]
+                    },
+                    {
+                        label: "是否合格",
+                        prop: "qualified",
+                        type: 'select',
+                        slot: true,
+                        search: true,
+                        searchSpan: 4,
+                        dicData: [{
+                            label: '合格',
+                            value: 0
+                        }, {
+                            label: '不合格',
+                            value: 1,
+                        }, {
+                            label: '暂未录实操成绩',
+                            value: 2,
+                        }],
+                        // 表单新增时是否禁止
+                        addDisabled: false,
+                        // 表单新增时是否可见
+                        addDisplay: true,
+                        // 表单新增时是否为查看模式
+                        addDetail: false,
+                        // 表单编辑时是否禁止
+                        editDisabled: true,
+                        // 表单编辑时是否可见
+                        editDisplay: true,
+                        // 表单编辑时是否为查看模式
+                        editDetail: false,
+                        rules: [{
+                            required: true,
+                            message: "请输入考试名称",
+                            trigger: "blur"
+                        }]
+                    },
+                ]
+            },
+            questionBankSearch: {},
+            questionBankLoading: true,
+            questionBankData: [
+            ],
+            questionBankPage: {
+                pageSize: 10,
+                currentPage: 1,
+                total: 16
+            },
+            questionBankQuery: {},
+            questionBankSelectionList: [],
+        }
+    },
+    created () {
+
+
+    },
+    mounted () {
+
+
+    },
+    methods: {
+        questionBankOnLoad (page, params = {}) {
+            this.questionBankLoading = false;
+            getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+                const data = res.data.data;
+                this.questionBankPage.total = data.total;
+                this.questionBankData = data.records;
+                this.questionBankLoading = false;
+                this.questionBankSelectionClear();
+            });
+        },
+        questionBankSelectionClear () {
+            this.questionBankSelectionList = [];
+            this.$refs.questionBankCrud.toggleSelection();
+        },
+        questionBankSelectionChange (list) {
+            this.questionBankSelectionList = list;
+        },
+        questionBankSearchChange (params, done) {
+            this.questionBankQuery = params;
+            this.questionBankPage.currentPage = 1;
+            this.questionBankOnLoad(this.questionBankPage, params);
+            done();
+        },
+        questionBankSearchReset () {
+            this.questionBankQuery = {};
+            this.questionBankOnLoad(this.questionBankPage);
+        },
+        questionBankCurrentChange (currentPage) {
+            this.questionBankPage.currentPage = currentPage;
+        },
+        questionBankSizeChange (pageSize) {
+            this.questionBankPage.pageSize = pageSize;
+        },
+
+        questionBankRowUpdate (row, index, done, loading) {
+
+            update({ theoryGrade: row.theoryGrade, learnGrade: row.learnGrade, id: row.id }).then(() => {
+                this.questionBankOnLoad(this.questionBankPage);
+                this.$message({
+                    type: "success",
+                    message: "操作成功!"
+                });
+                done();
+            }, error => {
+                window.console.log(error);
+                loading();
+            });
+        },
+
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+</style>
diff --git a/src/views/startexam/index.vue b/src/views/startexam/index.vue
new file mode 100644
index 0000000..4f446a8
--- /dev/null
+++ b/src/views/startexam/index.vue
@@ -0,0 +1,663 @@
+<template>
+
+    <el-row class="morpheus-box">
+        <el-col :span="24">
+            <el-card>
+
+                <div class="exam-card-body">
+
+                    <div class="subject-box">
+                        <el-row :gutter="30">
+                            <el-col :span="5">
+                                <div class="tool-bar">
+                                    <div class="time-remain">
+                                        剩余时间:
+                                        <div class="time">
+                                            <count-down v-on:start_callback="countDownS_cb(1)"
+                                                        v-on:end_callback="countDownE_cb(1)"
+                                                        :current-time="currentTime"
+                                                        :start-time="startTime"
+                                                        :end-time="endTime"
+                                                        :tip-text="'距离考试开始'"
+                                                        :tip-text-end="'距离考试结束'"
+                                                        :end-text="'考试结束'"
+                                                        :hourTxt="':'"
+                                                        :minutesTxt="':'"
+                                                        :secondsTxt="''">
+                                            </count-down>
+                                        </div>
+                                    </div>
+                                    <div class="current-progress">
+                                        当前进度: {{subjectIndex}}/{{subjectIds.length}}
+                                    </div>
+                                    <div class="answer-card">
+                                        <el-button type="text"
+                                                   icon="el-icon-date"
+                                                   @click="answerCard">答题卡</el-button>
+                                    </div>
+                                    <el-button type="success"
+                                               icon="el-icon-date"
+                                               @click="submitExam"
+                                               v-bind:disabled="disableSubmit">提交</el-button>
+                                </div>
+                            </el-col>
+                            <el-col :span="18">
+                                <div class="subject-box-card">
+                                    <div class="subject-exam-title">{{exam.examinationName}}(共{{subjectIds.length}}题,合计{{exam.totalScore}}分)</div>
+                                    <!-- 题目内容 -->
+                                    <choices ref="choices"
+                                             v-show="this.query.type === 0" />
+
+                                    <multiple-choices ref="multipleChoices"
+                                                      v-show="this.query.type === 1" />
+
+                                    <judgement ref="judgement"
+                                               v-show="this.query.type === 2" />
+
+                                    <practical-operation ref="practicalOperation"
+                                                         v-show="this.query.type === 3" />
+
+                                    <short-answer ref="shortAnswer"
+                                                  v-show="this.query.type === 4" />
+
+                                    <div class="subject-buttons"
+                                         v-if="query.subjectId !== ''">
+
+                                        <el-button plain
+                                                   @click="last"
+                                                   :loading="loadingLast">上一题</el-button>
+                                        <el-button plain
+                                                   @click="next"
+                                                   :loading="loadingNext">下一题</el-button>
+                                        <el-button type="success"
+                                                   @click="submitExam"
+                                                   v-bind:disabled="disableSubmit">提交</el-button>
+
+                                    </div>
+                                </div>
+                            </el-col>
+                        </el-row>
+                        <el-dialog title="答题卡"
+                                   :visible.sync="dialogVisible"
+                                   width="50%"
+                                   top="10vh"
+                                   :modal='false'
+                                   center>
+                            <div class="answer-card-title">{{exam.examinationName}}(共{{subjectIds.length}}题,合计{{exam.totalScore}}分)</div>
+                            <div class="answer-card-split"></div>
+                            <el-row class="answer-card-content">
+                                <el-button :class="{ 'answered': subjectIds[index].answered }"
+                                           circle
+                                           v-for="(value, index) in subjectIds"
+                                           :key="index"
+                                           @click="toSubject(value.everyID, value.type, index)">&nbsp;{{index + 1}}&nbsp;</el-button>
+                            </el-row>
+                        </el-dialog>
+                    </div>
+
+                </div>
+
+            </el-card>
+        </el-col>
+    </el-row>
+
+</template>
+<script>
+import { mapState } from 'vuex'
+import CountDown from 'vue2-countdown'
+import { saveAndNext } from '@/api/exam/answer'
+import { getSubjectIds } from '@/api/exam/exam'
+import { getCurrentTime } from '@/api/exam/examRecord'
+import { getSubjectAnswer } from '@/api/exam/subject'
+
+import moment from 'moment'
+import { messageSuccess, messageFail, messageWarn, isNotEmpty } from '@/util/util'
+import Tinymce from '@/components/Tinymce'
+import Choices from '@/components/Subjects/Choices'
+
+import MultipleChoices from '@/components/Subjects/MultipleChoices'
+import PracticalOperation from '@/components/Subjects/PracticalOperation'
+
+
+
+
+// import ShortAnswer from '@/components/Subjects/ShortAnswer'
+import Judgement from '@/components/Subjects/Judgement'
+
+import { nextSubjectType } from '@/const/constant'
+
+export default {
+    components: {
+        CountDown,
+        Tinymce,
+        Choices,
+        MultipleChoices,
+        PracticalOperation,
+        Judgement,
+        // ShortAnswer,
+    },
+    data () {
+        return {
+            loadingLast: false,
+            loadingNext: false,
+
+            currentTime: 0,
+            startTime: 0,
+            endTime: 0,
+            disableSubmit: true,
+            subjectIndex: 1,
+            query: {
+                examinationId: undefined,
+                examRecordId: undefined,
+                subjectId: undefined,
+                userId: undefined,
+                type: 0
+            },
+            subject: {},
+            answer: '',
+            dialogVisible: false,
+            subjectIds: [],
+            subjectStartTime: undefined,
+            exam: {
+                id: '590969316204220416',
+                creator: 'admin',
+                createDate: 1560939664000,
+                modifier: 'preview',
+                modifyDate: 1609835214000,
+
+                delFlag: 0,
+
+                examinationName: '',
+
+                startTime: null,
+                endTime: null,
+
+                totalScore: 50,
+
+                status: 0,
+
+
+                remark: '全国计算机统考练习题10道',
+
+                newRecord: false
+            },
+            firstFlag: true
+        }
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.user.userInfo
+        })
+    },
+    created () {
+
+        const examInfo = this.$route.params.id
+
+        if (isNotEmpty(examInfo)) {
+            // 试卷ID
+            this.query.examinationId = this.$route.params.id
+
+            // 考场ID
+            this.query.examRecordId = this.userInfo.user_id
+
+            this.query.userId = this.userInfo.user_id
+
+            this.exam.id = this.userInfo.user_id + '' + this.$route.params.id
+
+            this.exam.examinationName = this.$route.query.examName
+            this.exam.startTime = this.$route.query.startTime
+            this.exam.endTime = this.$route.query.endTime
+            this.exam.totalScore = this.$route.query.totalScore
+            this.exam.status = this.$route.query.examStatus
+            this.exam.remark = this.$route.query.remark
+
+            this.validateExamTime()
+        }
+    },
+    methods: {
+        countDownS_cb: function () {
+            messageSuccess(this, '考试开始')
+        },
+        validateExamTime () {
+            getCurrentTime().then(response => {
+                const currentTime = moment(response.data.data)
+                if (currentTime.isAfter(this.exam.endTime)) {
+                    messageWarn(this, '考试已结束')
+                } else if (currentTime.isBefore(this.exam.startTime)) {
+                    messageWarn(this, '考试未开始')
+                } else {
+                    this.startExam()
+                    const current = currentTime.valueOf()
+                    this.currentTime = current
+                    this.startTime = current
+                    this.subjectStartTime = current
+                    this.endTime = moment(this.exam.endTime).valueOf()
+                    this.disableSubmit = false
+                }
+            }).catch(() => {
+                messageFail(this, '开始考试失败!15')
+            })
+        },
+        startExam () {
+            // 获取题目ID列表
+            getSubjectIds({ id: this.query.examinationId }).then(subjectResponse => {
+                const subjectData = subjectResponse.data.data.examExaminationSubjects
+                if (subjectData.length > 0) {
+                    for (let i = 0; i < subjectData.length; i++) {
+                        const { examSubjectChoices } = subjectData[i]
+                        this.subjectIds.push({
+                            subjectId: subjectResponse.data.data.id,
+                            everyID: examSubjectChoices.id,
+                            type: examSubjectChoices.choicesType,
+                            index: i + 1,
+                            answered: false,
+                            answer: examSubjectChoices.answer,
+                            score: examSubjectChoices.score
+                        })
+                    }
+
+                    this.query.type = parseInt(this.subjectIds[0].type)
+
+                    // 准考证号
+                    this.query.subjectId = this.subjectIds[0].everyID
+
+                    this.updateSubjectIndex()
+                    // 获取当前题目信息
+                    getSubjectAnswer({
+                        id: this.subjectIds[0].everyID,
+                    }).then(response => {
+                        if (isNotEmpty(response.data.data)) {
+                            this.setSubjectInfo(response.data.data)
+                        }
+                    }).catch(() => {
+                        messageFail(this, '获取题目失败!')
+                    })
+                }
+            }).catch(() => {
+                messageFail(this, '开始考试失败!4646549888*8*')
+            })
+        },
+        countDownE_cb: function () {
+            messageWarn(this, '考试结束')
+            this.disableSubmit = true
+        },
+        last () {
+
+            for (let i = 0; i < this.subjectIds.length; i++) {
+
+                if (this.subjectIds[i].everyID == this.query.subjectId) {
+
+                    this.subjectIds[i].answer = this.getAnswer()
+
+                    this.markAnswered(this.subjectIds[i].answer, i)
+
+                    if (i === 0) {
+                        messageSuccess(this, '已经是第一题了')
+                        break
+                    }
+
+                    let { everyID, type, index } = this.subjectIds[--i]
+
+                    this.subjectIndex = index
+
+                    this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.last, everyID, type)
+
+                    break
+
+                }
+
+            }
+
+        },
+        next () {
+
+            for (let i = 0; i < this.subjectIds.length; i++) {
+
+                if (this.subjectIds[i].everyID == this.query.subjectId) {
+
+                    this.subjectIds[i].answer = this.getAnswer()
+
+                    this.markAnswered(this.subjectIds[i].answer, i)
+
+                    if (i === this.subjectIds.length - 1) {
+                        messageSuccess(this, '已经是最后一题了')
+                        break
+                    }
+
+                    let { everyID, index } = this.subjectIds[++i]
+
+                    this.subjectIndex = index
+
+                    this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.next, everyID)
+
+                    break
+
+                }
+
+            }
+
+        },
+        // 保存当前题目,同时根据序号加载下一题
+        saveCurrentSubjectAndGetNextSubject (nextType, nextSubjectId) {
+
+
+            this.startLoading(nextType)
+
+            getSubjectAnswer({ id: nextSubjectId }).then(response => {
+
+                if (response.data.data !== null) {
+
+                    // 保存成功后更新答题卡状态
+                    const subject = response.data.data
+                    const { id, choicesType } = subject
+
+                    this.query.subjectId = id
+
+                    this.query.type = choicesType
+
+                    for (let i = 0; i < this.subjectIds.length; i++) {
+
+                        if (this.subjectIds[i].everyID == nextSubjectId) {
+
+                            subject.answer = this.subjectIds[i].answer
+
+                            break
+
+                        }
+
+                    }
+
+
+
+                    this.setSubjectInfo(subject)
+
+                    // store.dispatch('SetSubjectInfo', subject).then(() => { })
+
+                }
+                // 更新时间
+                getCurrentTime().then(response => {
+                    this.subjectStartTime = moment(response.data.data)
+                })
+                this.endLoading(nextType)
+            }).catch((error) => {
+                console.log(error)
+                messageFail(this, '获取题目失败')
+                this.endLoading(nextType)
+            })
+        },
+        markAnswered (answer, index) {
+            if (answer && answer !== null) {
+                this.subjectIds[index].answered = true
+            }
+        },
+        // 答题卡
+        answerCard () {
+            this.dialogVisible = true
+        },
+        // 跳转题目
+        toSubject (everyID, type, index) {
+
+            var ind = this.subjectIndex;
+
+            if (this.firstFlag == false) {
+                ind = this.subjectIndex;
+            } else {
+                ind = this.subjectIndex - 1;
+            }
+
+
+            this.subjectIds[ind].answer = this.getAnswer()
+
+            this.markAnswered(this.subjectIds[ind].answer, ind)
+
+            this.subjectIndex = index + 1
+            this.firstFlag = true;
+            // 保存当前题目,同时加载下一题
+            this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.next, everyID, type)
+
+            this.dialogVisible = false
+        },
+        // 提交
+        submitExam () {
+
+            var ind = this.subjectIndex;
+
+            if (this.firstFlag == false) {
+                ind = this.subjectIndex;
+            } else {
+                ind = this.subjectIndex - 1;
+            }
+
+
+            this.subjectIds[ind].answer = this.getAnswer()
+
+            this.markAnswered(this.subjectIds[ind].answer, ind)
+
+            this.$confirm('确定要提交吗?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                this.disableSubmit = true
+                this.doSubmitExam()
+            }).catch(() => {
+            })
+        },
+        doSubmitExam () {
+
+            var obj = {
+                examName: this.$route.query.examName,
+                securityName: this.userInfo.user_name,
+                securityId: this.userInfo.user_id,
+                allScore: this.$route.query.totalScore,
+                company: this.userInfo.dept_id,
+                examTime: this.$route.query.startTime,
+                papersId: this.$route.query.id,
+                examEndTime: this.$route.query.endTime,
+                examResultVOS: null
+
+            }
+
+            var arr = []
+
+
+            this.subjectIds.forEach((item) => {
+
+
+                if (item.type == 3) {
+
+                    var str = ''
+
+                    if (item.answer.length > 0) {
+                        item.answer.forEach(it => {
+
+                            if (it.value != '') {
+                                str += it.value + ','
+                            }
+
+                        })
+
+                        var a = str.substr(0, str.length - 1);
+
+
+                        arr.push(
+                            {
+                                "subjectChoicesId": item.everyID,
+                                "value": a,
+                                "grade": item.score
+                            }
+
+                        )
+                    }
+                } else {
+                    arr.push(
+                        {
+                            "subjectChoicesId": item.everyID,
+                            "value": item.answer,
+                            "grade": item.score
+                        }
+
+                    )
+                }
+
+            })
+
+            obj.examResultVOS = arr
+
+            saveAndNext(obj).then(response => {
+                messageSuccess(this, '提交成功')
+                if (response) {
+                    this.$store.commit("DEL_TAG", this.$store.state.tags.tag);
+                    this.$router.push({
+                        path: `/singleperformance/index`,
+                    });
+                }
+
+            }).catch(() => {
+                this.disableSubmit = false
+                messageFail(this, '提交题目失败')
+            })
+        },
+        // 选中选项
+        toggleOption (answer) {
+            this.answer = answer
+        },
+        // 根据题目类型返回填写的答案
+        getAnswer () {
+            const ref = this.getSubjectRef()
+            if (isNotEmpty(ref)) {
+                const answer = ref.getAnswer()
+                this.answer = answer
+                return answer
+                // {
+                //     id: answerId,
+                //     userId: this.userInfo.id,
+                //     examinationId: this.query.examinationId,
+                //     examRecordId: this.query.examRecordId,
+                //     subjectId: this.query.subjectId,
+                //     answer: answer,
+                //     type: this.query.type,
+                //     startTime: this.subjectStartTime
+                // }
+            }
+            return {}
+        },
+        // 获取题目索引
+        getSubjectIndex (targetId) {
+            for (let subject of this.subjectIds) {
+                let { subjectId, index } = subject
+                if (subjectId === targetId) {
+                    return index
+                }
+            }
+            return 1
+        },
+        // 更新题目索引
+        updateSubjectIndex () {
+            this.subjectIndex = this.getSubjectIndex(this.query.subjectId)
+        },
+        startLoading (nextType) {
+            if (nextType === nextSubjectType.next) {
+                this.loadingNext = true
+            } else if (nextType === nextSubjectType.last) {
+                this.loadingLast = true
+            } else {
+                this.loadingNext = true
+            }
+        },
+        endLoading (nextType) {
+            if (nextType === nextSubjectType.next) {
+                this.loadingNext = false
+            } else if (nextType === nextSubjectType.last) {
+                this.loadingLast = false
+            } else {
+                this.loadingNext = false
+            }
+        },
+        getSubjectRef () {
+            let ref
+
+            switch (this.query.type) {
+                case 0:
+                    ref = this.$refs.choices
+                    break
+                case 1:
+                    ref = this.$refs.multipleChoices
+
+                    break
+                case 2:
+                    ref = this.$refs.judgement
+                    break
+                case 3:
+                    ref = this.$refs.practicalOperation
+                    break
+                case 4:
+                    ref = this.$refs.shortAnswer
+                    break
+            }
+            return ref
+        },
+        setSubjectInfo (subject) {
+
+            const ref = this.getSubjectRef()
+
+            if (isNotEmpty(ref)) {
+                try {
+                    ref.setSubjectInfo(subject, this.subjectIds.length, this.subjectIndex)
+                } catch (error) {
+                    console.error(error)
+                }
+            }
+        }
+    }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style lang="scss" rel="stylesheet/scss" scoped>
+.subject-box {
+    margin-top: 50px;
+    margin-left: 20px;
+}
+.subject-box-card {
+    width: 80%;
+    margin-bottom: 30px;
+    min-height: 400px;
+}
+.subject-buttons {
+    text-align: right;
+}
+.tool-bar {
+    margin-left: 20px;
+}
+.time-remain .time {
+    display: inline-block;
+    font-size: 18px;
+    line-height: 22px;
+    color: #ff0000;
+    font-weight: 400;
+}
+
+/* 答题卡 */
+.answer-card-title {
+    font-size: 13px;
+    color: #3a3e51;
+    line-height: 17px;
+    padding: 10px 0;
+}
+.answer-card-split {
+    width: 100%;
+    border-bottom: 1px solid #e6e6e6;
+}
+.answer-card-content {
+    padding-bottom: 10px;
+    font-size: 0;
+    margin-right: -15px;
+    > button {
+        margin-top: 5px;
+    }
+}
+.answered {
+    background-color: greenyellow;
+}
+</style>
diff --git a/src/views/trainExam/data.js b/src/views/trainExam/data.js
new file mode 100644
index 0000000..fa767af
--- /dev/null
+++ b/src/views/trainExam/data.js
@@ -0,0 +1,160 @@
+export var infoColumn = [{
+        label: "申请单位名称",
+
+        prop: "deptId",
+        type: "tree",
+        dicUrl: "/api/blade-system/dept/lazy-tree-type?deptCategory=3&parentId=1418458374477549569",
+        width: 180,
+        hide: true,
+        viewDisplay: false,
+        props: {
+            label: "title",
+            value: "id"
+        },
+        rules: [{
+            required: true,
+            message: "请选择申请单位名称",
+            trigger: "blur"
+        }]
+    }, {
+        label: "申请单位名称",
+        prop: "deptName",
+        type: "select",
+        dicUrl: "/api/blade-system/dept/tree",
+        width: 180,
+        editDisplay: false,
+        addDisplay: false
+    },
+    {
+        label: "考试名称",
+        searchSpan: 5,
+        width: 180,
+        prop: "trainExamName",
+        search: true,
+    },
+
+    {
+        label: "开始时间",
+        prop: "startTime",
+        type: "datetime",
+        format: "yyyy-MM-dd HH:mm:ss",
+        valueFormat: "yyyy-MM-dd HH:mm:ss",
+        width: 180,
+        rules: [{
+            required: true,
+            message: "请选择开始时间",
+            trigger: "blur"
+        }]
+    },
+    {
+        label: "结束时间",
+        prop: "endTime",
+        type: "datetime",
+        width: 180,
+        format: "yyyy-MM-dd HH:mm:ss",
+        valueFormat: "yyyy-MM-dd HH:mm:ss",
+        rules: [{
+            required: true,
+            message: "请选择结束时间",
+            trigger: "click"
+        }]
+    },
+    {
+        label: "申请时间",
+        prop: "createTime",
+        type: "datetime",
+        width: 180,
+        editDisplay: false,
+        addDisplay: false,
+        format: "yyyy-MM-dd HH:mm:ss",
+        valueFormat: "yyyy-MM-dd HH:mm:ss",
+        rules: [{
+            required: true,
+            message: "请选择结束时间",
+            trigger: "click"
+        }]
+    },
+    {
+        label: "审核时间",
+        prop: "auditTime",
+        type: "datetime",
+        width: 180,
+        editDisplay: false,
+        addDisplay: false,
+        format: "yyyy-MM-dd HH:mm:ss",
+        valueFormat: "yyyy-MM-dd HH:mm:ss",
+        rules: [{
+            required: true,
+            message: "请选择结束时间",
+            trigger: "click"
+        }]
+    },
+    {
+        label: "审核状态",
+        search: true,
+        searchSpan: 5,
+        prop: "auditStatus",
+        slot: true,
+        editDisplay: false,
+        addDisplay: false,
+        type: "select",
+        rules: [{
+            required: true,
+            message: "请选择审核类型",
+            trigger: "blur"
+        }],
+        dicData: [{
+                label: "审核通过",
+                value: 1
+            },
+            {
+                label: "不通过",
+                value: 2
+            },
+            {
+                label: "待审核",
+                value: 3
+            }
+        ]
+    },
+    {
+        label: "审核明细",
+        editDisplay: false,
+        addDisplay: false,
+        prop: "auditDetail"
+    }
+]
+
+
+export var auditColumn = [{
+        label: "审核状态",
+        search: true,
+        searchSpan: 5,
+        span: 24,
+        prop: "auditStatus",
+        slot: true,
+        editDisplay: false,
+        addDisplay: false,
+        type: "select",
+        rules: [{
+            required: true,
+            message: "请选择审核类型",
+            trigger: "blur"
+        }],
+        dicData: [{
+                label: "审核通过",
+                value: 1
+            },
+            {
+                label: "不通过",
+                value: 2
+            }
+        ]
+    },
+    {
+        label: "审核明细",
+        span: 24,
+        type: "textarea",
+        prop: "auditDetail"
+    }
+]
\ No newline at end of file
diff --git a/src/views/trainExam/index.vue b/src/views/trainExam/index.vue
new file mode 100644
index 0000000..3f20da8
--- /dev/null
+++ b/src/views/trainExam/index.vue
@@ -0,0 +1,287 @@
+<template>
+  <basic-container class="hasButOne">
+    <avue-crud
+      :option="option"
+      :table-loading="loading"
+      :data="data"
+      :page.sync="page"
+      ref="crud"
+      @row-del="rowDel"
+      v-model="form"
+      :permission="permissionList"
+      @row-update="rowUpdate"
+      @row-save="rowSave"
+      :before-open="beforeOpen"
+      @filter="filterChange"
+      @search-change="searchChange"
+      @search-reset="searchReset"
+      @selection-change="selectionChange"
+      @current-change="currentChange"
+      @size-change="sizeChange"
+      @refresh-change="refreshChange"
+      @on-load="onLoad"
+    >
+      <template slot-scope="{ type,row }" slot="menu">
+        <el-button
+          :type="type"
+          size="small"
+          icon="el-icon-folder-checked"
+          @click="handleAudit(row)"
+          >审核
+        </el-button>
+      </template>
+    </avue-crud>
+
+    <el-dialog title="考试申请审核" 
+      :visible.sync="dialogFormVisible" 
+      modal-append-to-body='false'
+      append-to-body='true'
+      :close-on-click-model="true">
+      <avue-form ref="formAudit" v-model="Audit" :option="optionAudit" @reset-change="emptytChange" @submit="submit"></avue-form>
+    </el-dialog>
+  </basic-container>
+</template>
+
+<script>
+import { infoColumn,auditColumn } from "./data";
+import {
+  getList,
+  remove,
+  update,
+  updateAudit,
+  add,
+  getDetail,
+} from "@/api/trainExam/trainExam";
+import { mapGetters } from "vuex";
+
+export default {
+  data() {
+    return {
+      form: {},
+      Audit:{},
+      query: {},
+      loading: true,
+      deptCategory: "",
+      deptId: "",
+      userId: "",
+      dialogFormVisible: false,
+      page: {
+        pageSize: 10,
+        currentPage: 1,
+        total: 0,
+      },
+      selectionList: [],
+      optionAudit:{
+        height: "auto",
+        calcHeight: 30,
+        dialogWidth: 1000,
+        tip: false,
+        searchShow: true,
+        searchMenuSpan: 6,
+        border: false,
+        index: true,
+        stripe: true,
+        viewBtn: true,
+        addBtn: true,
+        selection: true,
+        excelBtn: false,
+        menuWidth: 230,
+        dialogClickModal: false,
+        column: auditColumn,
+      },
+      option: {
+        height: "auto",
+        calcHeight: 30,
+        dialogWidth: 1000,
+        tip: false,
+        searchShow: true,
+        searchMenuSpan: 6,
+        border: false,
+        index: true,
+        stripe: true,
+        viewBtn: true,
+        addBtn: true,
+        selection: true,
+        excelBtn: false,
+        menuWidth: 230,
+        labelWidth: "120",
+        dialogClickModal: false,
+        column: infoColumn,
+      },
+      data: [],
+    };
+  },
+  computed: {
+    ...mapGetters(["permission"]),
+    permissionList() {
+      return {
+        addBtn: this.vaildData(this.permission.notice_add, false),
+        viewBtn: this.vaildData(this.permission.notice_view, false),
+        delBtn: this.vaildData(null, false),
+        editBtn: this.vaildData(this.permission.notice_edit, false),
+      };
+    },
+    ids() {
+      let ids = [];
+      this.selectionList.forEach((ele) => {
+        ids.push(ele.id);
+      });
+      return ids.join(",");
+    },
+  },
+  mounted() {},
+  methods: {
+    rowSave(row, done, loading) {
+      row.category = 1;
+      row.deptId = this.deptId;
+      add(row).then(
+        () => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+          done();
+        },
+        (error) => {
+          window.console.log(error);
+          loading();
+        }
+      );
+    },
+    rowUpdate(row, index, done, loading) {
+      update(row).then(
+        () => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+          done();
+        },
+        (error) => {
+          window.console.log(error);
+          loading();
+        }
+      );
+    },
+    rowDel(row) {
+      this.$confirm("确定将选择数据删除?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          return remove(row.id);
+        })
+        .then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+        });
+    },
+    searchReset() {
+      this.query = {};
+      this.onLoad(this.page);
+    },
+    searchChange(params, done) {
+      this.query = params;
+      this.page.currentPage = 1;
+      this.onLoad(this.page, params);
+      done();
+    },
+    selectionChange(list) {
+      this.selectionList = list;
+    },
+    selectionClear() {
+      this.selectionList = [];
+      this.$refs.crud.toggleSelection();
+    },
+    handleDelete() {
+      if (this.selectionList.length === 0) {
+        this.$message.warning("请选择至少一条数据");
+        return;
+      }
+      this.$confirm("确定将选择数据删除?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          return remove(this.ids);
+        })
+        .then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+          this.$refs.crud.toggleSelection();
+        });
+    },
+    //审核
+    submit(row,done,loading){
+      updateAudit(row).then(
+        () => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+          done();
+        },
+        (error) => {
+          window.console.log(error);
+          loading();
+        }
+      );
+    },
+    handleAudit(row){
+        this.dialogFormVisible = true;
+        this.Audit = row;
+    },
+    beforeOpen(done, type) {
+      if (["edit", "view"].includes(type)) {
+        getDetail(this.form.id).then((res) => {
+          this.form = res.data.data;
+        });
+      }
+      done();
+    },
+    currentChange(currentPage) {
+      this.page.currentPage = currentPage;
+    },
+    sizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+    },
+    refreshChange() {
+      this.onLoad(this.page, this.query);
+    },
+    onLoad(page, params = {}) {
+      this.deptId = JSON.parse(
+        window.localStorage.getItem("saber-userInfo")
+      ).content.dept_id;
+
+      this.userId = JSON.parse(
+        window.localStorage.getItem("saber-userInfo")
+      ).content.user_id;
+
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, params).then(
+            (res) => {
+            const data = res.data.data;
+            this.page.total = data.total;
+            this.data = data.records;
+            this.loading = false;
+            this.selectionClear();
+            }
+        );
+    },
+  },
+};
+</script>
+
+<style>
+</style>
diff --git a/vue.config.js b/vue.config.js
index 7649da5..ae07d48 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -28,8 +28,8 @@
       '/api': {
         //本地服务接口地址
         // target: 'http://localhost',
-        target: 'http://192.168.0.114:81',//钟W
-        // target: 'http://192.168.0.109:81',//tangW
+        // target: 'http://192.168.0.114:81',//钟W
+        target: 'http://192.168.0.108:81',//原W
         // target: 'http://192.168.0.104:80',//唐N
         //远程演示服务地址,可用于直接启动项目
         // target: 'https://saber.bladex.vip/api',

--
Gitblit v1.9.3