Pārlūkot izejas kodu

Merge branch 'master' of http://git.qmth.com.cn/ExamCloud-3/examcloud-web-admin

chenken 6 gadi atpakaļ
vecāks
revīzija
8a3ce90c50

+ 1 - 1
.browserslistrc

@@ -1,3 +1,3 @@
 > 1%
 last 2 versions
-not ie <= 8
+not ie <= 10

+ 1 - 1
src/App.vue

@@ -4,7 +4,7 @@
 
 <script>
 export default {
-  name: "app"
+  name: "App"
 };
 </script>
 

+ 1 - 0
src/filters/filters.js

@@ -1 +1,2 @@
 import "../modules/questions/filters/filters";
+import "../modules/marking/filters/filters";

+ 2 - 7
src/modules/basic/view/app_list.vue

@@ -1,13 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div class="box-header with-border">
-          <h3 class="box-title">鉴权管理 > 应用列表</h3>
-        </div>
-
-        <!-- 正文信息 -->
         <div class="box-body">
           <el-table
             :data="appList"
@@ -32,6 +26,7 @@ import { USER_SIGNIN } from "../../portal/store/user";
 import { CORE_API } from "@/constants/constants.js";
 
 export default {
+  name: "AppList",
   data() {
     return {
       appList: []

+ 2 - 9
src/modules/basic/view/campus.vue

@@ -1,15 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div
-          class="box-header with-border"
-          style="background-color:#D3DCE6;margin-bottom:20px;"
-        >
-          <h3 class="box-title">学习中心</h3>
-        </div>
-        <!-- 正文信息 -->
         <div
           class="box-body"
           v-loading.body="fileLoading"
@@ -294,6 +286,7 @@ import { CORE_API } from "@/constants/constants.js";
 import { mapState } from "vuex";
 
 export default {
+  name: "Campus",
   data() {
     return {
       isSuperAdmin: false,

+ 2 - 5
src/modules/basic/view/course.vue

@@ -1,11 +1,7 @@
 <template>
   <div>
-    <section class="content">
+    <section class="content" style="margin-top: 20px">
       <div class="box box-info">
-        <div class="box-header with-border">
-          <h3 class="box-title">课程列表</h3>
-        </div>
-
         <div
           v-loading.body="fileLoading"
           element-loading-text="课程上传中,请稍后..."
@@ -440,6 +436,7 @@ import { ENABLE_TYPE, LEVEL_TYPE } from "../constants/constants.js";
 import { mapState } from "vuex";
 
 export default {
+  name: "Course",
   data() {
     return {
       specialtyLoading4Search: false,

+ 2 - 9
src/modules/basic/view/exam_site.vue

@@ -1,15 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div
-          class="box-header with-border"
-          style="background-color:#D3DCE6;margin-bottom:20px;"
-        >
-          <h3 class="box-title">考点列表</h3>
-        </div>
-        <!-- 正文信息 -->
         <div class="box-body">
           <!-- 表单 -->
           <el-form
@@ -197,6 +189,7 @@ import { CORE_API } from "@/constants/constants.js";
 import { mapState } from "vuex";
 
 export default {
+  name: "ExamSite",
   data() {
     return {
       orgId: null,

+ 2 - 6
src/modules/basic/view/privilege_group_list.vue

@@ -1,12 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <div class="box-header with-border">
-          <h3 class="box-title">鉴权管理 &gt; 权限组管理</h3>
-        </div>
-
-        <!-- 正文信息 -->
         <div class="box-body">
           <el-table
             :data="privilegeGroupList"
@@ -42,6 +37,7 @@ import { mapState } from "vuex";
 import { CORE_API } from "@/constants/constants.js";
 
 export default {
+  name: "PrivilegeGroupList",
   data() {
     return {
       privilegeGroupList: []

+ 2 - 7
src/modules/basic/view/privilege_tree.vue

@@ -1,13 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div class="box-header with-border">
-          <h3 class="box-title">鉴权管理 &gt; 权限组列表 &gt; 权限树</h3>
-        </div>
-
-        <!-- 正文信息 -->
         <div class="box-body">
           <!-- 权限树 -->
           <div style="width: 50%;">
@@ -274,6 +268,7 @@ let checkCode = (rule, value, callback) => {
 
 
 export default {
+  name: "PrivilegeTree",
     data() {
         return {
             privilegeGroupId: null,

+ 2 - 7
src/modules/basic/view/role_privilege_settings.vue

@@ -1,13 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div class="box-header with-border">
-          <h3 class="box-title">鉴权管理 &gt; 角色权限配置</h3>
-        </div>
-
-        <!-- 正文信息 -->
         <div class="box-body">
           <!-- 选择 -->
           <el-form
@@ -104,6 +98,7 @@ import { mapState } from "vuex";
 import { CORE_API } from "@/constants/constants.js";
 
 export default {
+  name: "RolePrivilegeSettings",
   data() {
     return {
       completed: false,

+ 2 - 9
src/modules/basic/view/school.vue

@@ -1,15 +1,7 @@
 <template>
   <div>
-    <section class="content" style="margin-top: -10px;">
+    <section class="content" style="margin-top: 20px;">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div
-          class="box-header with-border"
-          style="background-color:#D3DCE6;margin-bottom:20px;"
-        >
-          <h3 class="box-title">学校列表</h3>
-        </div>
-        <!-- 正文信息 -->
         <div class="box-body">
           <!-- 表单 -->
           <el-form
@@ -320,6 +312,7 @@ import { CORE_API } from "@/constants/constants.js";
 import { mapState } from "vuex";
 
 export default {
+  name: "School",
   data() {
     return {
       formSearch: {

+ 1 - 6
src/modules/basic/view/specially.vue

@@ -2,12 +2,6 @@
   <div>
     <section class="content">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div class="box-header with-border">
-          <h3 class="box-title">专业列表</h3>
-        </div>
-
-        <!-- 正文信息 -->
         <div class="box-body">
           <el-form
             :inline="true"
@@ -356,6 +350,7 @@ import { CORE_API } from "@/constants/constants.js";
 import { mapState } from "vuex";
 
 export default {
+  name: "Specially",
   data() {
     return {
       courseLoading: false,

+ 1 - 6
src/modules/basic/view/user.vue

@@ -2,12 +2,6 @@
   <div>
     <section class="content">
       <div class="box box-info">
-        <!-- 头信息 -->
-        <div class="box-header with-border">
-          <h3 class="box-title">普通用户管理</h3>
-        </div>
-
-        <!-- 正文信息 -->
         <div class="box-body">
           <!-- 搜索 -->
           <el-form
@@ -455,6 +449,7 @@ import { CORE_API } from "@/constants/constants.js";
 import { mapState } from "vuex";
 
 export default {
+  name: "User",
   data() {
     var validateRootOrg = (rule, value, callback) => {
       if (0 != value && !value) {

+ 1 - 33
src/modules/marking/constants/constants.js

@@ -1,41 +1,9 @@
 import Vue from "vue";
 
-export const UPAI_YUN = "http://exam-cloud-test.b0.upaiyun.com"; //又拍云前端显示
-
 export const LEVEL_TYPE = [
   { label: "专升本", value: "ZSB" },
   { label: "高起专", value: "GQZ" },
   { label: "不限", value: "ALL" }
 ];
-//标记卷类型
-export const TAGS = [
-  { label: "雷同卷", value: "SAME" },
-  { label: "空白卷", value: "BLANK" },
-  { label: "答非所问", value: "IRRELEVANT" },
-  { label: "科目错误", value: "SUBJECT_ERROR" },
-  { label: "非手写", value: "QUESTIONABLE" }
-];
-//标记卷过滤器
-Vue.filter("tagFilter", function(val) {
-  for (let tag of TAGS) {
-    if (tag.value === val) {
-      return tag.label;
-    }
-  }
-});
-//考试类型
-export const EXAMTYPES = [
-  { label: "在线考试", value: "ONLINE" },
-  { label: "离线考试", value: "OFFLINE" },
-  { label: "传统考试", value: "TRADITION" },
-  { label: "练习", value: "PRACTICE" }
-];
-//考试类型过滤器
-Vue.filter("examTypeFilter", function(val) {
-  for (let examType of EXAMTYPES) {
-    if (examType.value === val) {
-      return examType.label;
-    }
-  }
-});
+
 export const EVENTHUB = new Vue();

+ 32 - 0
src/modules/marking/filters/filters.js

@@ -0,0 +1,32 @@
+import Vue from "vue";
+//标记卷类型
+export const TAGS = [
+  { label: "雷同卷", value: "SAME" },
+  { label: "空白卷", value: "BLANK" },
+  { label: "答非所问", value: "IRRELEVANT" },
+  { label: "科目错误", value: "SUBJECT_ERROR" },
+  { label: "非手写", value: "QUESTIONABLE" }
+];
+//标记卷过滤器
+Vue.filter("tagFilter", function(val) {
+  for (let tag of TAGS) {
+    if (tag.value === val) {
+      return tag.label;
+    }
+  }
+});
+//考试类型
+export const EXAMTYPES = [
+  { label: "在线考试", value: "ONLINE" },
+  { label: "离线考试", value: "OFFLINE" },
+  { label: "传统考试", value: "TRADITION" },
+  { label: "练习", value: "PRACTICE" }
+];
+//考试类型过滤器
+Vue.filter("examTypeFilter", function(val) {
+  for (let examType of EXAMTYPES) {
+    if (examType.value === val) {
+      return examType.label;
+    }
+  }
+});

+ 0 - 126
src/modules/marking/store/Print.js

@@ -1,126 +0,0 @@
-/* @Print.js
- * DH (http://denghao.me)
- * 2017-7-14
- */
-export function Print(dom, options) {
-  if (!(this instanceof Print)) return new Print(dom, options);
-
-  this.options = this.extend(
-    {
-      noPrint: ".no-print"
-    },
-    options
-  );
-
-  if (typeof dom === "string") {
-    this.dom = document.querySelector(dom);
-  } else {
-    this.dom = dom;
-  }
-
-  this.init();
-}
-Print.prototype = {
-  init: function() {
-    var content = this.getStyle() + this.getHtml();
-    this.writeIframe(content);
-  },
-  extend: function(obj, obj2) {
-    for (var k in obj2) {
-      obj[k] = obj2[k];
-    }
-    return obj;
-  },
-
-  getStyle: function() {
-    var str = "",
-      styles = document.querySelectorAll("style,link");
-    for (var i = 0; i < styles.length; i++) {
-      str += styles[i].outerHTML;
-    }
-    str +=
-      "<style>" +
-      (this.options.noPrint ? this.options.noPrint : ".no-print") +
-      "{display:none;}</style>";
-
-    return str;
-  },
-
-  getHtml: function() {
-    var inputs = document.querySelectorAll("input");
-    var textareas = document.querySelectorAll("textarea");
-    var selects = document.querySelectorAll("select");
-
-    for (var k in inputs) {
-      if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
-        if (inputs[k].checked == true) {
-          inputs[k].setAttribute("checked", "checked");
-        } else {
-          inputs[k].removeAttribute("checked");
-        }
-      } else if (inputs[k].type == "text") {
-        inputs[k].setAttribute("value", inputs[k].value);
-      }
-    }
-
-    for (var k2 in textareas) {
-      if (textareas[k2].type == "textarea") {
-        textareas[k2].innerHTML = textareas[k2].value;
-      }
-    }
-
-    for (var k3 in selects) {
-      if (selects[k3].type == "select-one") {
-        var child = selects[k3].children;
-        for (var i in child) {
-          if (child[i].tagName == "OPTION") {
-            if (child[i].selected == true) {
-              child[i].setAttribute("selected", "selected");
-            } else {
-              child[i].removeAttribute("selected");
-            }
-          }
-        }
-      }
-    }
-
-    return this.dom.outerHTML;
-  },
-
-  writeIframe: function(content) {
-    var w,
-      doc,
-      iframe = document.createElement("iframe"),
-      f = document.body.appendChild(iframe);
-    iframe.id = "myIframe";
-    iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
-
-    w = f.contentWindow || f.contentDocument;
-    doc = f.contentDocument || f.contentWindow.document;
-    doc.open();
-    doc.write(content);
-    doc.close();
-    this.toPrint(w);
-    // setTimeout(function() {
-    //   document.body.removeChild(iframe)
-    // }, 100)
-  },
-
-  toPrint: function(frameWindow) {
-    try {
-      setTimeout(function() {
-        frameWindow.focus();
-        try {
-          if (!frameWindow.document.execCommand("print", false, null)) {
-            frameWindow.print();
-          }
-        } catch (e) {
-          frameWindow.print();
-        }
-        frameWindow.close();
-      }, 1000);
-    } catch (err) {
-      console.log("err", err);
-    }
-  }
-};

+ 35 - 21
src/modules/marking/views/MarkWorkOverview.vue

@@ -11,8 +11,8 @@
 
         <div class="box-body">
           <div class="echarts">
-            <!-- <div class="pie"><IEcharts :option="pie"></IEcharts></div> -->
-            <!-- <div class="pie"><IEcharts :option="pie1"></IEcharts></div> -->
+            <div class="pie"><v-charts :options="pie"></v-charts></div>
+            <div class="pie"><v-charts :options="pie1"></v-charts></div>
           </div>
 
           <el-form
@@ -31,14 +31,13 @@
                     v-model="formSearch.courseCode"
                     placeholder="请选择"
                   >
-                    <el-option value="">请选择</el-option>
+                    <el-option value>请选择</el-option>
                     <el-option
                       v-for="item in courseAllListSelect"
                       :label="item.courseInfo"
                       :value="item.code"
                       :key="item.code"
-                    >
-                    </el-option>
+                    ></el-option>
                   </el-select>
                 </el-form-item>
                 <el-form-item>
@@ -61,16 +60,31 @@
             border
             style="width: 100%"
           >
-            <el-table-column label="课程名称" width="200" prop="name">
-            </el-table-column>
-            <el-table-column label="课程代码" min-width="100" prop="code">
-            </el-table-column>
-            <el-table-column label="任务总数" min-width="100" prop="totalCount">
-            </el-table-column>
-            <el-table-column label="完成数" min-width="100" prop="markedCount">
-            </el-table-column>
-            <el-table-column label="待完成" min-width="100" prop="leftCount">
-            </el-table-column>
+            <el-table-column
+              label="课程名称"
+              width="200"
+              prop="name"
+            ></el-table-column>
+            <el-table-column
+              label="课程代码"
+              min-width="100"
+              prop="code"
+            ></el-table-column>
+            <el-table-column
+              label="任务总数"
+              min-width="100"
+              prop="totalCount"
+            ></el-table-column>
+            <el-table-column
+              label="完成数"
+              min-width="100"
+              prop="markedCount"
+            ></el-table-column>
+            <el-table-column
+              label="待完成"
+              min-width="100"
+              prop="leftCount"
+            ></el-table-column>
             <el-table-column label="进度" min-width="100">
               <template slot-scope="scope">
                 <div>
@@ -97,8 +111,7 @@
               :page-size="10"
               layout="total, prev, pager, next, jumper"
               :total="total"
-            >
-            </el-pagination>
+            ></el-pagination>
           </div>
         </div>
       </div>
@@ -109,10 +122,11 @@
 <script>
 import { MARKING_API } from "@/constants/constants";
 import { mapState } from "vuex";
-// import IEcharts from 'vue-echarts-v3/src/full.vue'
+import ECharts from "vue-echarts/components/ECharts";
+import "echarts/lib/chart/pie";
 export default {
   components: {
-    // IEcharts
+    "v-charts": ECharts
   },
   data() {
     return {
@@ -132,7 +146,7 @@ export default {
       pie: {
         title: {
           text: "试卷进度情况",
-          x: "center"
+          left: "center"
         },
         tooltip: {
           trigger: "item",
@@ -182,7 +196,7 @@ export default {
       pie1: {
         title: {
           text: "课程进度情况",
-          x: "center"
+          left: "center"
         },
         tooltip: {
           trigger: "item",

+ 18 - 16
src/modules/marking/views/TpMain.vue

@@ -12,12 +12,12 @@
             <div class="paper" v-show="this.markSign">
               <div class="fixed marktitle signTitle">
                 <el-button-group class="itemTitle">
-                  <el-button type="info" size="small"
-                    ><span class="">当前题</span></el-button
-                  >
-                  <el-button type="info" size="small"
-                    ><span class="">{{ itemTitle }}</span></el-button
-                  >
+                  <el-button type="info" size="small">
+                    <span class>当前题</span>
+                  </el-button>
+                  <el-button type="info" size="small">
+                    <span class>{{ itemTitle }}</span>
+                  </el-button>
                 </el-button-group>
                 <!--
                   <el-button type="primary" size="small" @click="saveMarkSign">保存轨迹</el-button>
@@ -47,9 +47,9 @@
               style="float: right;margin-right: 20px;"
               class="no-print"
             >
-              <el-button size="small" type="success" @click="pdfDown();">
-                下载
-              </el-button>
+              <el-button size="small" type="success" @click="pdfDown();"
+                >下载</el-button
+              >
             </div>
           </div>
         </div>
@@ -58,9 +58,9 @@
         <el-tab-pane label="标答" name="second">
           <div id="answer-source" v-if="this.examType == 'OFFLINE'">
             <div style="float: right;margin-right: 20px;" class="no-print">
-              <el-button size="small" type="success" @click="printAnswer();">
-                打印
-              </el-button>
+              <el-button size="small" type="success" @click="printAnswer();"
+                >打印</el-button
+              >
             </div>
             <div
               class="paper"
@@ -75,8 +75,8 @@
 </template>
 <script>
 import { Drawing } from "../canvas/mark_sign";
-import { EVENTHUB, UPAI_YUN } from "../constants/constants";
-import { Print } from "../store/Print";
+import { EVENTHUB } from "../constants/constants";
+import printJS from "print-js";
 export default {
   data() {
     return {
@@ -256,12 +256,14 @@ export default {
     },
     //打印
     printAnswer() {
-      Print("#answer-source");
+      printJS({ printable: "answer-content", type: "html" });
     },
     pdfDown() {
       var url = this.studentPaper.studentSubjectiveHtml;
       if (url != "undefined" && url != "") {
-        url = url.replace(UPAI_YUN, "");
+        url = new URL(url);
+        url = url.pathname;
+        url = decodeURIComponent(url);
         let xhr = new XMLHttpRequest();
         xhr.responseType = "blob";
         xhr.open("GET", url, true);

+ 14 - 0
src/modules/portal/store/currentPaths.js

@@ -0,0 +1,14 @@
+export const UPDATE_CURRENT_PATHS = "UPDATE_CURRENT_PATHS"; //退出登录
+
+export default {
+  state: [],
+  mutations: {
+    [UPDATE_CURRENT_PATHS](state, paths) {
+      console.log(state, paths);
+      // state = paths;
+      // Object.assign(state, paths);
+      state.length = 0;
+      state.push(...paths);
+    }
+  }
+};

+ 12 - 3
src/modules/portal/views/home/Home.vue

@@ -30,7 +30,8 @@
     <el-container>
       <HomeSide v-if="ifShowHomeSide" :key="sideKey" />
       <el-container class="main-body">
-        <router-view></router-view>
+        <LinkTitles v-if="ifShowHomeSide" :key="Math.random()" />
+        <router-view class="main-content"></router-view>
         <el-footer class="footer">&copy; 启明泰和 2019</el-footer>
       </el-container>
     </el-container>
@@ -105,6 +106,7 @@ import { mapActions, mapState } from "vuex";
 import { USER_SIGNOUT } from "../../store/user";
 import { CORE_API } from "@/constants/constants";
 import HomeSide from "./HomeSide.vue";
+import LinkTitles from "./LinkTitles.vue";
 
 export default {
   name: "Home",
@@ -137,7 +139,7 @@ export default {
       }
     };
   },
-  components: { HomeSide },
+  components: { HomeSide, LinkTitles },
   computed: {
     ...mapState({ user: state => state.user }),
     ifShowHomeSide() {
@@ -243,14 +245,21 @@ body > .el-container {
 }
 
 .main-body {
-  min-height: calc(100vh - 60px);
+  min-height: calc(100vh - 60px - 20px);
   display: flex;
   flex-direction: column;
   justify-content: space-between;
+  margin-top: 20px;
+  margin-left: 20px;
+}
+
+.main-content {
+  min-height: calc(100vh - 60px - 60px - 60px);
 }
 
 .footer {
   justify-self: flex-end;
+  margin-left: -20px;
 }
 </style>
 

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

@@ -80,6 +80,9 @@ const routesToMenu = [
   }
 ];
 
+import { mapMutations } from "vuex";
+import { UPDATE_CURRENT_PATHS } from "../../store/currentPaths";
+
 export default {
   name: "HomeSide",
   data() {
@@ -97,6 +100,7 @@ export default {
     }
   },
   methods: {
+    ...mapMutations([UPDATE_CURRENT_PATHS]),
     async getUserPrivileges(groupCode) {
       var url = CORE_API + "/rolePrivilege/getUserPrivileges";
       const params = new URLSearchParams();
@@ -112,6 +116,21 @@ export default {
       return this.menuList.filter(
         m => m.parentId === menu1.id && m.ext1 === "menu"
       );
+    },
+    updatePath() {
+      let currentPaths = [];
+      let part = this.menuList.find(v => v.ext5 === this.$route.path);
+      if (!part) {
+        this.UPDATE_CURRENT_PATHS([]);
+        return;
+      }
+      currentPaths.unshift(part.name);
+      while (this.menuList.find(v => v.id === part.parentId)) {
+        part = this.menuList.find(v => v.id === part.parentId);
+        currentPaths.unshift(part.name);
+      }
+      console.log(currentPaths);
+      this.UPDATE_CURRENT_PATHS(currentPaths);
     }
   },
   async created() {
@@ -119,6 +138,12 @@ export default {
     const groupCode = this.group && this.group.groupCode;
     if (groupCode) {
       this.menuList = await this.getUserPrivileges(groupCode);
+      this.updatePath();
+    }
+  },
+  watch: {
+    $route() {
+      this.updatePath();
     }
   }
 };

+ 22 - 0
src/modules/portal/views/home/LinkTitles.vue

@@ -0,0 +1,22 @@
+<template>
+  <el-breadcrumb
+    separator-class="el-icon-arrow-right"
+    style="border-bottom: 1px solid #aaa; padding-bottom: 5px;"
+  >
+    <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+    <el-breadcrumb-item v-for="item in currentPaths" :key="item">
+      {{ item }}
+    </el-breadcrumb-item>
+  </el-breadcrumb>
+</template>
+
+<script>
+import { mapState } from "vuex";
+
+export default {
+  name: "LinkTitles",
+  computed: {
+    ...mapState(["currentPaths"])
+  }
+};
+</script>

+ 429 - 251
src/modules/print/view/CourseStatistic.vue

@@ -124,6 +124,7 @@
               size="small"
               type="primary"
               icon="el-icon-download"
+              :disabled="selectElements.length == 0"
               @click="openExportDialog"
               >批量导出
             </el-button>
@@ -132,6 +133,7 @@
               size="small"
               type="primary"
               icon="el-icon-refresh"
+              :disabled="selectElements.length == 0"
               @click="refreshStatistic"
               >刷新
             </el-button>
@@ -145,6 +147,7 @@
           element-loading-text="数据加载中"
           style="width:100%;"
           border
+          @selection-change="handleSelection"
         >
           <el-table-column type="selection" width="55"> </el-table-column>
           <el-table-column label="课程名称" prop="courseName" />
@@ -177,7 +180,7 @@
                 size="mini"
                 icon="el-icon-download"
                 v-show="scope.row.paperStatus > 1"
-                @click="download(scope.row);"
+                @click="openExportDialog(scope.row);"
                 >下载
               </el-button>
             </template>
@@ -251,177 +254,172 @@
         </el-form>
       </el-dialog>
 
-      <el-dialog title="试卷整体分配" :visible.sync="allotAllDialog">
+      <el-dialog
+        title="试卷整体分配"
+        width="400px"
+        :visible.sync="allotAllDialog"
+        @close="closeAllotAllDialog"
+      >
         <el-form
           :model="allotAllForm"
+          ref="allotAllForm"
+          :rules="rules"
           label-position="right"
-          label-width="100px"
+          label-width="80px"
         >
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="学校名称">
-                <el-select
-                  v-model="allotAllForm.orgId"
-                  @change="searchExamList(allotAllForm.orgId, 2);"
-                >
-                  <el-option label="请选择" value></el-option>
-                  <el-option
-                    v-for="item in orgList"
-                    :label="item.orgName"
-                    :value="item.orgId"
-                    :key="item.orgId"
-                  ></el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
-          </el-row>
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="考试名称">
-                <el-select v-model="allotAllForm.examId">
-                  <el-option label="请选择" value></el-option>
-                  <el-option
-                    v-for="item in examList"
-                    :label="item.examName"
-                    :value="item.examId"
-                    :key="item.examId"
-                  ></el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
-          </el-row>
-          <el-row :gutter="10">
-            <el-col :span="20">
-              <el-form-item>
-                <span style="font-size:20px;color: red;"
-                  >警告!确定后,选中考试中待指定的课程会在推送试卷中随机选取一套试卷,是否确定执行?</span
-                >
-              </el-form-item>
-            </el-col>
-          </el-row>
-          <el-row>
-            <el-col
-              :span="24"
-              class="text-center"
-              style="border-top: 2px solid;padding-top: 10px;"
+          <el-form-item label="学校名称" prop="orgId">
+            <el-select
+              v-model="allotAllForm.orgId"
+              @change="searchAllotExamList(allotAllForm.orgId);"
+              placeholder="请选择"
+              class="w220"
             >
-              <el-button
-                type="primary"
-                :disabled="
-                  allotAllForm.orgId === '' || allotAllForm.examId === ''
-                "
-                @click="saveAllotAll"
-                >确定</el-button
-              >
-            </el-col>
-          </el-row>
+              <el-option
+                v-for="item in orgList"
+                :label="item.orgName"
+                :value="item.orgId"
+                :key="item.orgId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="考试名称" prop="examId">
+            <el-select
+              v-model="allotAllForm.examId"
+              placeholder="请选择"
+              class="w220"
+            >
+              <el-option
+                v-for="item in allotExamList"
+                :label="item.examName"
+                :value="item.examId"
+                :key="item.examId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+
+          <div style="text-align: center">
+            <p style="color: red;">
+              警告:确定后当前考试中“未指定试卷”的课程会在已有的试卷中随机选取一套试卷分配关联,是否确定执行?
+            </p>
+            <el-button
+              type="primary"
+              @click="saveAllotAll"
+              :disabled="allotAllForm.examId == ''"
+              >确 定</el-button
+            >
+            <el-button @click="closeAllotAllDialog">取 消</el-button>
+          </div>
         </el-form>
       </el-dialog>
 
-      <el-dialog title="导出" :visible.sync="exportDialog">
-        <el-form :model="exportForm" label-position="right" label-width="80px">
-          <el-checkbox-group v-model="exportForm.types">
-            <el-checkbox label="1">试卷</el-checkbox>
-            <el-checkbox label="2">答案</el-checkbox>
-            <el-checkbox label="3">试卷结构</el-checkbox>
-          </el-checkbox-group>
+      <el-dialog
+        title="导出"
+        width="450px"
+        :visible.sync="exportDialog"
+        @close="closeExportDialog"
+      >
+        <el-form
+          :model="exportForm"
+          ref="exportForm"
+          :rules="rules"
+          label-position="right"
+          label-width="90px"
+        >
+          <el-form-item label="导出内容" prop="types">
+            <el-checkbox-group v-model="exportForm.types">
+              <el-checkbox label="1">试卷</el-checkbox>
+              <el-checkbox label="2">答案</el-checkbox>
+              <el-checkbox label="3">试卷结构</el-checkbox>
+            </el-checkbox-group>
+          </el-form-item>
+
           <div style="text-align: center">
-            <el-button type="primary" @click="doExport">确定导出</el-button>
+            <el-button
+              type="primary"
+              @click="doExport"
+              :disabled="exportForm.types.length == 0"
+              >确定导出</el-button
+            >
             <el-button @click="closeExportDialog">取 消</el-button>
           </div>
         </el-form>
       </el-dialog>
 
-      <el-dialog title="试卷整体导出" :visible.sync="exportAllDialog">
+      <el-dialog
+        title="试卷整体导出"
+        width="450px"
+        :visible.sync="exportAllDialog"
+        @close="closeExportAllDialog"
+      >
         <el-form
           :model="exportAllForm"
+          ref="exportAllForm"
+          :rules="rules"
           label-position="right"
-          label-width="100px"
+          label-width="90px"
         >
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="学校名称">
-                <el-select
-                  v-model="exportAllForm.orgId"
-                  @change="searchExamList(exportAllForm.orgId, 3);"
-                >
-                  <el-option label="请选择" value></el-option>
-                  <el-option
-                    v-for="item in orgList"
-                    :label="item.orgName"
-                    :value="item.orgId"
-                    :key="item.orgId"
-                  ></el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
-          </el-row>
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="考试名称">
-                <el-select
-                  v-model="exportAllForm.examId"
-                  @change="searchExamCoursePaperTotal"
-                >
-                  <el-option label="请选择" value></el-option>
-                  <el-option
-                    v-for="item in examList"
-                    :label="item.examName"
-                    :value="item.examId"
-                    :key="item.examId"
-                  ></el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
-          </el-row>
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="试卷总数">{{
-                exportAllForm.allNum
-              }}</el-form-item>
-            </el-col>
-          </el-row>
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="已有试卷数">{{
-                exportAllForm.existNum
-              }}</el-form-item>
-            </el-col>
-          </el-row>
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="缺少试卷数">{{
-                exportAllForm.missNum
-              }}</el-form-item>
-            </el-col>
-          </el-row>
-
-          <el-row :gutter="10">
-            <el-col :md="20">
-              <el-form-item label="导出内容">
-                <el-checkbox-group v-model="exportAllForm.types">
-                  <el-checkbox label="1">试卷</el-checkbox>
-                  <el-checkbox label="2">答案</el-checkbox>
-                  <el-checkbox label="3">试卷结构</el-checkbox>
-                </el-checkbox-group>
-              </el-form-item>
-            </el-col>
-          </el-row>
-
-          <el-row :gutter="10">
-            <el-col
-              :span="24"
-              class="text-center"
-              style="border-top: 2px solid;padding-top: 10px;"
+          <el-form-item label="学校名称" prop="orgId">
+            <el-select
+              v-model="exportAllForm.orgId"
+              @change="searchExportExamList(exportAllForm.orgId);"
+              placeholder="请选择"
+              class="w220"
             >
-              <el-button
-                type="primary"
-                :disabled="exportAllForm.existNum == 0"
-                @click="doExportAll"
-                >确定导出</el-button
-              >
-            </el-col>
-          </el-row>
+              <el-option
+                v-for="item in orgList"
+                :label="item.orgName"
+                :value="item.orgId"
+                :key="item.orgId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="考试名称" prop="examId">
+            <el-select
+              v-model="exportAllForm.examId"
+              @change="searchExamCoursePaperTotal"
+              placeholder="请选择"
+              class="w220"
+            >
+              <el-option
+                v-for="item in exportExamList"
+                :label="item.examName"
+                :value="item.examId"
+                :key="item.examId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="导出内容" prop="types">
+            <el-checkbox-group v-model="exportAllForm.types">
+              <el-checkbox label="1">试卷</el-checkbox>
+              <el-checkbox label="2">答案</el-checkbox>
+              <el-checkbox label="3">试卷结构</el-checkbox>
+            </el-checkbox-group>
+          </el-form-item>
+
+          <el-form-item label="试卷总数" prop="allNum">
+            {{ exportAllForm.allNum }}
+          </el-form-item>
+
+          <el-form-item label="已有试卷数" prop="existNum">
+            {{ exportAllForm.existNum }}
+          </el-form-item>
+
+          <el-form-item label="缺少试卷数" prop="missNum">
+            {{ exportAllForm.missNum }}
+          </el-form-item>
+
+          <div style="text-align: center">
+            <el-button
+              type="primary"
+              @click="doExportAll"
+              :disabled="exportAllForm.existNum == 0"
+              >确定导出</el-button
+            >
+            <el-button @click="closeExportAllDialog">取 消</el-button>
+          </div>
         </el-form>
       </el-dialog>
     </div>
@@ -455,6 +453,7 @@ export default {
       courseList: [],
       coursePaperList: [],
       coursePaperStatusList: coursePaperStatusList,
+      allotExamList: [],
       allotDialog: false,
       allotForm: {
         id: "",
@@ -467,28 +466,29 @@ export default {
         orgId: "",
         examId: ""
       },
+      selectElements: [],
+      exportExamList: [],
       exportDialog: false,
       exportForm: {
-        orgId: "",
-        examId: "",
-        courseCode: "",
-        courseName: "",
-        paperType: "",
-        coursePaperId: "",
-        courseId: "",
-        id: ""
+        ids: [],
+        types: []
       },
       exportAllDialog: false,
       exportAllForm: {
         orgId: "",
         examId: "",
-        exportList: [],
+        types: [],
         allNum: 0,
         existNum: 0,
-        missNum: 0,
-        types: []
+        missNum: 0
       },
       rules: {
+        orgId: [
+          { required: true, message: "学校不能为空!", trigger: "change" }
+        ],
+        examId: [
+          { required: true, message: "考试不能为空!", trigger: "change" }
+        ],
         coursePaperId: [
           { required: true, message: "试卷不能为空!", trigger: "change" }
         ],
@@ -497,13 +497,166 @@ export default {
         ],
         paperType: [
           { required: true, message: "试卷类型不能为空!", trigger: "change" }
+        ],
+        types: [
+          { required: true, message: "请选择导出内容!", trigger: "change" }
         ]
       }
     };
   },
   methods: {
-    searchExamCoursePaperTotal() {
-      /* xxx */
+    handleSelection(elements) {
+      /* 处理选中记录 */
+      this.selectElements = elements;
+    },
+    handlePager(current) {
+      /* 处理分页 */
+      this.formSearch.pageNo = current;
+      this.searchRecords();
+    },
+    searchRecords() {
+      /* 查询记录列表 */
+      let orgId = this.formSearch.orgId;
+      if (this.isEmptyNumber(orgId)) {
+        this.$notify({
+          message: "请选择学校!",
+          type: "warning"
+        });
+        return;
+      }
+
+      let examId = this.formSearch.examId;
+      if (this.isEmptyNumber(examId)) {
+        this.$notify({
+          message: "请选择考试!",
+          type: "warning"
+        });
+        return;
+      }
+
+      this.loading = true;
+      let url = PRINT_API + "/course/statistic/list";
+      this.$http.post(url, this.formSearch).then(
+        response => {
+          this.tableData = response.data.content;
+          this.totalElements = response.data.totalElements;
+          this.loading = false;
+        },
+        error => {
+          console.log(error);
+          this.loading = false;
+        }
+      );
+    },
+    searchExamList(orgId) {
+      /* 查询考试列表 */
+      this.formSearch.examId = "";
+      this.examList = [];
+      this.tableData = [];
+
+      if (!this.isEmptyNumber(orgId)) {
+        let url = PRINT_API + "/printing/project/exam/list?orgId=" + orgId;
+        this.$http.post(url).then(response => {
+          this.examList = response.data;
+        });
+      }
+    },
+    searchAllotExamList(orgId) {
+      /* 查询考试列表 */
+      this.allotAllForm.examId = "";
+      this.allotExamList = [];
+
+      if (!this.isEmptyNumber(orgId)) {
+        let url = PRINT_API + "/printing/project/exam/list?orgId=" + orgId;
+        this.$http.post(url).then(response => {
+          this.allotExamList = response.data;
+        });
+      }
+    },
+    searchExportExamList(orgId) {
+      /* 查询考试列表 */
+      this.exportAllForm.examId = "";
+      this.exportExamList = [];
+
+      if (!this.isEmptyNumber(orgId)) {
+        let url = PRINT_API + "/printing/project/exam/list?orgId=" + orgId;
+        this.$http.post(url).then(response => {
+          this.exportExamList = response.data;
+        });
+      }
+    },
+    searchCourseList(query) {
+      /* 查询课程列表 */
+      this.courseList = [];
+      let url = CORE_API + "/course/query?enable=true";
+
+      if (!this.isEmptyStr(query)) {
+        url += "&name=" + query;
+      }
+
+      this.$http.get(url).then(response => {
+        this.courseList = response.data;
+      });
+    },
+    refreshStatistic() {
+      /* 刷新当前统计信息 */
+      this.$confirm("刷新当前统计信息?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          if (this.selectElements.length == 0) {
+            this.$notify({
+              message: "请选择要刷新的项!",
+              type: "warning"
+            });
+            return;
+          }
+
+          let params = {};
+          params.orgId = this.selectElements[0].orgId;
+          params.examId = this.selectElements[0].examId;
+          params.couses = [];
+          this.selectElements.forEach(element => {
+            params.couses.push({
+              courseId: element.courseId,
+              paperType: element.paperType
+            });
+          });
+
+          let url = PRINT_API + "/course/statistic/refresh";
+          this.$http.post(url, params).then(
+            () => {
+              this.$notify({
+                type: "success",
+                message: "刷新成功!"
+              });
+              this.searchRecords();
+            },
+            () => {
+              this.$notify({
+                type: "error",
+                message: "刷新失败!"
+              });
+            }
+          );
+        })
+        .catch(() => {
+          //ignore
+        });
+    },
+    preview(row) {
+      /* 预览试卷PDF */
+      let url = row.paperPdfUrl;
+      if (!url) {
+        this.$notify({
+          message: "当前试卷不存在!",
+          type: "warning"
+        });
+        return;
+      }
+      window.open(url);
     },
     openAllotDialog(row) {
       /* 试卷状态为"已有"时,打开试卷指定弹窗 */
@@ -513,6 +666,7 @@ export default {
         this.allotForm.coursePaperId = row.coursePaperId;
         this.allotForm.courseName = row.courseName;
         this.allotForm.paperType = row.paperType;
+
         let params = {
           orgId: row.orgId,
           examId: row.examId,
@@ -564,19 +718,51 @@ export default {
       });
     },
     openAllotAllDialog() {
-      /* 打开分配待指定试卷弹窗 */
+      /* 打开试卷整体分配弹窗 */
       this.allotAllDialog = true;
     },
     closeAllotAllDialog() {
-      /* 关闭分配待指定试卷弹窗 */
+      /* 关闭试卷整体分配弹窗 */
       this.allotAllDialog = false;
     },
     saveAllotAll() {
-      /* 保存分配待指定试卷 */
+      /* 保存试卷整体分配 */
+      this.$refs.allotAllForm.validate(valid => {
+        if (!valid) {
+          return false;
+        }
+
+        let url =
+          PRINT_API +
+          "/course/paper/allot/all/" +
+          this.allotAllForm.orgId +
+          "/" +
+          this.allotAllForm.examId;
+
+        this.$http.post(url).then(
+          () => {
+            this.$notify({
+              message: "试卷整体分配成功!",
+              type: "success"
+            });
+            this.allotAllDialog = false;
+          },
+          () => {
+            this.$notify({
+              message: "试卷整体分配失败!",
+              type: "error"
+            });
+          }
+        );
+      });
     },
-    openExportDialog() {
+    openExportDialog(row) {
       /* 打开批量导出弹窗 */
       this.exportDialog = true;
+      this.exportForm.ids = [];
+      if (row.id) {
+        this.exportForm.ids.push(row.id);
+      }
     },
     closeExportDialog() {
       /* 关闭批量导出弹窗 */
@@ -584,6 +770,49 @@ export default {
     },
     doExport() {
       /* 批量导出 */
+      let ids = [];
+      if (this.exportForm.ids.length > 0) {
+        ids = this.exportForm.ids;
+      } else {
+        if (this.selectElements.length == 0) {
+          this.$notify({
+            message: "请选择要导出的项!",
+            type: "warning"
+          });
+          return;
+        }
+
+        this.selectElements.forEach(element => {
+          if (element.paperStatus > 1) {
+            ids.push(element.id);
+          }
+        });
+      }
+
+      this.$refs.exportForm.validate(valid => {
+        if (!valid) {
+          return false;
+        }
+
+        if (ids.length == 0) {
+          this.$notify({
+            message: "包含未被指定试卷的课程则不可导出!",
+            type: "warning"
+          });
+          return;
+        }
+
+        this.closeExportDialog();
+        let url =
+          PRINT_API +
+          "/course/paper/export/batch?ids=" +
+          ids.join(",") +
+          "&types=" +
+          this.exportForm.types.join(",");
+
+        //console.log(url);
+        window.location.href = url;
+      });
     },
     openExportAllDialog() {
       /* 打开整体导出弹窗 */
@@ -595,94 +824,43 @@ export default {
     },
     doExportAll() {
       /* 整体导出 */
+      this.$refs.exportAllForm.validate(valid => {
+        if (!valid) {
+          return false;
+        }
+        this.closeExportAllDialog();
+        let url =
+          PRINT_API +
+          "/course/paper/export/all?orgId=" +
+          this.exportAllForm.orgId +
+          "&examId=" +
+          this.exportAllForm.examId +
+          "&types=" +
+          this.exportAllForm.types.join(",");
+
+        //console.log(url);
+        window.location.href = url;
+      });
     },
-    handlePager(current) {
-      /* 处理分页 */
-      this.formSearch.pageNo = current;
-      this.searchRecords();
-    },
-    searchRecords() {
-      /* 查询记录列表 */
-      let orgId = this.formSearch.orgId;
-      if (this.isEmptyNumber(orgId)) {
-        this.$notify({
-          message: "请选择学校!",
-          type: "warning"
-        });
-        return;
-      }
-
-      let examId = this.formSearch.examId;
-      if (this.isEmptyNumber(examId)) {
-        this.$notify({
-          message: "请选择考试!",
-          type: "warning"
-        });
-        return;
-      }
-
-      this.loading = true;
-      let url = PRINT_API + "/course/statistic/list";
-      this.$http.post(url, this.formSearch).then(
+    searchExamCoursePaperTotal() {
+      /* 查询考试的试卷数量情况 */
+      let url =
+        PRINT_API +
+        "/course/paper/total/" +
+        this.exportAllForm.orgId +
+        "/" +
+        this.exportAllForm.examId;
+      this.$http.post(url).then(
         response => {
-          this.tableData = response.data.content;
-          this.totalElements = response.data.totalElements;
-          this.loading = false;
+          let data = response.data;
+          this.exportAllForm.allNum = data.allNum;
+          this.exportAllForm.existNum = data.existNum;
+          this.exportAllForm.missNum = data.missNum;
         },
         error => {
           console.log(error);
-          this.loading = false;
         }
       );
-    },
-    searchExamList(orgId) {
-      /* 查询考试列表 */
-      this.formSearch.examId = "";
-      this.examList = [];
-      this.tableData = [];
-
-      if (!this.isEmptyNumber(orgId)) {
-        let url = PRINT_API + "/printing/project/exam/list?orgId=" + orgId;
-        this.$http.post(url).then(response => {
-          this.examList = response.data;
-        });
-      }
-    },
-    searchCourseList(query) {
-      /* 查询课程列表 */
-      this.courseList = [];
-      let url = CORE_API + "/course/query?enable=true";
-
-      if (!this.isEmptyStr(query)) {
-        url += "&name=" + query;
-      }
-
-      this.$http.get(url).then(response => {
-        this.courseList = response.data;
-      });
-    },
-    refreshStatistic() {
-      /* 刷新当前统计信息 */
-      this.$notify({
-        message: "Todo...",
-        type: "warning"
-      });
-    },
-    preview(row) {
-      /* 预览试卷PDF */
-      console.log(row);
-      this.$notify({
-        message: "Todo...",
-        type: "warning"
-      });
-    },
-    download(row) {
-      /* 下载试卷结构 */
-      console.log(row);
-      this.$notify({
-        message: "Todo...",
-        type: "warning"
-      });
     }
   },
   computed: {

+ 66 - 62
src/plugins/vueLifecylceLogs.js

@@ -4,11 +4,6 @@ const ignoreComponents = [undefined, "transition", "router-link", "Bar"];
 
 const ignoreComponentsNameRegexArray = [/^El[A-Z].*/, /^fa-.*/];
 
-setInterval(
-  () => console.log("----------------------Vue lifecyle logs----------------"),
-  10 * 1000
-);
-
 function getParentNumber(that) {
   let parentNumber = 0;
   while (that) {
@@ -28,8 +23,6 @@ function componentNameMatch(name) {
   } else {
     let match = false;
     for (const regex of ignoreComponentsNameRegexArray) {
-      // console.log(regex);
-      // console.log(name);
       if (regex.test(name)) {
         match = true;
         break;
@@ -38,68 +31,79 @@ function componentNameMatch(name) {
     return match;
   }
 }
-Vue.mixin({
-  created() {
-    const parentNumber = getParentNumber(this);
-    if (!componentNameMatch(this.$options.name))
-      console.log(
-        "--".repeat(parentNumber) + `${this.$options.name} %c created`,
-        "color: green"
-      );
-  },
-  mounted() {
-    const parentNumber = getParentNumber(this);
-    if (!componentNameMatch(this.$options.name))
-      console.log(
-        "--".repeat(parentNumber) + `${this.$options.name} %c mounted`,
-        "color: green"
-      );
-  },
-  updated() {
+
+const injectMethods = [
+  { name: "beforeCreate", style: "color: green" },
+  { name: "created", style: "color: green" },
+  { name: "beforeMount", style: "color: green" },
+  { name: "mounted", style: "color: green" },
+  { name: "beforeUpdate", style: "color: #0000aa" },
+  { name: "updated", style: "color: #0000aa" },
+  { name: "beforeDestroy", style: "color: red; font-weight: bold" },
+  { name: "destroyed", style: "color: red; font-weight: bold" }
+];
+
+const injecRoutertMethods = [
+  { name: "beforeRouteEnter", style: ["background: #aaa", "color: #0000aa;"] },
+  { name: "beforeRouteUpdate", style: ["background: #aaa", "color: #0000aa;"] },
+  { name: "beforeRouteLeave", style: ["background: #aaa", "color: #0000aa;"] }
+];
+
+let lifeCycleMixins = {};
+
+let startLogging = false;
+let loggingTime = Date.now();
+const RENDER_DURATION = 1 * 1000;
+
+for (const m of injectMethods) {
+  lifeCycleMixins[m.name] = function() {
     const parentNumber = getParentNumber(this);
-    if (!componentNameMatch(this.$options.name))
+    if (!componentNameMatch(this.$options.name)) {
+      if (!startLogging) {
+        startLogging = true;
+        loggingTime = Date.now();
+      }
       console.log(
-        "--".repeat(parentNumber) + `${this.$options.name} %c updated`,
-        "color: #0000aa"
+        "--".repeat(parentNumber) + `${this.$options.name} %c ${m.name}`,
+        m.style
       );
-  },
-  beforeRouteEnter(to, from, next) {
-    console.log(
-      "%c " + from.fullPath + " --> " + to.fullPath + " %c beforeRouteEnter",
-      "background: #aaa",
-      "color: #0000aa"
-    );
+    }
+  };
+}
+
+for (const m of injecRoutertMethods) {
+  lifeCycleMixins[m.name] = function(to, from, next) {
+    if (!startLogging) {
+      startLogging = true;
+      console.group("Vue lifecyle logs");
+      loggingTime = Date.now();
+    }
 
-    next();
-  },
-  beforeRouteUpdate(to, from, next) {
-    const parentNumber = getParentNumber(this);
-    console.log(
-      "%c " +
-        "--".repeat(parentNumber) +
-        `${this.$options.name} %c beforeRouteUpdate`,
-      "background: #aaa",
-      "color: #0000aa"
-    );
-    next();
-  },
-  beforeRouteLeave(to, from, next) {
-    const parentNumber = getParentNumber(this);
     console.log(
       "%c " +
-        "--".repeat(parentNumber) +
-        `${this.$options.name} %c beforeRouteLeave`,
-      "background: #aaa",
-      "color: #0000aa"
+        from.fullPath +
+        " --> " +
+        to.fullPath +
+        (this ? ` (${this.$options.name}) ` : " ") +
+        `%c ${m.name}`,
+      ...m.style
     );
+
     next();
-  },
-  beforeDestroy() {
-    const parentNumber = getParentNumber(this);
-    if (!componentNameMatch(this.$options.name))
-      console.log(
-        "--".repeat(parentNumber) + `${this.$options.name} %c beforeDestroy`,
-        "color: red; font-weight: bold"
-      );
+  };
+}
+
+// setInterval(
+//   () => console.log("----------------------Vue lifecyle logs----------------"),
+//   10 * 1000
+// );
+setInterval(() => {
+  if (startLogging && Date.now() - loggingTime > RENDER_DURATION) {
+    console.groupEnd();
+    startLogging = false;
   }
+}, 1 * 100);
+
+Vue.mixin({
+  ...lifeCycleMixins
 });

+ 3 - 1
src/store.js

@@ -1,6 +1,7 @@
 import Vue from "vue";
 import Vuex from "vuex";
 import user from "./modules/portal/store/user";
+import currentPaths from "./modules/portal/store/currentPaths";
 
 Vue.use(Vuex);
 
@@ -9,6 +10,7 @@ export default new Vuex.Store({
   mutations: {},
   actions: {},
   modules: {
-    user
+    user,
+    currentPaths
   }
 });