chenken 6 år sedan
förälder
incheckning
12b041339b

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
     "axios": "^0.18.0",
     "element-ui": "^2.4.9",
     "moment": "^2.22.2",
+    "rasterizehtml": "^1.3.0",
     "register-service-worker": "^1.0.0",
     "vue": "^2.5.17",
     "vue-awesome": "^3.2.0",

+ 3 - 1
src/modules/marking/canvas/mark_sign.js

@@ -1,3 +1,5 @@
+import rasterizeHTML from "rasterizehtml";
+
 export function Drawing(canvas, option) {
   typeof canvas == "string" && (canvas = document.getElementById(canvas));
   if (!canvas || !canvas.getContext) {
@@ -83,7 +85,7 @@ Drawing.prototype = {
     );
   },
   removeEvent: function() {
-    this.canvas.removeEventListener("click", function(event) {}, false);
+    this.canvas.removeEventListener("click", function() {}, false);
   },
   ResetDrawAll: function() {
     this.clearDraw();

+ 25 - 30
src/modules/marking/routes/routes.js

@@ -1,17 +1,16 @@
-import Home from "../../portal/views/Home.vue";
-import marking from "../views/marking.vue";
-import mark_setting_main from "../views/mark_setting_main.vue";
-import mark_work from "../views/mark_work.vue";
-import mark_paper_check from "../views/mark_paper_check.vue";
-import mark_setting_work from "../views/mark_setting_work.vue";
-import mark_setting_fast from "../views/mark_setting_fast.vue";
-import mark_grade_main from "../views/mark_grade_main.vue";
-import view_paper from "../views/view_paper.vue";
-import mark_work_overview from "../views/mark_work_overview.vue";
-import marker from "../views/marker.vue";
-import course_detail from "../views/course_detail.vue";
-import marker_detail from "../views/marker_detail.vue";
-import batchMark from "../views/batchMark.vue";
+import Home from "../../portal/views/home/Home.vue";
+import Marking from "../views/Marking.vue";
+import MarkSettingMain from "../views/MarkSettingMain.vue";
+import MarkWork from "../views/MarkWork.vue";
+import MarkPaperCheck from "../views/MarkPaperCheck.vue";
+import MarkSettingWork from "../views/MarkSettingWork.vue";
+import MarkSettingFast from "../views/MarkSettingFast.vue";
+import MarkGradeMain from "../views/MarkGradeMain.vue";
+import ViewPaper from "../views/ViewPaper.vue";
+import MarkWorkOverview from "../views/MarkWorkOverview.vue";
+import Marker from "../views/Marker.vue";
+import CourseDetail from "../views/CourseDetail.vue";
+import MarkerDetail from "../views/MarkerDetail.vue";
 
 export default [
   {
@@ -21,57 +20,53 @@ export default [
     children: [
       {
         path: "mark_work_overview/:workId/:examId/:name", //评卷总览
-        component: mark_work_overview
+        component: MarkWorkOverview
       },
       {
         path: "course_detail/:workId/:examId/:name/:courseCode/:courseName", //课程详情
-        component: course_detail
+        component: CourseDetail
       },
       {
         path: "marker/:workId/:examId/:name", //评卷员一览
-        component: marker
+        component: Marker
       },
       {
         path: "marker_detail/:workId/:examId/:name/:markerId/:userName", //评卷员详情
-        component: marker_detail
+        component: MarkerDetail
       },
       {
         path: "mark_setting_main/:workId/:examId/:name", //评卷设置主页面
-        component: mark_setting_main
+        component: MarkSettingMain
       },
       {
         path: "mark_setting_fast/:workId/:examId/:name/:courseCode/:courseName", //评卷快速设置主页面
-        component: mark_setting_fast
+        component: MarkSettingFast
       },
       {
         path: "mark_work", //评卷工作
-        component: mark_work
+        component: MarkWork
       },
       {
         path: "mark_paper_check/:workId/:examId/:examType", //试卷检查
-        component: mark_paper_check
+        component: MarkPaperCheck
       },
       {
         path: "mark_setting_work/:type", //选择评卷工作
-        component: mark_setting_work
+        component: MarkSettingWork
       },
       {
         path: "mark_grade_main/:examId", //成绩查询
-        component: mark_grade_main
+        component: MarkGradeMain
       },
       {
         path: "view_paper/:workId/:examId/:studentPaperId/:examType", //查看原卷
-        component: view_paper
+        component: ViewPaper
       }
     ]
   },
   {
     path: "/marking/:workId/:examType", //试卷正评
-    component: marking
-  },
-  {
-    path: "/batchMark/:workId", //批量离线评分
-    component: batchMark
+    component: Marking
   },
   { path: "*", redirect: "/login" }
 ];

+ 3 - 9
src/modules/marking/views/course_detail.vue → src/modules/marking/views/CourseDetail.vue

@@ -1,4 +1,4 @@
-<style lang="css">
+<style lang="css" scoped>
 
 li {
     list-style-type: none;
@@ -125,13 +125,7 @@ li {
 </template>
 
 <script>
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  OE_API
-} from "../constants/constants";
+import { DATA_PROCESS_API } from "../constants/constants";
 import { mapState } from "vuex";
 export default {
   data() {
@@ -227,7 +221,7 @@ export default {
     back() {
       this.$router.push({
         path:
-          "/index/mark_work_overview/" +
+          "/index/MarkWorkOverview/" +
           this.workId +
           "/" +
           this.examId +

+ 3 - 11
src/modules/marking/views/mark_grade_main.vue → src/modules/marking/views/MarkGradeMain.vue

@@ -1,4 +1,4 @@
-<style lang="css">
+<style lang="css" scoped>
 
 li {
     list-style-type: none;
@@ -205,14 +205,7 @@ li {
 
 <script>
 import { mapState } from "vuex";
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  OE_API,
-  LEVEL_TYPE
-} from "../constants/constants";
+import { CORE_API, DATA_PROCESS_API, LEVEL_TYPE } from "../constants/constants";
 export default {
   data() {
     return {
@@ -297,7 +290,6 @@ export default {
         for (let item of rList) {
           if (item.id == studentpaperPk) {
             return item.value;
-            break;
           }
         }
       }
@@ -356,7 +348,7 @@ export default {
     },
     back() {
       this.$router.push({
-        path: "/index/mark_setting_work/grade"
+        path: "/index/MarkSettingWork/grade"
       });
     }
   },

+ 2 - 8
src/modules/marking/views/mark_paper_check.vue → src/modules/marking/views/MarkPaperCheck.vue

@@ -1,5 +1,3 @@
-<style lang="css"></style>
-
 <template>
   <div>
     <section class="content">
@@ -205,11 +203,8 @@
 import { mapState } from "vuex";
 import {
   CORE_API,
-  EXAM_WORK_API,
   MARKING_API,
-  DATA_PROCESS_API,
-  OE_API,
-  TAGS
+  DATA_PROCESS_API
 } from "../constants/constants";
 export default {
   data() {
@@ -324,7 +319,6 @@ export default {
     },
     //查询方法
     searchMarkPaperCheck() {
-      var orgId = this.user.rootOrgId;
       this.formSearch.workId = this.workId;
       this.formSearch.examType = this.examType;
       this.loading = true;
@@ -358,7 +352,7 @@ export default {
         var studentPaperId = row.studentPaper.id;
         console.log("studentPaperId:", studentPaperId);
         var urls =
-          "/index/view_paper/" +
+          "/index/ViewPaper/" +
           this.workId +
           "/" +
           this.examId +

+ 6 - 12
src/modules/marking/views/mark_setting_fast.vue → src/modules/marking/views/MarkSettingFast.vue

@@ -1,4 +1,4 @@
-<style lang="css">
+<style lang="css" scoped>
 
 li {
     list-style-type: none;
@@ -121,13 +121,7 @@ li {
 </template>
 
 <script>
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  OE_API
-} from "../constants/constants";
+import { MARKING_API, DATA_PROCESS_API } from "../constants/constants";
 import { mapState } from "vuex";
 export default {
   data() {
@@ -162,7 +156,7 @@ export default {
   methods: {
     selectChange(val) {
       var selectedMarker = this.selectedMarker;
-      val.forEach((element, index) => {
+      val.forEach(element => {
         selectedMarker.push(element);
         this.removeMarkerData(element.userId);
       });
@@ -181,7 +175,7 @@ export default {
         };
         this.loading = true;
         this.$http.post(DATA_PROCESS_API + "/markTasks", this.markTasks).then(
-          response => {
+          () => {
             this.$notify({
               message: "快速设置成功",
               type: "success"
@@ -190,7 +184,7 @@ export default {
             this.initMarker();
             this.searchSelectedMarker();
           },
-          response => {
+          () => {
             this.$notify({
               message: "快速设置失败",
               type: "error"
@@ -294,7 +288,7 @@ export default {
     back() {
       this.$router.push({
         path:
-          "/index/mark_setting_main/" +
+          "/index/MarkSettingMain/" +
           this.$route.params.workId +
           "/" +
           this.$route.params.examId +

+ 3 - 3
src/modules/marking/views/mark_setting_main.vue → src/modules/marking/views/MarkSettingMain.vue

@@ -1,4 +1,4 @@
-<style lang="css">
+<style lang="css" scoped>
 
 li {
     list-style-type: none;
@@ -258,7 +258,7 @@ export default {
     fastSetting(index, row) {
       this.paperId = row.pk;
       var url =
-        "/index/mark_setting_fast/" +
+        "/index/MarkSettingFast/" +
         this.$route.params.workId +
         "/" +
         this.$route.params.examId +
@@ -353,7 +353,7 @@ export default {
     },
     back() {
       this.$router.push({
-        path: "/index/mark_setting_work/setting"
+        path: "/index/MarkSettingWork/setting"
       });
     },
     //导入

+ 7 - 27
src/modules/marking/views/mark_setting_work.vue → src/modules/marking/views/MarkSettingWork.vue

@@ -1,5 +1,3 @@
-<style lang="css"></style>
-
 <template lang="html">
   <div>
     <section class="content">
@@ -130,14 +128,7 @@
 </template>
 
 <script>
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  EXAMTYPES
-} from "../constants/constants";
-import { mapActions } from "vuex";
+import { DATA_PROCESS_API } from "../constants/constants";
 import { mapState } from "vuex";
 export default {
   data() {
@@ -215,37 +206,27 @@ export default {
     },
     settingMarkWork(row) {
       var url =
-        "/index/mark_setting_main/" +
-        row.id +
-        "/" +
-        row.examId +
-        "/" +
-        row.name;
+        "/index/MarkSettingMain/" + row.id + "/" + row.examId + "/" + row.name;
       this.$router.push({
         path: url
       });
     },
     markWorkOverview(row) {
       var url =
-        "/index/mark_work_overview/" +
-        row.id +
-        "/" +
-        row.examId +
-        "/" +
-        row.name;
+        "/index/MarkWorkOverview/" + row.id + "/" + row.examId + "/" + row.name;
       this.$router.push({
         path: url
       });
     },
     marker(row) {
-      var url = "/index/marker/" + row.id + "/" + row.examId + "/" + row.name;
+      var url = "/index/Marker/" + row.id + "/" + row.examId + "/" + row.name;
       this.$router.push({
         path: url
       });
     },
     paperCheck(row) {
       var url =
-        "/index/mark_paper_check/" +
+        "/index/MarkPaperCheck/" +
         row.id +
         "/" +
         row.examId +
@@ -256,7 +237,7 @@ export default {
       });
     },
     viewGrade(row) {
-      var url = "/index/mark_grade_main/" + row.examId;
+      var url = "/index/MarkGradeMain/" + row.examId;
       this.$router.push({
         path: url
       });
@@ -264,7 +245,7 @@ export default {
     marking(row) {
       var userId = this.user.userId;
       var self = this;
-      var url = "/marking/" + row.id + "/" + row.examType;
+      var url = "/Marking/" + row.id + "/" + row.examType;
       self.$http
         .get(
           DATA_PROCESS_API + "/markTasks?workId=" + row.id + "&userId=" + userId
@@ -296,7 +277,6 @@ export default {
       return false;
     },
     isMarker() {
-      return true;
       if (sessionStorage.getItem("MarkButtonShow")) {
         return true;
       }

+ 13 - 16
src/modules/marking/views/mark_work.vue → src/modules/marking/views/MarkWork.vue

@@ -270,16 +270,14 @@ export default {
     },
     recreate(row) {
       this.loading = true;
-      this.$http
-        .put(DATA_PROCESS_API + "/markWorks/" + row.id)
-        .then(response => {
-          this.$notify({
-            message: "评卷工作保存成功",
-            type: "success"
-          });
-          this.initMarkWorkData();
-          this.loading = false;
+      this.$http.put(DATA_PROCESS_API + "/markWorks/" + row.id).then(() => {
+        this.$notify({
+          message: "评卷工作保存成功",
+          type: "success"
         });
+        this.initMarkWorkData();
+        this.loading = false;
+      });
     },
     getExamSelect() {
       var orgId = this.user.rootOrgId;
@@ -380,14 +378,14 @@ export default {
         this.loading = true;
         this.$http
           .delete(MARKING_API + "/markWorks/" + row.id)
-          .then(response => {
+          .then(() => {
             this.$notify({
               message: "删除成功",
               type: "success"
             });
             this.initMarkWorkData();
           })
-          .catch(throws => {
+          .catch(() => {
             this.$notify({
               message: "删除失败",
               type: "success"
@@ -413,13 +411,13 @@ export default {
         this.$http
           .post(DATA_PROCESS_API + "/markWorks/" + row.examId + "/publish")
           .then(
-            response => {
+            () => {
               this.$notify({
                 message: "成绩发布成功",
                 type: "success"
               });
             },
-            response => {
+            () => {
               this.$notify({
                 message: "成绩发布失败",
                 type: "error"
@@ -460,7 +458,7 @@ export default {
                 this.formMarkWork
               )
               .then(
-                response => {
+                () => {
                   this.$notify({
                     message: "评卷工作保存成功",
                     type: "success"
@@ -482,7 +480,7 @@ export default {
             this.$http
               .post(DATA_PROCESS_API + "/markWorks", this.formMarkWork)
               .then(
-                response => {
+                () => {
                   this.$notify({
                     message: "评卷工作新增成功",
                     type: "success"
@@ -558,7 +556,6 @@ export default {
     }
   },
   created() {
-    this.user.rootOrgId = 7;
     this.getUserPrivileges();
     this.initMarkWorkData();
     //this.getExamSelect();

+ 1 - 1
src/modules/marking/views/mark_work_overview.vue → src/modules/marking/views/MarkWorkOverview.vue

@@ -326,7 +326,7 @@ export default {
     },
     courseDetail(row) {
       var url =
-        "/index/course_detail/" +
+        "/index/CourseDetail/" +
         this.$route.params.workId +
         "/" +
         this.$route.params.examId +

+ 3 - 9
src/modules/marking/views/marker.vue → src/modules/marking/views/Marker.vue

@@ -1,4 +1,4 @@
-<style lang="css">
+<style lang="css" scoped>
 
 li {
     list-style-type: none;
@@ -125,13 +125,7 @@ li {
 </template>
 
 <script>
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  OE_API
-} from "../constants/constants";
+import { DATA_PROCESS_API } from "../constants/constants";
 import { mapState } from "vuex";
 export default {
   data() {
@@ -210,7 +204,7 @@ export default {
     },
     markerDetail(row) {
       var url =
-        "/index/marker_detail/" +
+        "/index/MarkerDetail/" +
         this.$route.params.workId +
         "/" +
         this.$route.params.examId +

+ 5 - 11
src/modules/marking/views/marker_detail.vue → src/modules/marking/views/MarkerDetail.vue

@@ -1,4 +1,4 @@
-<style lang="css">
+<style lang="css" scoped>
 
 li {
     list-style-type: none;
@@ -120,13 +120,7 @@ li {
 </template>
 
 <script>
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  OE_API
-} from "../constants/constants";
+import { MARKING_API } from "../constants/constants";
 import { mapState } from "vuex";
 export default {
   data() {
@@ -170,7 +164,7 @@ export default {
       this.$http
         .get(
           MARKING_API +
-            "/markCourses/all/marker/0/" +
+            "/markCourses/all/Marker/0/" +
             this.pageSize +
             "?workId=" +
             this.workId +
@@ -189,7 +183,7 @@ export default {
       this.$http
         .get(
           MARKING_API +
-            "/markCourses/all/marker/" +
+            "/markCourses/all/Marker/" +
             (this.currentPage - 1) +
             "/" +
             this.pageSize +
@@ -209,7 +203,7 @@ export default {
     back() {
       this.$router.push({
         path:
-          "/index/marker/" +
+          "/index/Marker/" +
           this.workId +
           "/" +
           this.examId +

+ 6 - 6
src/modules/marking/views/marking.vue → src/modules/marking/views/Marking.vue

@@ -332,13 +332,13 @@ li {
 </template>
 <script>
 import { mapState } from "vuex";
-import tpMain from ".//tp_main.vue";
-import tpScoreboard from ".//tp_scoreboard.vue";
+import TpMain from "./TpMain.vue";
+import TpScoreBoard from "./TpScoreBoard.vue";
 import { MARKING_API, DATA_PROCESS_API } from "../constants/constants";
 export default {
   components: {
-    tpMain,
-    tpScoreboard
+    tpMain: TpMain,
+    tpScoreboard: TpScoreBoard
   },
   data() {
     return {
@@ -405,7 +405,7 @@ export default {
         }
       }
     },
-    clearScores(val) {
+    clearScores() {
       this.signScores.splice(0, this.signScores.length);
     },
     changePaperSign(val) {
@@ -439,7 +439,7 @@ export default {
       this.problemTaskVisible = true;
     },
     backIndex() {
-      this.$router.push({ path: "/index/mark_setting_work/marking" });
+      this.$router.push({ path: "/index/MarkSettingWork/Marking" });
     },
     taskCurrentChange(val) {
       this.taskCurrentPage = val;

+ 0 - 0
src/modules/marking/views/tp_main.vue → src/modules/marking/views/TpMain.vue


+ 0 - 0
src/modules/marking/views/tp_scoreboard.vue → src/modules/marking/views/TpScoreBoard.vue


+ 2 - 8
src/modules/marking/views/view_paper.vue → src/modules/marking/views/ViewPaper.vue

@@ -9,13 +9,7 @@
 </template>
 <script>
 import { mapState } from "vuex";
-import {
-  CORE_API,
-  EXAM_WORK_API,
-  MARKING_API,
-  DATA_PROCESS_API,
-  OE_API
-} from "../constants/constants";
+import { DATA_PROCESS_API } from "../constants/constants";
 export default {
   data() {
     return {
@@ -32,7 +26,7 @@ export default {
   methods: {
     back() {
       var url =
-        "/index/mark_paper_check/" +
+        "/index/MarkPaperCheck/" +
         this.workId +
         "/" +
         this.examId +

+ 0 - 376
src/modules/marking/views/batchMark.vue

@@ -1,376 +0,0 @@
-<style lang="css"></style>
-
-<template lang="html">
-  <div>
-    <section class="content">
-      <div class="box box-info">
-        <div class="box-header with-border">
-          <h3 class="box-title">请选择评卷工作</h3>
-          <div class="box-tools pull-right">
-            <button
-              type="button"
-              class="btn btn-box-tool"
-              data-widget="collapse"
-            >
-              <i class="fa fa-minus"></i>
-            </button>
-          </div>
-        </div>
-        <div class="box-body">
-          <el-form
-            :inline="true"
-            :model="formSearch"
-            label-position="right"
-            label-width="110px"
-          >
-            <el-form-item label="课程代码" class="pull-left">
-              <el-input
-                placeholder="课程代码"
-                v-model="formSearch.courseCode"
-              ></el-input>
-            </el-form-item>
-            <el-form-item label="课程名称" class="pull-left">
-              <el-input
-                placeholder="课程名称"
-                v-model="formSearch.courseName"
-              ></el-input>
-            </el-form-item>
-            <el-form-item class="pull-right">
-              <el-button type="primary" icon="search" @click="searchMarkWork"
-                >查询</el-button
-              >
-              <el-button type="success" icon="caret-left" @click="backIndex"
-                >返回</el-button
-              >
-            </el-form-item>
-          </el-form>
-          <el-table
-            v-loading="loading"
-            element-loading-text="拼命加载中"
-            :data="tableData"
-            border
-            style="width: 100%"
-          >
-            <el-table-column label="课程名称" width="200">
-              <div>
-                <span style="margin-left: 10px">{{ row.courseName }}</span>
-              </div>
-            </el-table-column>
-            <el-table-column label="课程代码" width="250">
-              <div>
-                <span style="margin-left: 10px">{{ row.courseCode }}</span>
-              </div>
-            </el-table-column>
-            <el-table-column label="试卷数" width="200">
-              <div>
-                <span style="margin-left: 10px">{{ row.totalCount }}</span>
-              </div>
-            </el-table-column>
-            <el-table-column label="进度">
-              <div>
-                <span style="margin-left: 10px"
-                  >{{
-                    (
-                      ((row.totalCount - row.leftCount) * 100) /
-                      row.totalCount
-                    ).toFixed(2)
-                  }}%</span
-                >
-              </div>
-            </el-table-column>
-            <el-table-column label="未评数">
-              <div>
-                <span style="margin-left: 10px">{{ row.leftCount }}</span>
-              </div>
-            </el-table-column>
-            <el-table-column :context="_self" label="操作">
-              <div class="pull-left">
-                <el-button
-                  @click="batchUserPaperInfo(row);"
-                  type="success"
-                  size="mini"
-                  >批量下载</el-button
-                >
-                <el-button
-                  @click="uploadMarkScore(row);"
-                  type="info"
-                  size="mini"
-                  >上传评分</el-button
-                >
-              </div>
-            </el-table-column>
-          </el-table>
-
-          <!-- 导入弹窗 -->
-          <el-dialog
-            title="离线分数"
-            size="tiny"
-            v-model="batchScoreImportDialog"
-          >
-            <el-form>
-              <el-row>
-                <el-form-item style="margin-left:20px">
-                  <el-upload
-                    class="form_left"
-                    ref="upload"
-                    accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
-                    :action="uploadAction"
-                    :headers="uploadHeaders"
-                    :data="uploadData"
-                    :before-upload="beforeUpload"
-                    :on-progress="uploadProgress"
-                    :on-success="uploadSuccess"
-                    :on-error="uploadError"
-                    :file-list="fileList"
-                    :auto-upload="false"
-                    :multiple="false"
-                  >
-                    <el-button size="small" slot="trigger" type="primary"
-                      >选择文件</el-button
-                    >
-                    <el-button size="small" type="success" @click="submitUpload"
-                      >确认上传</el-button
-                    >
-                    <el-button size="small" type="danger" @click="removeFile"
-                      >清空文件</el-button
-                    >
-                    <!--
-                      <el-button size="small" type="info" @click="exportFile">下载模板</el-button>
-                    -->
-                    <div slot="tip" class="el-upload__tip">
-                      只能上传xlsx文件
-                    </div>
-                  </el-upload>
-                </el-form-item>
-              </el-row>
-            </el-form>
-          </el-dialog>
-
-          <!-- 导入错误信息列表 -->
-          <el-dialog title="错误提示" v-model="errDialog">
-            <div
-              class="text-danger"
-              v-for="errMessage in errMessages"
-              :key="errMessage.row"
-            >
-              第{{ errMessage.row }}行:{{ errMessage.excelErrorType }}
-            </div>
-            <span slot="footer" class="dialog-footer">
-              <el-button @click="errDialog = false;">确定</el-button>
-            </span>
-          </el-dialog>
-
-          <div class="page pull-right">
-            <el-pagination
-              background
-              @current-change="paging"
-              :current-page="currentPage"
-              :page-size="pageSize"
-              layout="total, prev, pager, next, jumper"
-              :total="total"
-            >
-            </el-pagination>
-          </div>
-        </div>
-      </div>
-    </section>
-  </div>
-</template>
-
-<script>
-import { DATA_PROCESS_API } from "../constants/constants";
-import { mapState } from "vuex";
-export default {
-  data() {
-    return {
-      formSearch: {
-        courseCode: "",
-        courseName: ""
-      },
-      tableData: [],
-      currentPage: 1,
-      pageSize: 10,
-      total: 0,
-      loading: false,
-      batchScoreImportDialog: false,
-      uploadAction: DATA_PROCESS_API + "/markTasks/batchImportScore",
-      uploadHeaders: {},
-      uploadData: { workId: this.$route.params.workId, courseCode: "" },
-      errMessages: [],
-      errDialog: false,
-      fileLoading: false,
-      fileList: []
-    };
-  },
-  methods: {
-    searchMarkWork() {
-      var self = this;
-      this.loading = true;
-      this.workId = this.$route.params.workId;
-      var userId = this.user.userId;
-      $.ajax({
-        type: "GET",
-        url:
-          DATA_PROCESS_API +
-          "/markTasks?workId=" +
-          self.workId +
-          "&userId=" +
-          userId,
-        async: false,
-        beforeSend: function(XMLHttpRequest) {
-          XMLHttpRequest.setRequestHeader("key", self.user.key);
-          XMLHttpRequest.setRequestHeader("token", self.user.token);
-        },
-        success: function(response) {
-          self.tableData = response;
-          self.total = self.tableData.length;
-          self.filterMarkWork();
-          self.paging();
-          self.loading = false;
-        }
-      });
-    },
-    filterMarkWork() {
-      var tempData = this.tableData.filter(element => {
-        var flag = true;
-        if (this.formSearch.courseCode || this.formSearch.courseName) {
-          if (this.formSearch.courseCode) {
-            flag =
-              flag && element.courseCode.includes(this.formSearch.courseCode);
-          }
-          if (this.formSearch.courseName) {
-            flag =
-              flag && element.courseName.includes(this.formSearch.courseName);
-          }
-          return flag;
-        } else {
-          return flag;
-        }
-      });
-      this.tableData = tempData;
-      this.total = tempData.length;
-    },
-    handleCurrentChange(val) {
-      this.currentPage = val;
-      this.searchMarkWork();
-    },
-    paging() {
-      var start = (this.currentPage - 1) * this.pageSize;
-      var end =
-        this.currentPage * this.pageSize < this.total
-          ? this.currentPage * this.pageSize
-          : this.total;
-      var tempData = [];
-      console.log(`当前页: ${this.currentPage},开始:${start},结束:${end}`);
-      for (let i = start; i < end; i++) {
-        tempData.push(this.tableData[i]);
-      }
-      console.log(tempData);
-      this.tableData = tempData;
-    },
-    batchUserPaperInfo(row) {
-      this.$notify({
-        message: "离线考试批量评阅",
-        type: "warning"
-      });
-    },
-    uploadMarkScore(row) {
-      this.uploadData.courseCode = row.courseCode;
-      this.batchScoreImportDialog = true;
-      this.initUpload();
-    },
-    backIndex() {
-      this.$router.push({ path: "/index/mark_setting_work/marking" });
-    },
-    //关于导入/导出
-    beforeUpload(file) {
-      console.log(file);
-    },
-    uploadProgress(event, file, fileList) {
-      console.log("uploadProgress");
-    },
-    uploadSuccess(response, file, fileList) {
-      console.log("uploadSuccess");
-      console.log(response);
-      if (!response || response.length == 0) {
-        this.$notify({
-          message: "上传成功",
-          type: "success"
-        });
-      } else {
-        this.errMessages = response;
-        this.errDialog = true;
-      }
-      this.fileLoading = false;
-      this.batchScoreImportDialog = false;
-      this.searchMarkWork();
-    },
-    uploadError(err, file, fileList) {
-      var result = err.message.match(/\{.+}/);
-      var errMessage = JSON.parse(result[0]).errorMsg;
-      this.$notify({
-        message: errMessage,
-        type: "error"
-      });
-      this.fileLoading = false;
-    },
-    initUpload() {
-      this.fileList = [];
-    },
-    checkUpload() {
-      var fileList = this.$refs.upload.uploadFiles;
-      if (fileList.length == 0) {
-        this.$notify({
-          message: "上传文件不能为空",
-          type: "error"
-        });
-        return false;
-      }
-      if (fileList.length > 1) {
-        this.$notify({
-          message: "每次只能上传一个文件",
-          type: "error"
-        });
-        return false;
-      }
-      for (let file of fileList) {
-        if (!file.name.endsWith(".xlsx")) {
-          this.$notify({
-            message: "上传文件必须为xlsx格式",
-            type: "error"
-          });
-          this.initUpload();
-          return false;
-        }
-      }
-      return true;
-    },
-    //确定上传
-    submitUpload() {
-      if (!this.checkUpload()) {
-        return false;
-      }
-      this.$refs.upload.submit();
-      this.fileLoading = true;
-    },
-    //清空文件
-    removeFile() {
-      this.$refs.upload.clearFiles();
-    },
-    //下载模板
-    exportFile() {
-      window.location.href = "/api/sms/teacher/download";
-    }
-  },
-  computed: {
-    ...mapState({ user: state => state.user })
-  },
-  created() {
-    this.uploadHeaders = {
-      key: this.user.key,
-      token: this.user.token
-    };
-    this.searchMarkWork();
-  }
-};
-</script>

+ 0 - 202
src/modules/marking/views/index.vue

@@ -1,202 +0,0 @@
-<template>
-  <div>
-    <el-container>
-      <el-header>
-        <a href="javascript:void(0)" class="logo">
-          <span class="logo-mini"><b>阅</b></span>
-          <span class="logo-lg"><b>云阅卷</b></span>
-        </a>
-        <!-- Header Navbar: style can be found in header.less -->
-        <nav class="navbar navbar-static-top">
-          <!-- Sidebar toggle button -->
-          <a
-            href="javascript:void(0)"
-            class="sidebar-toggle"
-            data-toggle="offcanvas"
-            role="button"
-          >
-            <span class="sr-only">Toggle navigation</span>
-          </a>
-          <!-- Navbar Right Menu -->
-          <div class="navbar-custom-menu">
-            <ul class="nav navbar-nav">
-              <!-- User Account: style can be found in dropdown.less -->
-              <li class="dropdown user user-menu">
-                <a
-                  href="javascript:void(0)"
-                  class="dropdown-toggle"
-                  data-toggle="dropdown"
-                >
-                  <span class="hidden-xs">
-                    <i class="fa fa-user"></i> {{ user.displayName }}
-                  </span>
-                </a>
-              </li>
-
-              <li class="user user-menu">
-                <a href="javascript:void(0)" click="backIndex">
-                  <i class="fa fa-home"></i> <span>主页面</span>
-                </a>
-              </li>
-
-              <li class="user user-menu">
-                <a href="javascript:void(0)" click="logout">
-                  <i class="fa fa-sign-out"></i> <span>退出</span>
-                </a>
-              </li>
-            </ul>
-          </div>
-        </nav>
-      </el-header>
-      <el-container>
-        <el-aside width="200px">
-          <ul class="sidebar-menu">
-            <li class="header"></li>
-            <li class="treeview active">
-              <a href="javascript:void(0)">
-                <i class="fa fa-database"></i> <span>云阅卷</span>
-                <span class="pull-right-container">
-                  <i class="fa fa-angle-left pull-right"></i>
-                </span>
-              </a>
-
-              <ul class="treeview-menu">
-                <li
-                  v-for="menu1 in menuList"
-                  v-if="menu1.parentId == null && menu1.ext1 == 'menu'"
-                  :key="menu1"
-                >
-                  <a href="#" v-if="menu1.ext2 == null">
-                    <i v-bind:class="menu1.ext3"></i>{{ menu1.name }}
-                    <span class="pull-right-container">
-                      <i class="fa fa-angle-left pull-right"></i>
-                    </span>
-                  </a>
-                  <router-link v-else :to="{ path: menu1.ext2 }"
-                    ><i v-bind:class="menu1.ext3"></i>{{ menu1.name }}
-                  </router-link>
-                  <ul class="treeview-menu">
-                    <li
-                      v-for="menu2 in menuList"
-                      v-if="menu2.parentId == menu1.id && menu2.ext1 == 'menu'"
-                      :key="menu2"
-                    >
-                      <router-link :to="{ path: menu2.ext2 }">
-                        <i v-bind:class="menu2.ext3"></i>{{ menu2.name }}
-                      </router-link>
-                    </li>
-                  </ul>
-                </li>
-              </ul>
-            </li>
-          </ul>
-        </el-aside>
-        <el-container>
-          <el-main>
-            <div class="content-wrapper">
-              <!-- Content Header (Page header) -->
-              <section class="content">
-                <div class="row"><router-view></router-view></div>
-              </section>
-              <!-- Main content -->
-            </div>
-          </el-main>
-        </el-container>
-      </el-container>
-    </el-container>
-  </div>
-</template>
-<style>
-span.logo-lg {
-  font-family: "Micrsoft YaHei";
-  font-size: 30px;
-}
-</style>
-<script>
-import { mapActions } from "vuex";
-import { mapState } from "vuex";
-import { CORE_API } from "../constants/constants";
-import { USER_SIGNOUT } from "../../portal/store/user";
-
-export default {
-  data() {
-    return {
-      menuList: []
-    };
-  },
-  components: {},
-  computed: {
-    ...mapState({ user: state => state.user })
-  },
-  methods: {
-    ...mapActions([USER_SIGNOUT]),
-    logout() {
-      var loginUrl = sessionStorage.getItem("loginUrl");
-      this.$http
-        .post(CORE_API + "/auth/logout")
-        .then(response => {
-          this.USER_SIGNOUT();
-          sessionStorage.clear();
-          if (loginUrl) {
-            window.location.href = loginUrl;
-          } else {
-            window.location.href = "about:blank";
-          }
-        })
-        .catch(response => {
-          this.USER_SIGNOUT();
-          sessionStorage.clear();
-          if (loginUrl) {
-            window.location.href = loginUrl;
-          } else {
-            window.location.href = "about:blank";
-          }
-        });
-    },
-    backIndex() {
-      var indexUrl = sessionStorage.getItem("indexUrl");
-      if (indexUrl) {
-        window.location.href = indexUrl;
-      } else {
-        window.location.href = "about:blank";
-      }
-    },
-    getUserPrivileges() {
-      var self = this;
-      var url = CORE_API + "/rolePrivilege/getUserPrivileges";
-      let config = {
-        url: url,
-        method: "post",
-        params: {
-          groupCode: "MARK_WORK_MENUS",
-          full: false
-        },
-        headers: {
-          "Content-Type": "application/x-www-form-urlencoded"
-        }
-      };
-      this.$http
-        .post(config)
-        .then(response => {
-          self.menuList = response.data;
-          for (let menu in self.menuList) {
-            let menuItem = self.menuList[menu];
-            if (menuItem.ext1 == "button") {
-              sessionStorage.setItem(menuItem.code, true);
-            }
-          }
-        })
-        .catch(thrown => {
-          self.$notify({
-            showClose: true,
-            message: thrown.message,
-            type: "error"
-          });
-        });
-    }
-  },
-  created() {
-    this.getUserPrivileges();
-  }
-};
-</script>

+ 0 - 18
src/modules/marking/views/logout.vue

@@ -1,18 +0,0 @@
-<style scoped></style>
-<template>
-  <div><a href="javascript:void(0)" @click="submit">退出</a></div>
-</template>
-<script>
-import { mapActions } from "vuex";
-import { USER_SIGNOUT } from "../../portal/store/user";
-export default {
-  methods: {
-    ...mapActions([USER_SIGNOUT]),
-    submit: function() {
-      this.USER_SIGNOUT();
-      this.$router.replace({ path: "/login" });
-      window.location.reload();
-    }
-  }
-};
-</script>

+ 9 - 3
src/modules/portal/routes/routes.js

@@ -1,5 +1,6 @@
 import Login from "../views/Login.vue";
-import Home from "../views/Home.vue";
+import Home from "../views/home/Home.vue";
+import HomeMain from "../views/home/HomeMain.vue";
 
 export default [
   {
@@ -14,8 +15,13 @@ export default [
   },
   {
     path: "/home",
-    name: "Home",
-    component: Home
+    component: Home,
+    children: [
+      {
+        path: "overview",
+        component: HomeMain
+      }
+    ]
   }
   // {
   //   path: "/about",

+ 1 - 1
src/modules/portal/views/Login.vue

@@ -127,7 +127,7 @@ export default {
           user.loginUrl = "http://" + window.location.host + "/#/login";
           user.indexUrl = "http://" + window.location.host + "/#/index";
           window.name = JSON.stringify(user);
-          this.$router.replace({ path: "/home" });
+          this.$router.replace({ path: "/home/overview" });
           this.$notify({
             message: "登录成功",
             type: "success"

+ 8 - 119
src/modules/portal/views/Home.vue → src/modules/portal/views/home/Home.vue

@@ -20,92 +20,13 @@
     </el-header>
 
     <el-container>
-      <el-aside width="200px">
-        <el-menu
-          default-active="2"
-          class="el-menu-vertical-demo"
-          background-color="#545c64"
-          text-color="#fff"
-          active-text-color="#ffd04b"
-          style="height: 100%"
-        >
-          <el-submenu index="1">
-            <template slot="title">
-              <i class="el-icon-location"></i> <span>基础信息</span>
-            </template>
-            <el-menu-item-group>
-              <template slot="title"
-                >分组一</template
-              >
-              <el-menu-item index="1-1">选项1</el-menu-item>
-              <el-menu-item index="1-2">选项2</el-menu-item>
-            </el-menu-item-group>
-            <el-menu-item-group title="分组2">
-              <el-menu-item index="1-3">选项3</el-menu-item>
-            </el-menu-item-group>
-            <el-submenu index="1-4">
-              <template slot="title"
-                >选项4</template
-              >
-              <el-menu-item index="1-4-1">选项1</el-menu-item>
-            </el-submenu>
-          </el-submenu>
-          <el-menu-item index="2">
-            <i class="el-icon-menu"></i> <span slot="title">考务</span>
-          </el-menu-item>
-          <el-menu-item index="3" disabled>
-            <i class="el-icon-document"></i> <span slot="title">题库</span>
-          </el-menu-item>
-          <el-menu-item index="4">
-            <i class="el-icon-setting"></i> <span slot="title">网考</span>
-          </el-menu-item>
-          <el-menu-item index="5">
-            <i class="el-icon-setting"></i> <span slot="title">阅卷</span>
-          </el-menu-item>
-          <el-menu-item index="6">
-            <v-icon name="print" class="el-icon-" />
-            <span slot="title">印刷</span>
-          </el-menu-item>
-          <el-menu-item index="7">
-            <v-icon name="flag" class="el-icon-" />
-            <span slot="title">报表</span>
-          </el-menu-item>
-        </el-menu>
-      </el-aside>
+      <HomeSide />
       <el-container>
-        <el-main>
-          <div class="content-wrapper">
-            <section class="content">
-              <div class="row"><router-view></router-view></div>
-            </section>
-          </div>
-        </el-main>
+        <router-view></router-view>
         <el-footer>&copy; 启明泰和 2018</el-footer>
       </el-container>
     </el-container>
 
-    <!--
-      <div class="main-content">
-        <section class="content">
-          <div class="row">
-            <ul class="center">
-              <li
-                class="menu"
-                v-for="menu in menuList.filter(m => m.parentId === null)"
-                :key="menu.id"
-              >
-                <a :href="'/' + menu.code.toLowerCase()">{{ menu.name }}</a>
-                <div v-if="menu.code === 'BASIC'">
-                  <a href=""></a>
-                  得到菜单权限
-                </div>
-              </li>
-            </ul>
-          </div>
-        </section>
-      </div>
-    -->
-
     <!-- 添加用户信息弹出框 -->
     <el-dialog title="个人信息" :visible.sync="userDialog">
       <el-tabs>
@@ -173,10 +94,12 @@
 
 <script>
 import { mapActions, mapState } from "vuex";
-import { USER_SIGNOUT } from "../store/user";
-import { core_api } from "../constants/constants";
+import { USER_SIGNOUT } from "../../store/user";
+import { core_api } from "../../constants/constants";
+import HomeSide from "./HomeSide.vue";
 
 export default {
+  name: "Home",
   data() {
     var validatePass = (rule, value, callback) => {
       if (value === "") {
@@ -198,7 +121,6 @@ export default {
       }
     };
     return {
-      menuList: [],
       userDialog: false,
       passForm: { pass: "", checkPass: "" },
       passRules: {
@@ -207,7 +129,7 @@ export default {
       }
     };
   },
-  components: {},
+  components: { HomeSide },
   computed: {
     ...mapState({ user: state => state.user })
   },
@@ -285,33 +207,11 @@ export default {
           });
         });
     }
-  },
-  created() {
-    var url = core_api + "/rolePrivilege/getUserPrivileges";
-    const params = new URLSearchParams();
-    params.append("groupCode", "PORTAL_MENUS");
-    params.append("full", false);
-    this.$http
-      .post(url, params, {
-        headers: { "content-type": "application/x-www-form-urlencoded" }
-      })
-      .then(response => {
-        this.menuList = response.data;
-      })
-      .catch(response => {
-        if (response.status == 500) {
-          this.$notify({
-            showClose: true,
-            message: response.data.desc,
-            type: "error"
-          });
-        }
-      });
   }
 };
 </script>
 
-<style lang="css">
+<style lang="css" scoped>
 .fr {
   float: right;
 }
@@ -321,24 +221,13 @@ export default {
   text-align: center;
   line-height: 60px;
 }
-.el-menu-vertical-demo {
-  height: calc(100vh - 60px);
-}
 .el-aside {
   background-color: #D3DCE6;
   color: #333;
   line-height: 200px;
 }
 
-.el-main {
-  background-color: #E9EEF3;
-  color: #333;
-}
-
 body > .el-container {
   margin-bottom: 40px;
 }
-body {
-  margin: 0
-}
 </style>

+ 60 - 0
src/modules/portal/views/home/HomeMain.vue

@@ -0,0 +1,60 @@
+<template>
+  <el-main>
+    <div class="main-content">
+      <section class="content">
+        <div class="row">
+          <ul class="center">
+            <li
+              class="menu"
+              v-for="menu in menuList.filter(m => m.parentId === null)"
+              :key="menu.id"
+            >
+              <a :href="'/' + menu.ext4">{{ menu.name }}</a>
+            </li>
+          </ul>
+        </div>
+      </section>
+    </div>
+  </el-main>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { core_api } from "../../constants/constants";
+
+export default {
+  name: "HomeMain",
+  data() {
+    return {
+      menuList: []
+    };
+  },
+  components: {},
+  computed: {
+    ...mapState({ user: state => state.user })
+  },
+  methods: {},
+  created() {
+    var url = core_api + "/rolePrivilege/getUserPrivileges";
+    const params = new URLSearchParams();
+    params.append("groupCode", "PORTAL_MENUS");
+    params.append("full", false);
+    this.$http
+      .post(url, params, {
+        headers: { "content-type": "application/x-www-form-urlencoded" }
+      })
+      .then(response => {
+        this.menuList = response.data;
+      });
+  }
+};
+</script>
+
+<style lang="css" scoped>
+.el-main {
+  background-color: #E9EEF3;
+  color: #333;
+  text-align: center;
+  line-height: 60px;
+}
+</style>

+ 204 - 0
src/modules/portal/views/home/HomeSide.vue

@@ -0,0 +1,204 @@
+<template>
+  <el-aside width="200px">
+    <el-menu
+      default-active="2"
+      class="el-menu-vertical-demo"
+      background-color="#545c64"
+      text-color="#fff"
+      active-text-color="#ffd04b"
+    >
+      <el-submenu index="1">
+        <template slot="title">
+          <i class="el-icon-location"></i> <span>基础信息</span>
+        </template>
+        <el-menu-item-group>
+          <template slot="title"
+            >分组一</template
+          >
+          <el-menu-item index="1-1">选项1</el-menu-item>
+          <el-menu-item index="1-2">选项2</el-menu-item>
+        </el-menu-item-group>
+        <el-menu-item-group title="分组2">
+          <el-menu-item index="1-3">选项3</el-menu-item>
+        </el-menu-item-group>
+        <el-submenu index="1-4">
+          <template slot="title"
+            >选项4</template
+          >
+          <el-menu-item index="1-4-1">选项1</el-menu-item>
+        </el-submenu>
+      </el-submenu>
+      <el-menu-item index="2">
+        <i class="el-icon-menu"></i> <span slot="title">考务</span>
+      </el-menu-item>
+      <el-menu-item index="3">
+        <i class="el-icon-document"></i> <span slot="title">题库</span>
+      </el-menu-item>
+      <el-menu-item index="4">
+        <i class="el-icon-setting"></i> <span slot="title">网考</span>
+      </el-menu-item>
+      <el-menu-item index="5">
+        <i class="el-icon-setting"></i> <span slot="title">阅卷</span>
+      </el-menu-item>
+      <el-menu-item index="6">
+        <v-icon name="print" class="el-icon-" />
+        <span slot="title">印刷</span>
+      </el-menu-item>
+      <el-menu-item index="7">
+        <v-icon name="flag" class="el-icon-" />
+        <span slot="title">报表</span>
+      </el-menu-item>
+    </el-menu>
+  </el-aside>
+</template>
+
+<script>
+import { mapActions, mapState } from "vuex";
+import { USER_SIGNOUT } from "../../store/user";
+import { core_api } from "../../constants/constants";
+
+export default {
+  name: "HomeSide",
+  data() {
+    var validatePass = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("请输入密码"));
+      } else {
+        if (this.passForm.checkPass !== "") {
+          this.$refs.passForm.validateField("checkPass");
+        }
+        callback();
+      }
+    };
+    var validatePass2 = (rule, value, callback) => {
+      if (value === "") {
+        callback(new Error("请输入确认密码"));
+      } else if (value !== this.passForm.pass) {
+        callback(new Error("两次输入密码不一致!"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      menuList: [],
+      userDialog: false,
+      passForm: { pass: "", checkPass: "" },
+      passRules: {
+        pass: [{ validator: validatePass, trigger: "blur" }],
+        checkPass: [{ validator: validatePass2, trigger: "blur" }]
+      }
+    };
+  },
+  computed: {
+    ...mapState({ user: state => state.user })
+  },
+  methods: {
+    ...mapActions([USER_SIGNOUT]),
+    openUserDialog() {
+      this.passForm = { pass: "", checkPass: "" };
+      this.userDialog = true;
+    },
+    //保存密码
+    submitForm() {
+      this.$refs.passForm.validate(valid => {
+        if (valid) {
+          var userId = this.user.userId;
+          var password = encodeURIComponent(this.passForm.pass);
+          var url =
+            core_api +
+            "/user/password?userId=" +
+            userId +
+            "&password=" +
+            password;
+          this.$http.put(url).then(() => {
+            this.$notify({
+              type: "success",
+              message: "修改密码成功!"
+            });
+            this.resetForm();
+            this.userDialog = false;
+          });
+        } else {
+          console.log("error submit!");
+          return false;
+        }
+      });
+    },
+    //重置
+    resetForm() {
+      this.$refs.passForm.resetFields();
+    },
+    isSuperAdmin() {
+      if (!this.user.roleList) {
+        return false;
+      }
+      for (let role of this.user.roleList) {
+        if (role.roleCode == "SUPER_ADMIN") {
+          return true;
+        }
+      }
+      return false;
+    },
+    logout() {
+      this.$http
+        .post(core_api + "/auth/logout")
+        .then(() => {
+          const orgId = this.user.rootOrgId;
+          this.USER_SIGNOUT();
+          window.name = "";
+          this.$router.replace({
+            path: "/login" + "?orgId=" + orgId
+          });
+        })
+        .catch(response => {
+          const orgId = this.user.rootOrgId;
+          if (response.status == 500) {
+            this.$notify({
+              showClose: true,
+              message: response.data.desc,
+              type: "error"
+            });
+          }
+          this.USER_SIGNOUT();
+          window.name = "";
+          this.$router.replace({
+            path: "/login" + "?orgId=" + orgId
+          });
+        });
+    }
+  },
+  created() {
+    var url = core_api + "/rolePrivilege/getUserPrivileges";
+    const params = new URLSearchParams();
+    params.append("groupCode", "PORTAL_MENUS");
+    params.append("full", false);
+    this.$http
+      .post(url, params, {
+        headers: { "content-type": "application/x-www-form-urlencoded" }
+      })
+      .then(response => {
+        this.menuList = response.data;
+      })
+      .catch(response => {
+        if (response.status == 500) {
+          this.$notify({
+            showClose: true,
+            message: response.data.desc,
+            type: "error"
+          });
+        }
+      });
+  }
+};
+</script>
+
+<style lang="css" scoped>
+.el-menu-vertical-demo {
+  height: calc(100vh - 60px);
+}
+.el-aside {
+  background-color: #D3DCE6;
+  color: #333;
+  line-height: 200px;
+}
+</style>

+ 88 - 0
src/modules/questions/constants/constants.js

@@ -0,0 +1,88 @@
+import Vue from "vue";
+export const CORE_API = "/api/ecs_core"; //基础信息API
+export const EXAM_WORK_API = "/api/ecs_exam_work"; //考务信息API
+export const Q_API = "/api/ecs_ques"; //题库API
+export const LEVEL_TYPE = [
+  { label: "专升本", value: "ZSB" },
+  { label: "高起专", value: "GQZ" },
+  { label: "高起本", value: "GQB" },
+  { label: "不限", value: "ALL" }
+];
+export const questionTypes = [
+  { value: "SINGLE_ANSWER_QUESTION", label: "单选" },
+  { value: "MULTIPLE_ANSWER_QUESTION", label: "多选" },
+  { value: "BOOL_ANSWER_QUESTION", label: "判断" },
+  { value: "FILL_BLANK_QUESTION", label: "填空" },
+  { value: "TEXT_ANSWER_QUESTION", label: "问答" },
+  { value: "NESTED_ANSWER_QUESTION", label: "套题" }
+];
+//option字母顺序过滤器
+Vue.filter("optionOrderWordFilter", function(value) {
+  return String.fromCharCode(65 + value);
+});
+//题型过滤器
+Vue.filter("questionType", function(value) {
+  for (let questionType of questionTypes) {
+    if (questionType.value === value) {
+      return questionType.label;
+    }
+  }
+});
+
+export const examTypes = [
+  { value: "TRADITION", label: "传统考试" },
+  { value: "ONLINE", label: "网络考试" },
+  { value: "PRACTICE", label: "在线练习" }
+];
+
+export const exportTypes = [
+  { value: "ONLINE", label: "机考" },
+  { value: "NORMAL", label: "普通" }
+];
+
+Vue.filter("examTypesFilter", function(value) {
+  for (let item of examTypes) {
+    if (item.value === value) {
+      return item.label;
+    }
+  }
+});
+Vue.filter("exportTypesFilter", function(value) {
+  for (let item of exportTypes) {
+    if (item.value === value) {
+      return item.label;
+    }
+  }
+});
+
+// Vue.directive("questionAudio", {
+//   bind: function(el, binding, vnode) {
+//     addAudio(el, binding, vnode);
+//   },
+//   inserted: function(el, binding, vnode) {},
+//   update: function(el, binding, vnode) {},
+//   componentUpdated: function(el, binding, vnode) {},
+//   unbind: function(el, binding, vnode) {}
+// });
+
+// function addAudio(el, binding, vnode) {
+//   let $el = $(el);
+//   if (vnode.data.attrs.hasAudio) {
+//     $el.find("p>a").each(function() {
+//       var questionAudioId = $(this).attr("id");
+//       if (questionAudioId) {
+//         vnode.context.$http
+//           .get(Q_API + "/questionAudio/" + questionAudioId)
+//           .then(response => {
+//             if (response && response.body) {
+//               let audioFlag =
+//                 '<audio controls><source src="http://exam-cloud-test.b0.upaiyun.com' +
+//                 response.body.fileUrl +
+//                 '" type="audio/mpeg"></audio>';
+//               $(this).append(audioFlag);
+//             }
+//           });
+//       }
+//     });
+//   }
+// }

+ 16 - 0
src/modules/questions/routes/routes.js

@@ -0,0 +1,16 @@
+import Home from "../../portal/views/home/Home.vue";
+import PaperStructure from "../views/PaperStructure.vue";
+
+export default [
+  {
+    path: "/questions", //首页
+    meta: { auth: false },
+    component: Home,
+    children: [
+      {
+        path: "paper_structure/:isClear", //试卷结构
+        component: PaperStructure
+      }
+    ]
+  }
+];

+ 396 - 0
src/modules/questions/views/PaperStructure.vue

@@ -0,0 +1,396 @@
+<style>
+.form_width {
+  width: 180px;
+}
+</style>
+<template>
+  <div>
+    <section class="content">
+      <div>
+        <!-- 头信息 -->
+        <div><h3 class="box-title">精确结构预设</h3></div>
+        <!-- 正文信息 -->
+        <div class="box-body">
+          <el-form
+            :inline="true"
+            :model="formSearch"
+            label-position="right"
+            label-width="90px"
+          >
+            <el-row :gutter="10">
+              <el-col :xs="7" :sm="7" :md="7" :lg="8">
+                <el-form-item label="结构名称" class="pull-left">
+                  <el-input
+                    placeholder="请输入结构名称"
+                    v-model="formSearch.name"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :xs="7" :sm="7" :md="7" :lg="8">
+                <el-form-item label="创建人" class="pull-left">
+                  <el-input
+                    placeholder="请输入创建人"
+                    v-model="formSearch.creator"
+                  ></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :xs="7" :sm="7" :md="7" :lg="8">
+                <el-form-item label="制定课程">
+                  <el-select
+                    v-model="formSearch.courseNo"
+                    class="form_width"
+                    filterable
+                    :remote-method="getCourses"
+                    remote
+                    clearable
+                    placeholder="请选择"
+                  >
+                    <el-option label="请选择" value="ALL" key="ALL"></el-option>
+                    <el-option label="公用" value="" key=""></el-option>
+                    <el-option
+                      v-for="item in courseInfoSelect"
+                      :label="item.courseInfo"
+                      :value="item.courseNo"
+                      :key="item.courseNo"
+                    >
+                    </el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-form-item class="pull-right buttonframe">
+                <el-button
+                  size="small"
+                  style="margin-left:90px;"
+                  type="primary"
+                  icon="search"
+                  @click="searchPaperStructs"
+                  >查询</el-button
+                >
+                <el-button
+                  size="small"
+                  type="primary"
+                  icon="plus"
+                  @click="addPaperStruct"
+                  >新增</el-button
+                >
+                <el-button size="small" type="danger" @click="deletePapers"
+                  ><i class="el-icon-delete"></i> 删除</el-button
+                >
+              </el-form-item>
+            </el-row>
+          </el-form>
+
+          <!-- 页面列表 -->
+          <el-table
+            :data="tableData"
+            v-loading="loading"
+            element-loading-text="拼命加载中"
+            border
+            style="width: 100%;text-align:center;"
+            @selection-change="selectionChange"
+          >
+            <el-table-column type="selection"> </el-table-column>
+            <el-table-column label="预设精确结构名称" width="200">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.name }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="关联课程" width="180">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.courseName }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="课程代码" width="110">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.courseNo }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="类型" width="110">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ getType(scope.row.courseNo) }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="大题数" width="80">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.detailCount }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="小题数" width="80">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.detailUnitCount }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="总分" width="70">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.totalScore }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="创建人" width="110">
+              <template slot-scope="scope">
+                <div>
+                  <span>{{ scope.row.creator }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column :context="_self" label="操作" width="140">
+              <div>
+                <el-button
+                  size="mini"
+                  type="info"
+                  @click="editPaperStruct(row);"
+                >
+                  修改
+                </el-button>
+                <el-button
+                  size="mini"
+                  type="danger"
+                  @click="deletePaper($index, row);"
+                >
+                  删除
+                </el-button>
+              </div>
+            </el-table-column>
+          </el-table>
+          <div class="page pull-right">
+            <el-pagination
+              @current-change="handleCurrentChange"
+              :current-page="currentPage"
+              :page-size="pageSize"
+              layout="total, prev, pager, next, jumper"
+              :total="total"
+            >
+            </el-pagination>
+          </div>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<script>
+import { CORE_API, Q_API } from "../constants/constants";
+export default {
+  data() {
+    return {
+      courseLoading: false,
+      formSearch: {
+        name: "",
+        creator: "",
+        courseNo: "ALL",
+        type: "EXACT"
+      },
+      paperStructId: "",
+      loading: false,
+      tableData: [],
+      selectedList: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 10,
+      courseList: [],
+      isClear: 0
+    };
+  },
+  methods: {
+    //查询
+    searchPaperStructs() {
+      this.loading = true;
+      var url =
+        Q_API + "/paperStruct/" + this.currentPage + "/" + this.pageSize;
+      this.$http.get(url, { params: this.formSearch }).then(response => {
+        console.log("response:", response);
+        this.tableData = response.data.content;
+        this.total = response.data.totalElements;
+      });
+      this.loading = false;
+    },
+    //全选
+    selectionChange(val) {
+      this.selectedList = [];
+      var selectedList = this.selectedList;
+      val.forEach(element => {
+        selectedList.push(element.id);
+      });
+      this.selectedList = selectedList;
+    },
+    editPaperStruct(row) {
+      sessionStorage.setItem("paper_stucture", JSON.stringify(this.formSearch));
+      sessionStorage.setItem("paper_stucture_currentPage", this.currentPage);
+      sessionStorage.setItem("paperStruct", JSON.stringify(row));
+      this.$router.push({
+        path: "/index/insert_paper_structure/" + row.id
+      });
+    },
+    //删除单条数据
+    deletePaper(index, row) {
+      this.$confirm("是否删除试卷结构?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        var url = Q_API + "/paperStruct/" + row.id;
+        this.loading = true;
+        this.$http.delete(url).then(
+          () => {
+            this.$notify({
+              type: "success",
+              message: "删除成功!"
+            });
+            this.searchPaperStructs();
+          },
+          () => {
+            this.$notify({
+              type: "error",
+              message: "删除失败!"
+            });
+          }
+        );
+      });
+      this.loading = false;
+    },
+    //删除多条数据
+    deletePapers() {
+      var selectedList = this.selectedList;
+      if (selectedList.length === 0) {
+        this.$notify({
+          type: "error",
+          message: "请选择要删除的试卷结构"
+        });
+      } else {
+        this.$confirm("是否删除试卷结构?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "error"
+        }).then(() => {
+          this.loading = true;
+          var url = Q_API + "/paperStruct/" + this.selectedIds;
+          this.$http
+            .delete(url)
+            .then(() => {
+              this.$notify({
+                type: "success",
+                message: "删除成功!"
+              });
+              this.searchPaperStructs();
+              this.selectedList = [];
+            })
+            .catch(() => {
+              this.$notify({
+                type: "error",
+                message: "删除失败!"
+              });
+              this.selectedList = [];
+            });
+        });
+      }
+      this.loading = false;
+    },
+
+    //新增
+    addPaperStruct() {
+      sessionStorage.setItem("paper_stucture", JSON.stringify(this.formSearch));
+      sessionStorage.setItem("paper_stucture_currentPage", this.currentPage);
+      this.$router.push({
+        path: "/index/insert_paper_structure/add"
+      });
+    },
+
+    //分页跳转
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.searchPaperStructs();
+    },
+
+    removeItem() {
+      sessionStorage.removeItem("paperStruct");
+    },
+    //查询所有课程
+    getCourses(query) {
+      console.log("query:", query);
+      query = query.trim();
+      if (query) {
+        if (!(query.indexOf("(") > -1 && query.indexOf(")") > -1)) {
+          this.courseLoading = true;
+          this.$http
+            .get(CORE_API + "/course/query?name=" + query + "&enable=true")
+            .then(response => {
+              this.courseList = response.body;
+              this.courseLoading = false;
+            });
+        }
+      } else {
+        this.courseList = [];
+      }
+    },
+    getType(val) {
+      if (val == "ENSEMBLE") {
+        return "宏观结构";
+      }
+      return "微观结构";
+    }
+  },
+  computed: {
+    selectedIds() {
+      var selectedIdsStr = "";
+      for (let id of this.selectedList) {
+        if (!selectedIdsStr) {
+          selectedIdsStr += id;
+        } else {
+          selectedIdsStr += "," + id;
+        }
+      }
+      return selectedIdsStr;
+    },
+    courseInfoSelect() {
+      var courseList = [];
+      for (let course of this.courseList) {
+        var courseInfo = course.name + "(" + course.code + ")";
+        var courseNo = course.code;
+        courseList.push({ courseNo: courseNo, courseInfo: courseInfo });
+      }
+      return courseList;
+    }
+  },
+  created() {
+    this.isClear = this.$route.params.isClear;
+    if (this.isClear == 0 || !this.isClear) {
+      sessionStorage.removeItem("paper_stucture");
+      sessionStorage.removeItem("paper_stucture_currentPage");
+    } else {
+      this.formSearch = JSON.parse(sessionStorage.getItem("paper_stucture"));
+      this.currentPage = parseInt(
+        sessionStorage.getItem("paper_stucture_currentPage")
+      );
+      if (!this.formSearch) {
+        this.formSearch = {
+          name: "",
+          creator: "",
+          courseNo: "ALL",
+          type: "EXACT"
+        };
+      }
+      if (!this.currentPage) {
+        this.currentPage = 1;
+      }
+    }
+    this.removeItem();
+    this.searchPaperStructs();
+    //this.getCourses();
+  }
+};
+</script>

+ 2 - 1
src/router.js

@@ -2,13 +2,14 @@ import Vue from "vue";
 import Router from "vue-router";
 import PortalRoutes from "./modules/portal/routes/routes";
 import MarklRoutes from "./modules/marking/routes/routes";
+import QuestionsRoutes from "./modules/questions/routes/routes";
 import OeRoutes from "./modules/oe/routes/routes";
 
 Vue.use(Router);
 
 let router = new Router({
   mode: "history",
-  routes: [...PortalRoutes, ...MarklRoutes, ...OeRoutes]
+  routes: [...PortalRoutes, ...MarklRoutes, ...QuestionsRoutes, ...OeRoutes]
 });
 
 // router.beforeEach((to, from, next) => {

+ 4 - 0
src/styles/global.css

@@ -1,3 +1,7 @@
+body {
+  margin: 0;
+}
+
 .qm-primary-text {
   font-size: 14px;
   font-weight: normal;

+ 34 - 1
yarn.lock

@@ -2615,6 +2615,11 @@ css-declaration-sorter@^4.0.1:
     postcss "^7.0.1"
     timsort "^0.3.0"
 
+css-font-face-src@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/css-font-face-src/-/css-font-face-src-1.0.0.tgz#a8c6307d48d9afc84a404082cb1776cd458864b1"
+  integrity sha1-qMYwfUjZr8hKQECCyxd2zUWIZLE=
+
 css-loader@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.1.tgz#6885bb5233b35ec47b006057da01cc640b6b79fe"
@@ -4757,6 +4762,14 @@ ini@^1.3.4, ini@~1.3.0:
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
   integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
 
+inlineresources@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/inlineresources/-/inlineresources-1.0.0.tgz#633e7d3f863a55935c110027a3541d3b56cdda08"
+  integrity sha512-lhldtEpNb9dLnuz8zkyrl6VlNweu0zb9XP1GZ6EnLb3YNxATAjoNdrYxsBiYVVKf1uQmiIOHckcH/NPVlgtRMQ==
+  dependencies:
+    css-font-face-src "^1.0.0"
+    url "~0.11.0"
+
 inquirer@^3.0.6:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
@@ -7777,6 +7790,16 @@ range-parser@^1.0.3, range-parser@~1.2.0:
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
   integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
 
+rasterizehtml@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/rasterizehtml/-/rasterizehtml-1.3.0.tgz#65bd3dc892f880b713a5f29b063203eaec372e73"
+  integrity sha512-d2kM6o82UgdozhniyPy3Af9unN1INBd4Rp7Apu2wmblwFOlGxa9VKp0UAuvL/BTQI3/R+bSWJyNkdpN0FJ4VwA==
+  dependencies:
+    inlineresources "^1.0.0"
+    sane-domparser-error "~0.2.0"
+    url "~0.11.0"
+    xmlserializer "~0.6.0"
+
 raw-body@2.3.3:
   version "2.3.3"
   resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
@@ -8214,6 +8237,11 @@ safe-regex@^1.1.0:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
+sane-domparser-error@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/sane-domparser-error/-/sane-domparser-error-0.2.0.tgz#adec5360c8a394526c204e61b00ea125f7b2b01f"
+  integrity sha1-rexTYMijlFJsIE5hsA6hJfeysB8=
+
 sane@^2.0.0:
   version "2.5.2"
   resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
@@ -9360,7 +9388,7 @@ url-parse@^1.4.3:
     querystringify "^2.0.0"
     requires-port "^1.0.0"
 
-url@^0.11.0:
+url@^0.11.0, url@~0.11.0:
   version "0.11.0"
   resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
   integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
@@ -9988,6 +10016,11 @@ xml-name-validator@^3.0.0:
   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
   integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
 
+xmlserializer@~0.6.0:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/xmlserializer/-/xmlserializer-0.6.1.tgz#14099f60272e16cb608be3758992f998070cc29a"
+  integrity sha512-FNb0eEqqUUbnuvxuHqNuKH8qCGKqxu+558Zi8UzOoQk8Z9LdvpONK+v7m3gpKVHrk5Aq+0nNLsKxu/6OYh7Umw==
+
 xregexp@4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"