Explorar o código

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

chenken %!s(int64=6) %!d(string=hai) anos
pai
achega
89a84d1297
Modificáronse 33 ficheiros con 1645 adicións e 827 borrados
  1. 174 3
      UI规范.md
  2. 3 0
      package.json
  3. 47 0
      src/components/EcsFormSearch.vue
  4. 1 1
      src/components/LinkTitlesCustom.vue
  5. 16 7
      src/components/ckeditor.vue
  6. 4 0
      src/main.js
  7. 103 87
      src/modules/basic/view/campus.vue
  8. 9 9
      src/modules/basic/view/course.vue
  9. 192 168
      src/modules/basic/view/exam_site.vue
  10. 1 7
      src/modules/basic/view/privilege_group_list.vue
  11. 273 272
      src/modules/basic/view/school.vue
  12. 11 13
      src/modules/basic/view/specially.vue
  13. 137 128
      src/modules/basic/view/user.vue
  14. 0 17
      src/modules/examwork/view/examInfo.vue
  15. 2 3
      src/modules/examwork/view/examStudent.vue
  16. 2 3
      src/modules/examwork/view/examStudentImport.vue
  17. 7 10
      src/modules/examwork/view/onlineExam.vue
  18. 7 4
      src/modules/examwork/view/practiceExam.vue
  19. 2 3
      src/modules/examwork/view/student.vue
  20. 2 3
      src/modules/marking/views/Marking.vue
  21. 4 1
      src/modules/marking/views/TpMain.vue
  22. 124 47
      src/modules/marking/views/TpScoreBoard.vue
  23. 36 9
      src/modules/portal/views/Login.vue
  24. 2 1
      src/modules/portal/views/home/Home.vue
  25. 2 1
      src/modules/portal/views/home/HomeSide.vue
  26. 1 1
      src/modules/portal/views/home/LinkTitles.vue
  27. 11 4
      src/modules/print/view/CourseStatistic.vue
  28. 11 4
      src/modules/print/view/ExamStructure.vue
  29. 11 4
      src/modules/print/view/Project.vue
  30. 42 0
      src/styles/bootstrap.scss
  31. 11 0
      src/styles/elementuiCustomize.css
  32. 2 0
      src/styles/global.css
  33. 395 17
      yarn.lock

+ 174 - 3
UI规范.md

@@ -1,13 +1,184 @@
 # 背景
 
-UI 规范本来应该由 UI 设计师来确定,但在设计师缺失的情况下,仅靠程序员也能做出一种中规中矩的 UI。
+UI 规范本来应该由 UI 设计师来确定,但在设计师缺失的情况下,仅靠程序员也能高效方便的做出一种中规中矩的 UI。  
+本文以 Web 为设计目标,移动端原生应用有很大不同,但可以根据这些章节做对应修改。  
+本文考虑能应用到 mobile first 的场景。
 
 ## 需求
 
-程序员一般不具备整体的页面设计能力,所以需要提供的是明确的指令和模板。
+程序员一般不具备整体的页面设计能力,所以需要提供的是明确的指令和模板。  
+程序员不应该深入设计细节,应该通过表达意图,而不是具体细节来完成业务。  
+意图:按钮:主要,大小。
+默认对齐:文字在不同的容器内对齐方式不一样,按钮、表格、标题。元素之间的对齐。
 
-#### TODO
+- 常用的页面模板。登录,注册,主页,顶部导航,侧边导航,表单查询,表格。
+- 按钮的类型。
+
+css reset
+h1 div container responsive
+
+normal-text
+rem: root em
+em: container em
+em 与组件库之间的关系
+浏览器默认的字体是 16px。
+
+字体大小会随着设备的大小而调整?必要性?设备大小,只影响布局?
+
+块之间的间距。间距来标明各块之间的亲密度。
+相同背景色的块之间的分隔线。
+
+从已有的项目中抽取规范。
+
+```s
+.title-text {
+  font-size: 22px;
+  font-weight: 600;
+  line-height: 32px;
+  color: #1a1a1a;
+}
+```
+
+## 布局
+
+### header
+
+```s
+.bd-navbar {
+  min-height: 4rem;
+}
+.navbar {
+}
+```
+
+### 侧边栏 sidebar
+
+### 底边 footer
+
+### 默认的边距(margin/padding)
+
+默认的边距为$spacer,$spacer 为 1rem。mt、py-2 等等为定制的边距。mt-n2 可以为负的 margin。
+
+### 模块间距
+
+一般的 padding 是 1rem。
+column 的 padding 是 15px。但 rem/html_font-size 是 16px,这里做一下改变?
+
+### 行高 line-height
+
+### 段落间距 paragraph margin
+
+### 间距的渐进(亲密性)
+
+导航以颜色来区分。  
+模块以线条分割。
+标题与正文之间间隔 2rem。
+正文的 line-height 为 1.5rem。
+段落之间的分割为 1rem?
+
+## 颜色
+
+- 标题颜色 #000000
+- 提示颜色 #666666
+- 文字点击状态 #FF8900
+- 文字悬浮颜色
+- 链接颜色
+- 链接悬浮变色
+- 品牌色
+- 正文色
+- 标题色
+- 副标题色
+- 作者、日期等色
+- 背景色
+- 边框色
+- 输入框填充色
+- 阴影色
+- 成功操作颜色
+- 失败操作颜色
+
+## 字体
+
+### font-family
+
+优先采用系统默认字体。
+
+```s
+  // Safari for OS X and iOS (San Francisco)
+  -apple-system,
+  // Windows
+  "Segoe UI",
+  // Android
+  "Roboto",
+  // Basic web fallback
+  "Helvetica Neue", Arial, sans-serif,
+```
+
+### font-size
+
+### font-weight
+
+## 图片
+
+### svg
+
+### 应用本身的图片尺寸
+
+顶部导航图标 48
+个人中心指示性图标 32
+
+### 图片与描述的间距
+
+0.5rem?
+
+### 按钮中图片与文字的间距,line-height,font-size
+
+间距 0.5em ?
+图片与文字高度一致
+
+### 按钮中图片的变色
+
+### 透明度
+
+透明度可以用来对比重要和不重要,启用和禁用。
+
+## 样例
+
+## Bootstrap 链接
+
+### 定制
+
+### Reboot
+
+### 颜色
+
+### 表单对齐
+
+### 表格对齐
+
+### 水平居中
+
+### 垂直居中
+
+### 水平和垂直居中
+
+### Utilities
+
+### ElementUI
+
+## TODO
 
 - UI guildlines auto check
 - flex class (bootstrap container class)
 - media query breakpoint
+- border / line-height
+- color variables
+- namespace
+- 定制已有组件
+- 科普:颜色对比度。像素,ppi。
+- z-index 规划
+- sketch=ui axure=product js/css/html=component
+- 网页
+- animation
+
+https://zellwk.com/blog/rem-vs-em/
+https://www.designbetter.co/design-systems-handbook

+ 3 - 0
package.json

@@ -11,6 +11,7 @@
   },
   "dependencies": {
     "axios": "^0.18.0",
+    "bootstrap": "^4.2.1",
     "element-ui": "^2.4.9",
     "lodash": "^4.17.11",
     "moment": "^2.22.2",
@@ -37,6 +38,8 @@
     "babel-jest": "^23.6.0",
     "eslint": "^5.8.0",
     "eslint-plugin-vue": "^5.0.0-0",
+    "node-sass": "^4.9.0",
+    "sass-loader": "^7.0.1",
     "vue-cli-plugin-axios": "0.0.4",
     "vue-cli-plugin-element": "^1.0.0",
     "vue-template-compiler": "^2.5.21"

+ 47 - 0
src/components/EcsFormSearch.vue

@@ -0,0 +1,47 @@
+<template>
+  <section class="content">
+    <!-- 表单 -->
+    <el-form
+      ref="resetEcsFormSearch"
+      :inline="!advanceSearch"
+      :model="model"
+      :advance-search="advanceSearch"
+      :label-position="labelPosition"
+      :label-width="advanceSearch ? labelWidth : 'auto'"
+    >
+      <slot />
+    </el-form>
+
+    <div
+      style="width: 100%; border-bottom: 1px solid #eee; margin: 10px 0;"
+    ></div>
+  </section>
+</template>
+<script>
+export default {
+  name: "EcsFormSearch",
+  props: {
+    model: Object,
+    advanceSearch: {
+      type: Boolean,
+      default: false
+    },
+    labelPosition: {
+      type: String,
+      default: "left"
+    },
+    labelWidth: {
+      type: String,
+      default: "100px"
+    }
+  },
+  data() {
+    return {
+      // inline: true,
+      // formLabelWidth: ""
+    };
+  }
+};
+</script>
+
+<style scoped></style>

+ 1 - 1
src/components/LinkTitlesCustom.vue

@@ -2,7 +2,7 @@
   <el-breadcrumb
     v-if="currentPaths.length > 0"
     separator-class="el-icon-arrow-right"
-    style="border-bottom: 1px solid #aaa; padding-bottom: 5px; margin-top: -20px; margin-bottom: 20px"
+    style="border-bottom: 1px solid #eee; padding-bottom: 5px; margin-top: -20px; margin-bottom: 20px"
   >
     <el-breadcrumb-item :to="{ path: '/home/overview' }">
       首页

+ 16 - 7
src/components/ckeditor.vue

@@ -1,17 +1,24 @@
 <template>
-  <div class="ckeditor">
-    <textarea
-      :id="id"
-      :display="display"
-      :value="value"
-      class="el-textarea__inner"
-    ></textarea>
+  <div :style="divStyle">
+    <div class="ckeditor">
+      <textarea
+        :id="id"
+        :display="display"
+        :value="value"
+        class="el-textarea__inner"
+      ></textarea>
+    </div>
   </div>
 </template>
 
 <script>
 let inc = 0;
 export default {
+  data() {
+    return {
+      divStyle: ""
+    };
+  },
   props: {
     display: {
       type: String,
@@ -52,6 +59,8 @@ export default {
     }
   },
   mounted() {
+    this.divStyle = this.divStyle + "width:" + this.width + ";";
+
     let config = {
       language: this.language,
       height: this.height,

+ 4 - 0
src/main.js

@@ -8,7 +8,9 @@ import "./plugins/axios";
 import "./plugins/vueAwesome";
 import "./directives/directives.js";
 import "./filters/filters.js";
+import "./styles/bootstrap.scss";
 import "./styles/global.css";
+import EcsFormSearch from "./components/EcsFormSearch";
 
 Vue.config.productionTip = process.env.NODE_ENV !== "production";
 
@@ -19,6 +21,8 @@ if (
   require("./plugins/vueLifecylceLogs");
 }
 
+Vue.component("ecs-form-search", EcsFormSearch);
+
 new Vue({
   router,
   store,

+ 103 - 87
src/modules/basic/view/campus.vue

@@ -7,77 +7,81 @@
         element-loading-text="机构上传中,请稍后..."
       >
         <!-- 表单 -->
-        <el-form
-          :inline="true"
-          :model="formSearch"
-          label-position="right"
-          label-width="100"
-        >
-          <el-row :gutter="5">
-            <el-form-item label="顶级机构" class="pull-left">
-              <el-select
-                class="input_width_lg"
-                v-model="formSearch.parentId"
-                placeholder="请选择"
-                :disabled="!isSuperAdmin"
-              >
-                <el-option
-                  v-for="item in rootOrgList"
-                  :label="item.name"
-                  :value="item.id"
-                  :key="item.id"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="中心代码" class="pull-left">
-              <el-input
-                placeholder="请输入学习中心代码"
-                v-model="formSearch.code"
+        <ecs-form-search :model="formSearch">
+          <el-form-item label="顶级机构">
+            <el-select
+              v-model="formSearch.parentId"
+              placeholder="请选择"
+              :disabled="!isSuperAdmin"
+            >
+              <el-option
+                v-for="item in rootOrgList"
+                :label="item.name"
+                :value="item.id"
+                :key="item.id"
               />
-            </el-form-item>
-            <el-form-item label="中心名称" class="pull-left">
-              <el-input
-                placeholder="请输入学习中心名称"
-                v-model="formSearch.name"
-              />
-            </el-form-item>
-            <el-form-item class="pull-right">
-              <el-button
-                size="small"
-                type="primary"
-                icon="search"
-                @click="searchForm"
-              >
-                查询
-              </el-button>
-              <el-button
-                size="small"
-                type="primary"
-                icon="plus"
-                @click="insert"
-              >
-                新增
-              </el-button>
-              <el-button
-                size="small"
-                type="primary"
-                icon="upload2"
-                @click="imp"
-              >
-                导入
-              </el-button>
-              <el-button size="small" type="success" @click="enableOrg">
-                <i class="fa fa-check" aria-hidden="true"></i>启用
-              </el-button>
-              <el-button size="small" type="danger" @click="disableOrg">
-                <i class="fa fa-close" aria-hidden="true"></i>禁用
-              </el-button>
-            </el-form-item>
-          </el-row>
-        </el-form>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="中心代码">
+            <el-input
+              placeholder="请输入学习中心代码"
+              v-model="formSearch.code"
+            />
+          </el-form-item>
+          <el-form-item label="中心名称">
+            <el-input
+              placeholder="请输入学习中心名称"
+              v-model="formSearch.name"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-search"
+              @click="searchForm"
+            >
+              查询
+            </el-button>
+            <el-button size="small" @click="resetEcsFormSearch">
+              重置
+            </el-button>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-plus"
+              @click="insert"
+            >
+              新增
+            </el-button>
+          </el-form-item>
+        </ecs-form-search>
+
+        <span>批量操作:</span>
+        <el-button
+          size="small"
+          type="success"
+          :disabled="noBatchSelected"
+          @click="enableOrg"
+        >
+          <i class="fa fa-check" aria-hidden="true"></i>启用
+        </el-button>
+        <el-button
+          size="small"
+          type="danger"
+          :disabled="noBatchSelected"
+          @click="disableOrg"
+        >
+          <i class="fa fa-close" aria-hidden="true"></i>禁用
+        </el-button>
+        <el-button size="small" type="primary" icon="upload2" @click="imp">
+          导入
+        </el-button>
+
+        <div style="width: 100%;margin-bottom: 10px;"></div>
 
         <!-- 添加或修改学习中心弹出框 -->
-        <el-dialog title="中心信息" :visible.sync="campusDialog">
+        <el-dialog title="中心信息" width="400px" :visible.sync="campusDialog">
           <el-form
             :inline="true"
             :model="campusForm"
@@ -146,7 +150,7 @@
                 </el-radio-group>
               </el-form-item>
             </el-row>
-            <el-row class="pull_center">
+            <el-row class="d-flex justify-content-center">
               <el-button type="primary" @click="submitForm">保 存</el-button>
               <el-button @click="campusDialog = false">取 消</el-button>
             </el-row>
@@ -154,7 +158,7 @@
         </el-dialog>
 
         <!-- 导入弹窗 -->
-        <el-dialog title="导入窗口" :visible.sync="impDialog">
+        <el-dialog title="导入窗口" width="460px" :visible.sync="impDialog">
           <el-form>
             <el-row>
               <el-form-item style="margin-left:20px">
@@ -177,7 +181,7 @@
                     选择文件
                   </el-button>
                   &nbsp;
-                  <el-button size="small" type="success" @click="submitUpload">
+                  <el-button size="small" type="primary" @click="submitUpload">
                     确认上传
                   </el-button>
                   <el-button size="small" type="danger" @click="removeFile">
@@ -213,10 +217,10 @@
           border
           resizable
           stripe
-          style="width: 100%;text-align:center;"
+          style="width: 100%;"
           @selection-change="selectChange"
         >
-          <el-table-column type="selection" width="55" />
+          <el-table-column type="selection" width="35" />
           <el-table-column width="50" label="ID">
             <span slot-scope="scope">{{ scope.row.id }}</span>
           </el-table-column>
@@ -236,21 +240,23 @@
             <span slot-scope="scope">{{ scope.row.updateTime }}</span>
           </el-table-column>
           <el-table-column width="70" label="状态">
-            <span slot-scope="scope">
-              <el-tag :type="getTag(scope.row.enable)">
-                {{ getStatus(scope.row.enable) }}
-              </el-tag>
-            </span>
+            <span slot-scope="scope"> {{ getStatus(scope.row.enable) }} </span>
           </el-table-column>
           <el-table-column :context="_self" label="操作">
             <div slot-scope="scope">
-              <el-button size="mini" type="primary" @click="edit(scope.row)">
+              <el-button
+                size="mini"
+                type="primary"
+                plain
+                @click="edit(scope.row)"
+              >
                 <i class="el-icon-edit"></i> 编辑
               </el-button>
               <el-button
                 size="mini"
                 type="primary"
                 @click="toExamSite(scope.row)"
+                plain
               >
                 考点设置
               </el-button>
@@ -262,7 +268,9 @@
             @current-change="handleCurrentChange"
             :current-page="currentPage"
             :page-size="pageSize"
-            layout="total, prev, pager, next, jumper"
+            :page-sizes="[10, 30, 50, 100]"
+            @size-change="handleSizeChange"
+            layout="total, sizes, prev, pager, next, jumper"
             :total="total"
           />
         </div>
@@ -338,9 +346,22 @@ export default {
         }
       }
       return orgIds;
+    },
+    noBatchSelected() {
+      return this.selectedOrgIds.length === 0;
     }
   },
   methods: {
+    resetEcsFormSearch() {
+      this.formSearch = Object.assign(this.formSearch, {
+        code: "",
+        name: ""
+      });
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.searchForm();
+    },
     toExamSite(row) {
       this.$router.push({ path: "/basic/examSite/" + row.id });
     },
@@ -583,11 +604,10 @@ export default {
       }
     },
     uploadError(response) {
-      var jsonStr = response.message.substring(4);
-      var resp = eval("(" + jsonStr + ")");
+      var json = JSON.parse(response.message);
       if (response.status == 500) {
         this.$notify({
-          message: resp.desc,
+          message: json.desc,
           type: "error"
         });
       }
@@ -674,10 +694,6 @@ export default {
   margin-top: 10px;
 }
 
-.el-table th > .cell {
-  text-align: center;
-}
-
 .el-upload {
   width: 80px;
 }

+ 9 - 9
src/modules/basic/view/course.vue

@@ -275,11 +275,7 @@
           </el-form>
 
           <!-- 专业列表 -->
-          <el-table
-            :data="specialtyTableData"
-            border
-            style="width: 100%;text-align:center;"
-          >
+          <el-table :data="specialtyTableData" border>
             <el-table-column prop="id" label="ID" width="150" />
             <el-table-column prop="name" label="专业名称" width="250" />
             <el-table-column prop="code" label="专业代码" />
@@ -303,7 +299,6 @@
               @current-change="handleSpecialtyCurrentChange"
               :current-page="currentSpecialtyPage"
               :page-size="10"
-              layout="total, prev, pager, next, jumper"
               :total="specialtyTotal"
             />
           </div>
@@ -355,10 +350,9 @@
           border
           resizable
           stripe
-          style="width: 100%;text-align:center;"
           @selection-change="selectChange"
         >
-          <el-table-column type="selection" width="50" />
+          <el-table-column type="selection" width="35" />
           <el-table-column prop="id" label="课程ID" width="80" />
           <el-table-column prop="name" label="课程名称" width="180" />
           <el-table-column prop="code" label="课程代码" />
@@ -417,7 +411,9 @@
             @current-change="handleCurrentChange"
             :current-page="currentPage"
             :page-size="10"
-            layout="total, prev, pager, next, jumper"
+            :page-sizes="[10, 30, 50, 100]"
+            @size-change="handleSizeChange"
+            layout="total, sizes, prev, pager, next, jumper"
             :total="total"
           >
           </el-pagination>
@@ -592,6 +588,10 @@ export default {
     }
   },
   methods: {
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.searchForm();
+    },
     deleteRelation(row) {
       var specialtyId = row.id;
       var courseId = this.specialtySearchForm.courseId;

+ 192 - 168
src/modules/basic/view/exam_site.vue

@@ -1,186 +1,203 @@
 <template>
-  <section class="content">
-    <div class="box box-info">
-      <div class="box-body">
-        <!-- 表单 -->
-        <el-form
-          :inline="true"
-          :model="formSearch"
-          label-position="right"
-          label-width="100px"
-        >
-          <el-row :gutter="5">
-            <el-form-item label="学习中心" class="pull-left">
-              <el-input v-model="orgName" readonly />
-            </el-form-item>
-            <el-form-item label="考点代码" class="pull-left">
-              <el-input
-                placeholder="请输入考点代码"
-                v-model="formSearch.code"
-              />
-            </el-form-item>
-            <el-form-item label="考点名称" class="pull-left">
-              <el-input
-                placeholder="请输入考点名称"
-                v-model="formSearch.name"
-              />
-            </el-form-item>
-            <el-form-item class="pull-right">
-              <el-button
-                size="small"
-                type="primary"
-                icon="search"
-                @click="searchForm"
-              >
-                查询
-              </el-button>
-              <el-button
-                size="small"
-                type="primary"
-                icon="plus"
-                @click="insert"
-              >
-                新增
-              </el-button>
-              <el-button size="small" type="danger" @click="deleteByIds">
-                <i class="el-icon-delete"></i>删除
-              </el-button>
-              <el-button size="small" type="info" @click="back">
-                退回
-              </el-button>
-            </el-form-item>
-          </el-row>
-        </el-form>
+  <div>
+    <LinkTitlesCustom :currentPaths="['机构管理 ', '中心列表', '考点设置']" />
 
-        <!-- 添加考点信息弹出框 -->
-        <el-dialog title="考点信息" :visible.sync="examSiteDialog">
-          <el-form
-            :inline="true"
-            :model="examSiteForm"
-            ref="examSiteForm"
-            :rules="rules"
-            label-position="right"
-            label-width="90px"
-          >
+    <section class="content">
+      <div class="box box-info">
+        <div class="box-body">
+          <!-- 表单 -->
+          <ecs-form-search :model="formSearch">
             <el-row>
-              <el-form-item label="学习中心" label-width="120px" prop="code">
-                <el-input
-                  class="pull_length"
-                  v-model="orgName"
-                  auto-complete="off"
-                  placeholder="中心代码"
-                  readonly
-                />
+              <el-form-item label="学习中心">
+                <el-input v-model="orgName" disabled />
               </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="考点代码" label-width="120px" prop="code">
+              <el-form-item label="考点代码">
                 <el-input
-                  class="pull_length"
-                  v-model="examSiteForm.code"
-                  auto-complete="off"
-                  placeholder="考点代码"
-                  :readonly="null != examSiteForm.id"
+                  placeholder="请输入考点代码"
+                  v-model="formSearch.code"
                 />
               </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="考点名称" label-width="120px" prop="name">
-                <el-input
-                  class="pull_length"
-                  v-model="examSiteForm.name"
-                  auto-complete="off"
-                  placeholder="考点名称"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="负责人" label-width="120px">
-                <el-input
-                  class="pull_length"
-                  v-model="examSiteForm.contacts"
-                  auto-complete="off"
-                  placeholder="负责人"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="联系方式" label-width="120px">
+              <el-form-item label="考点名称">
                 <el-input
-                  class="pull_length"
-                  v-model="examSiteForm.telephone"
-                  auto-complete="off"
-                  placeholder="联系方式"
+                  placeholder="请输入考点名称"
+                  v-model="formSearch.name"
                 />
               </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="备注" label-width="120px">
-                <el-input
-                  class="pull_length"
-                  v-model="examSiteForm.remark"
-                  auto-complete="off"
-                  placeholder="备注"
-                />
+              <el-form-item>
+                <el-button
+                  size="small"
+                  type="primary"
+                  icon="el-icon-search"
+                  @click="searchForm"
+                >
+                  查询
+                </el-button>
+                <el-button size="small" @click="resetSearchForm">
+                  重置
+                </el-button>
+                <el-button
+                  size="small"
+                  type="primary"
+                  icon="el-icon-plus"
+                  @click="insert"
+                >
+                  新增
+                </el-button>
+                <el-button size="small" type="info" @click="back">
+                  退回
+                </el-button>
               </el-form-item>
             </el-row>
-            <el-row class="pull_center">
-              <el-button type="primary" @click="submitForm">保 存</el-button>
-              <el-button @click="examSiteDialog = false">取 消</el-button>
-            </el-row>
-          </el-form>
-        </el-dialog>
+          </ecs-form-search>
+
+          <!-- 添加考点信息弹出框 -->
+          <el-dialog
+            title="考点信息"
+            width="400px"
+            :visible.sync="examSiteDialog"
+          >
+            <el-form
+              :inline="true"
+              inline-message
+              :model="examSiteForm"
+              ref="examSiteForm"
+              :rules="rules"
+              label-position="right"
+              label-width="90px"
+            >
+              <el-row>
+                <el-form-item label="学习中心" label-width="120px" prop="code">
+                  <el-input
+                    class="pull_length"
+                    v-model="orgName"
+                    auto-complete="off"
+                    placeholder="中心代码"
+                    disabled
+                  />
+                </el-form-item>
+              </el-row>
+              <el-row>
+                <el-form-item label="考点代码" label-width="120px" prop="code">
+                  <el-input
+                    class="pull_length"
+                    v-model="examSiteForm.code"
+                    auto-complete="off"
+                    placeholder="考点代码"
+                    :readonly="null != examSiteForm.id"
+                  />
+                </el-form-item>
+              </el-row>
+              <el-row>
+                <el-form-item label="考点名称" label-width="120px" prop="name">
+                  <el-input
+                    class="pull_length"
+                    v-model="examSiteForm.name"
+                    auto-complete="off"
+                    placeholder="考点名称"
+                  />
+                </el-form-item>
+              </el-row>
+              <el-row>
+                <el-form-item label="负责人" label-width="120px">
+                  <el-input
+                    class="pull_length"
+                    v-model="examSiteForm.contacts"
+                    auto-complete="off"
+                    placeholder="负责人"
+                  />
+                </el-form-item>
+              </el-row>
+              <el-row>
+                <el-form-item label="联系方式" label-width="120px">
+                  <el-input
+                    class="pull_length"
+                    v-model="examSiteForm.telephone"
+                    auto-complete="off"
+                    placeholder="联系方式"
+                  />
+                </el-form-item>
+              </el-row>
+              <el-row>
+                <el-form-item label="备注" label-width="120px">
+                  <el-input
+                    class="pull_length"
+                    v-model="examSiteForm.remark"
+                    auto-complete="off"
+                    placeholder="备注"
+                  />
+                </el-form-item>
+              </el-row>
+              <el-row class="d-flex justify-content-center">
+                <el-button type="primary" @click="submitForm">保 存</el-button>
+                <el-button @click="examSiteDialog = false">取 消</el-button>
+              </el-row>
+            </el-form>
+          </el-dialog>
+
+          <span>批量操作:</span>
+          <el-button
+            size="small"
+            type="danger"
+            icon="el-icon-delete"
+            @click="deleteByIds"
+          >
+            删除
+          </el-button>
 
-        <!-- 页面列表 -->
-        <el-table
-          :data="tableData"
-          border
-          resizable
-          stripe
-          style="width: 100%;text-align:center;"
-          @selection-change="selectChange"
-        >
-          <el-table-column type="selection" width="50" />
-          <el-table-column prop="id" width="80" label="ID" />
-          <el-table-column prop="orgName" label="学习中心" />
-          <el-table-column prop="code" label="考点代码" />
-          <el-table-column prop="name" label="考点名称" />
-          <el-table-column prop="contacts" width="100" label="负责人" />
-          <el-table-column prop="telephone" width="100" label="联系方式" />
-          <el-table-column prop="remark" width="150" label="备注" />
-          <el-table-column prop="updateTime" width="180" label="更新时间" />
-          <el-table-column label="操作" width="180">
-            <div slot-scope="scope">
-              <el-button size="mini" type="primary" @click="edit(scope.row)">
-                <i class="el-icon-edit"></i> 修改
-              </el-button>
-              <el-button
-                size="mini"
-                type="danger"
-                @click="deleteById(scope.row)"
-              >
-                <i class="el-icon-delete"></i> 删除
-              </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"
-          />
+          <div style="width: 100%;margin-bottom: 10px;"></div>
+
+          <!-- 页面列表 -->
+          <el-table
+            :data="tableData"
+            border
+            resizable
+            stripe
+            @selection-change="selectChange"
+          >
+            <el-table-column type="selection" width="35" />
+            <el-table-column prop="id" width="80" label="ID" />
+            <el-table-column prop="code" label="考点代码" />
+            <el-table-column prop="name" label="考点名称" />
+            <el-table-column prop="contacts" width="100" label="负责人" />
+            <el-table-column prop="telephone" width="100" label="联系方式" />
+            <el-table-column prop="remark" width="120" label="备注" />
+            <el-table-column prop="updateTime" width="180" label="更新时间" />
+            <el-table-column label="操作" width="180">
+              <div slot-scope="scope">
+                <el-button size="mini" type="primary" @click="edit(scope.row)">
+                  <i class="el-icon-edit"></i> 编辑
+                </el-button>
+                <el-button
+                  size="mini"
+                  type="danger"
+                  @click="deleteById(scope.row)"
+                >
+                  <i class="el-icon-delete"></i> 删除
+                </el-button>
+              </div>
+            </el-table-column>
+          </el-table>
+          <div class="page pull-right">
+            <el-pagination
+              @current-change="handleCurrentChange"
+              :current-page="currentPage"
+              :page-size="pageSize"
+              :page-sizes="[10, 30, 50, 100]"
+              @size-change="handleSizeChange"
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+            />
+          </div>
         </div>
       </div>
-    </div>
-  </section>
+    </section>
+  </div>
 </template>
 
 <script>
 import { CORE_API } from "@/constants/constants.js";
 import { mapState } from "vuex";
+import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
 
 export default {
   name: "ExamSite",
@@ -237,12 +254,20 @@ export default {
   },
   methods: {
     back() {
-      this.$router.push({ path: "/index/campus" });
+      this.$router.back();
+    },
+    resetSearchForm() {
+      this.formSearch.code = "";
+      this.formSearch.name = "";
     },
     handleCurrentChange(val) {
       this.currentPage = val;
       this.searchForm();
     },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.searchForm();
+    },
     //查询
     searchForm() {
       this.loading = true;
@@ -436,6 +461,9 @@ export default {
     this.orgId = this.$route.params.orgId;
     this.formSearch.orgId = this.$route.params.orgId;
     this.init();
+  },
+  components: {
+    LinkTitlesCustom
   }
 };
 </script>
@@ -445,10 +473,6 @@ export default {
   margin-top: 10px;
 }
 
-.el-table th > .cell {
-  text-align: center;
-}
-
 .el-upload {
   width: 80px;
 }

+ 1 - 7
src/modules/basic/view/privilege_group_list.vue

@@ -2,13 +2,7 @@
   <section class="content">
     <div class="box box-info">
       <div class="box-body">
-        <el-table
-          :data="privilegeGroupList"
-          border
-          resizable
-          stripe
-          style="width: 100%;text-align:center;"
-        >
+        <el-table :data="privilegeGroupList" border resizable stripe>
           <el-table-column prop="id" label="ID" width="100" />
           <el-table-column prop="code" label="权限组编码" />
           <el-table-column prop="name" label="权限组名称" />

+ 273 - 272
src/modules/basic/view/school.vue

@@ -1,294 +1,287 @@
 <template>
   <section class="content">
-    <div class="box box-info">
-      <div class="box-body">
-        <!-- 表单 -->
+    <div class="box-body">
+      <!-- 表单 -->
+      <el-form :inline="true" :model="formSearch">
+        <el-form-item label="学校名称">
+          <el-input placeholder="请输入学校名称" v-model="formSearch.name" />
+        </el-form-item>
+        <el-form-item label="学校代码">
+          <el-input placeholder="请输入学校代码" v-model="formSearch.code" />
+        </el-form-item>
+        <el-form-item label="学校域名">
+          <el-input
+            placeholder="请输入学校域名"
+            v-model="formSearch.domainName"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            size="small"
+            type="primary"
+            icon="search"
+            @click="searchForm"
+          >
+            查询
+          </el-button>
+          <el-button size="small" @click="resetSearchForm"> 重置 </el-button>
+          <el-button size="small" type="primary" icon="plus" @click="insert">
+            新增
+          </el-button>
+        </el-form-item>
+      </el-form>
+
+      <div
+        style="width: 100%; border-bottom: 1px solid #eee; margin: 20px 0 ;"
+      ></div>
+
+      <span>批量操作:</span>
+      <el-button
+        size="small"
+        type="success"
+        :disabled="noBatchSelected"
+        @click="enableOrg"
+      >
+        <i class="fa fa-check" aria-hidden="true"></i>启用
+      </el-button>
+      <el-button
+        size="small"
+        type="danger"
+        :disabled="noBatchSelected"
+        @click="disableOrg"
+      >
+        <i class="fa fa-close" aria-hidden="true"></i>禁用
+      </el-button>
+
+      <div style="width: 100%;margin-bottom: 10px;"></div>
+
+      <!-- 添加或修改学校弹出框 -->
+      <el-dialog title="学校信息" width="400px" :visible.sync="schoolDialog">
         <el-form
           :inline="true"
-          :model="formSearch"
+          :model="schoolForm"
+          ref="schoolForm"
+          :rules="rules"
           label-position="right"
-          label-width="100px"
+          label-width="90px"
         >
-          <el-row :gutter="5">
-            <el-form-item label="学校名称" class="pull-left">
+          <el-row>
+            <el-form-item label="学校代码" label-width="120px" prop="code">
               <el-input
-                placeholder="请输入学校名称"
-                v-model="formSearch.name"
+                class="pull_length"
+                v-model="schoolForm.code"
+                auto-complete="off"
+                placeholder="学校域名"
+                :disabled="null != schoolForm.id"
               />
             </el-form-item>
-            <el-form-item label="学校代码" class="pull-left">
+          </el-row>
+          <el-row>
+            <el-form-item label="学校名称" label-width="120px" prop="name">
               <el-input
-                placeholder="请输入学校代码"
-                v-model="formSearch.code"
+                class="pull_length"
+                v-model="schoolForm.name"
+                auto-complete="off"
+                placeholder="学校名称"
               />
             </el-form-item>
-            <el-form-item label="学校域名" class="pull-left">
+          </el-row>
+          <el-row>
+            <el-form-item
+              label="学校域名"
+              label-width="120px"
+              prop="domainName"
+            >
               <el-input
-                placeholder="请输入学校域名"
-                v-model="formSearch.domainName"
+                class="pull_length"
+                v-model="schoolForm.domainName"
+                auto-complete="off"
+                placeholder="学校域名"
               />
             </el-form-item>
-            <el-form-item class="pull-right">
-              <el-button
-                size="small"
-                type="primary"
-                icon="search"
-                @click="searchForm"
-              >
-                查询
-              </el-button>
-              <el-button
-                size="small"
-                type="primary"
-                icon="plus"
-                @click="insert"
-              >
-                新增
-              </el-button>
-              <el-button size="small" type="success" @click="enableOrg">
-                <i class="fa fa-check" aria-hidden="true"></i>启用
-              </el-button>
-              <el-button size="small" type="danger" @click="disableOrg">
-                <i class="fa fa-close" aria-hidden="true"></i>禁用
-              </el-button>
+          </el-row>
+          <el-row>
+            <el-form-item label="负责人" label-width="120px" prop="contacts">
+              <el-input
+                class="pull_length"
+                v-model="schoolForm.contacts"
+                auto-complete="off"
+                placeholder="负责人"
+              />
+            </el-form-item>
+          </el-row>
+          <el-row>
+            <el-form-item label="联系方式" label-width="120px" prop="telephone">
+              <el-input
+                class="pull_length"
+                v-model="schoolForm.telephone"
+                auto-complete="off"
+                placeholder="联系方式"
+              />
+            </el-form-item>
+          </el-row>
+          <el-row>
+            <el-form-item label="考生端产品名" label-width="120px">
+              <el-input
+                class="pull_length"
+                v-model="schoolForm.properties.OE_STUDENT_SYS_NAME"
+                auto-complete="off"
+                placeholder="考生端产品名"
+              />
             </el-form-item>
           </el-row>
+          <el-row>
+            <el-form-item label="状态" label-width="120px" prop="enable">
+              <el-radio-group class="pull_right_sm" v-model="schoolForm.enable">
+                <el-radio label="true">启用</el-radio>
+                <el-radio label="false">禁用</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-row>
+          <el-row class="d-flex justify-content-center">
+            <el-button type="primary" @click="submitForm">保 存</el-button>
+            <el-button @click="schoolDialog = false">取 消</el-button>
+          </el-row>
         </el-form>
+      </el-dialog>
 
-        <!-- 添加或修改学校弹出框 -->
-        <el-dialog title="学校信息" :visible.sync="schoolDialog">
-          <el-form
-            :inline="true"
-            :model="schoolForm"
-            ref="schoolForm"
-            :rules="rules"
-            label-position="right"
-            label-width="90px"
-          >
-            <el-row>
-              <el-form-item label="学校代码" label-width="120px" prop="code">
-                <el-input
-                  class="pull_length"
-                  v-model="schoolForm.code"
-                  auto-complete="off"
-                  placeholder="学校域名"
-                  :disabled="null != schoolForm.id"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="学校名称" label-width="120px" prop="name">
-                <el-input
-                  class="pull_length"
-                  v-model="schoolForm.name"
-                  auto-complete="off"
-                  placeholder="学校名称"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item
-                label="学校域名"
-                label-width="120px"
-                prop="domainName"
-              >
-                <el-input
-                  class="pull_length"
-                  v-model="schoolForm.domainName"
-                  auto-complete="off"
-                  placeholder="学校域名"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="负责人" label-width="120px" prop="contacts">
-                <el-input
-                  class="pull_length"
-                  v-model="schoolForm.contacts"
-                  auto-complete="off"
-                  placeholder="负责人"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item
-                label="联系方式"
-                label-width="120px"
-                prop="telephone"
+      <!-- 学校产品分配弹出框 -->
+      <el-dialog title="产品分配" :visible.sync="functionDialog">
+        <div>
+          <el-button type="primary" @click="saveOrgFunction"> 保 存 </el-button>
+          <el-button @click="functionDialog = false">取 消</el-button>
+        </div>
+      </el-dialog>
+
+      <!-- logo上传弹窗 -->
+      <el-dialog title="logo上传" width="350px" :visible.sync="logoDialog">
+        <el-form inline>
+          <el-row>
+            <el-form-item label="学校名称">
+              <el-input class="pull_length" v-model="curSchool.name" disabled />
+            </el-form-item>
+            <el-form-item label="学校代码">
+              <el-input class="pull_length" v-model="curSchool.code" disabled />
+            </el-form-item>
+            <el-form-item>
+              <el-upload
+                class="form_left"
+                ref="upload"
+                accept="image/*"
+                :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-input
-                  class="pull_length"
-                  v-model="schoolForm.telephone"
-                  auto-complete="off"
-                  placeholder="联系方式"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="考生端产品名" label-width="120px">
-                <el-input
-                  class="pull_length"
-                  v-model="schoolForm.properties.OE_STUDENT_SYS_NAME"
-                  auto-complete="off"
-                  placeholder="考生端产品名"
-                />
-              </el-form-item>
-            </el-row>
-            <el-row>
-              <el-form-item label="状态" label-width="120px" prop="enable">
-                <el-radio-group
-                  class="pull_right_sm"
-                  v-model="schoolForm.enable"
-                >
-                  <el-radio label="true">启用</el-radio>
-                  <el-radio label="false">禁用</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-row>
-            <el-row class="pull_center">
-              <el-button type="primary" @click="submitForm">保 存</el-button>
-              <el-button @click="schoolDialog = false">取 消</el-button>
-            </el-row>
-          </el-form>
-        </el-dialog>
+                <el-button size="small" slot="trigger" type="primary">
+                  选择文件
+                </el-button>
+                &nbsp;
+                <el-button size="small" type="success" @click="submitUpload">
+                  确认上传
+                </el-button>
+                <el-button size="small" type="danger" @click="removeFile">
+                  清空文件
+                </el-button>
+                <div slot="tip" class="el-upload__tip">只能上传图片</div>
+              </el-upload>
+            </el-form-item>
+          </el-row>
+        </el-form>
+      </el-dialog>
 
-        <!-- 学校产品分配弹出框 -->
-        <el-dialog title="产品分配" :visible.sync="functionDialog">
-          <div>
-            <el-button type="primary" @click="saveOrgFunction">
-              保 存
+      <!-- 页面列表 -->
+      <el-table
+        :data="tableData"
+        border
+        resizable
+        stripe
+        @selection-change="selectChange"
+      >
+        <el-table-column type="selection" width="35" />
+        <el-table-column prop="id" label="ID" width="60" />
+        <el-table-column label="学校名称">
+          <template slot-scope="scope">
+            <el-popover trigger="hover" placement="left">
+              <div style="font-size: 18px;font-family: 新宋体">
+                <tr>
+                  <td style="color: green">学校名称</td>
+                  <td style="color:purple;padding-left: 20px;">
+                    {{ scope.row.name }}
+                  </td>
+                </tr>
+                <tr>
+                  <td style="color: green">学校代码</td>
+                  <td style="color:purple;padding-left: 20px;">
+                    {{ scope.row.code }}
+                  </td>
+                </tr>
+                <tr>
+                  <td style="color: green">负责人</td>
+                  <td style="color:purple;padding-left: 20px;">
+                    {{ scope.row.contacts }}
+                  </td>
+                </tr>
+                <tr>
+                  <td style="color: green">联系方式</td>
+                  <td style="color:purple;padding-left: 20px;">
+                    {{ scope.row.telephone }}
+                  </td>
+                </tr>
+              </div>
+
+              <div slot="reference" class="name-wrapper">
+                <span>{{ scope.row.name }}</span>
+              </div>
+            </el-popover>
+          </template>
+        </el-table-column>
+        <el-table-column prop="domainName" width="190" label="学校域名" />
+        <el-table-column prop="updateTime" width="170" label="更新时间" />
+        <el-table-column width="70" label="状态">
+          <span slot-scope="scope">
+            <!-- <el-tag :type="getTag(scope.row.enable)"> -->
+            {{ getStatus(scope.row.enable) }}
+            <!-- </el-tag> -->
+          </span>
+        </el-table-column>
+        <el-table-column :context="_self" width="200" prop="" label="操作">
+          <div slot-scope="scope">
+            <el-button
+              size="mini"
+              type="primary"
+              plain
+              @click="edit(scope.row)"
+            >
+              <i class="el-icon-edit"></i> 编辑
+            </el-button>
+            <el-button
+              size="mini"
+              type="primary"
+              plain
+              @click="setLogo(scope.row)"
+            >
+              logo上传
             </el-button>
-            <el-button @click="functionDialog = false">取 消</el-button>
           </div>
-        </el-dialog>
-
-        <!-- logo上传弹窗 -->
-        <el-dialog title="logo上传" :visible.sync="logoDialog">
-          <el-form>
-            <el-row>
-              <el-form-item label="学校名称" label-width="120px">
-                <el-input
-                  class="pull_length"
-                  v-model="curSchool.name"
-                  disabled
-                />
-              </el-form-item>
-              <el-form-item label="学校代码" label-width="120px">
-                <el-input
-                  class="pull_length"
-                  v-model="curSchool.code"
-                  disabled
-                />
-              </el-form-item>
-              <el-form-item style="margin-left:20px">
-                <el-upload
-                  class="form_left"
-                  ref="upload"
-                  accept="image/*"
-                  :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>
-                  &nbsp;
-                  <el-button size="small" type="success" @click="submitUpload">
-                    确认上传
-                  </el-button>
-                  <el-button size="small" type="danger" @click="removeFile">
-                    清空文件
-                  </el-button>
-                  <div slot="tip" class="el-upload__tip">只能上传图片</div>
-                </el-upload>
-              </el-form-item>
-            </el-row>
-          </el-form>
-        </el-dialog>
-
-        <!-- 页面列表 -->
-        <el-table
-          :data="tableData"
-          border
-          resizable
-          stripe
-          style="width: 100%;text-align:center;"
-          @selection-change="selectChange"
-        >
-          <el-table-column type="selection" width="50" />
-          <el-table-column prop="id" label="ID" width="60" />
-          <el-table-column label="学校名称">
-            <template slot-scope="scope">
-              <el-popover trigger="hover" placement="left">
-                <div style="font-size: 18px;font-family: 新宋体">
-                  <tr>
-                    <td style="color: green">学校名称</td>
-                    <td style="color:purple;padding-left: 20px;">
-                      {{ scope.row.name }}
-                    </td>
-                  </tr>
-                  <tr>
-                    <td style="color: green">学校代码</td>
-                    <td style="color:purple;padding-left: 20px;">
-                      {{ scope.row.code }}
-                    </td>
-                  </tr>
-                  <tr>
-                    <td style="color: green">负责人</td>
-                    <td style="color:purple;padding-left: 20px;">
-                      {{ scope.row.contacts }}
-                    </td>
-                  </tr>
-                  <tr>
-                    <td style="color: green">联系方式</td>
-                    <td style="color:purple;padding-left: 20px;">
-                      {{ scope.row.telephone }}
-                    </td>
-                  </tr>
-                </div>
-
-                <div slot="reference" class="name-wrapper">
-                  <span>{{ scope.row.name }}</span>
-                </div>
-              </el-popover>
-            </template>
-          </el-table-column>
-          <el-table-column prop="domainName" width="190" label="学校域名" />
-          <el-table-column prop="updateTime" width="170" label="更新时间" />
-          <el-table-column width="100" label="状态">
-            <span slot-scope="scope">
-              <el-tag :type="getTag(scope.row.enable)">
-                {{ getStatus(scope.row.enable) }}
-              </el-tag>
-            </span>
-          </el-table-column>
-          <el-table-column :context="_self" width="200" prop="" label="操作">
-            <div slot-scope="scope">
-              <el-button size="mini" type="primary" @click="edit(scope.row)">
-                <i class="el-icon-edit"></i> 编辑
-              </el-button>
-              <el-button size="mini" type="primary" @click="setLogo(scope.row)">
-                logo上传
-              </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"
-          />
-        </div>
+        </el-table-column>
+      </el-table>
+      <div class="page pull-right">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page="currentPage"
+          :page-size="pageSize"
+          :page-sizes="[10, 30, 50, 100]"
+          @size-change="handleSizeChange"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="total"
+        />
       </div>
     </div>
   </section>
@@ -357,6 +350,9 @@ export default {
   },
   computed: {
     ...mapState({ user: state => state.user }),
+    noBatchSelected() {
+      return this.selectedOrgIds.length === 0;
+    },
     orgIds() {
       var orgIds = "";
       for (let orgId of this.selectedOrgIds) {
@@ -370,6 +366,15 @@ export default {
     }
   },
   methods: {
+    resetSearchForm() {
+      this.formSearch.code = "";
+      this.formSearch.name = "";
+      this.formSearch.domainName = "";
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.searchForm();
+    },
     getStatus(status) {
       if (status == true) {
         return "启用";
@@ -693,10 +698,6 @@ export default {
   margin-top: 10px;
 }
 
-.el-table th > .cell {
-  text-align: center;
-}
-
 .el-upload {
   width: 80px;
 }

+ 11 - 13
src/modules/basic/view/specially.vue

@@ -158,13 +158,7 @@
           </el-form>
 
           <!-- 课程列表 -->
-          <el-table
-            :data="courseTableData"
-            border
-            resizable
-            stripe
-            style="width: 100%;text-align:center;"
-          >
+          <el-table :data="courseTableData" border resizable stripe>
             <el-table-column prop="id" label="ID" width="150" />
             <el-table-column prop="name" label="课程名称" width="250" />
             <el-table-column prop="code" label="课程代码" />
@@ -236,10 +230,9 @@
         <el-table
           :data="tableData"
           border
-          style="width: 100%;text-align:center;"
           @selection-change="handleSelectionChange"
         >
-          <el-table-column type="selection" width="50"> </el-table-column>
+          <el-table-column type="selection" width="35"> </el-table-column>
           <el-table-column prop="id" label="ID" width="60"> </el-table-column>
           <el-table-column prop="code" label="专业代码"> </el-table-column>
           <el-table-column prop="name" label="专业名称"> </el-table-column>
@@ -274,7 +267,9 @@
             @current-change="handleCurrentChange"
             :current-page="currentPage"
             :page-size="pageSize"
-            layout="total, prev, pager, next, jumper"
+            :page-sizes="[10, 30, 50, 100]"
+            @size-change="handleSizeChange"
+            layout="total, sizes, prev, pager, next, jumper"
             :total="total"
           />
         </div>
@@ -443,6 +438,10 @@ export default {
     }
   },
   methods: {
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.searchForm();
+    },
     deleteRelation(row) {
       var courseId = row.id;
       var specialtyId = this.courseSearchForm.specialtyId;
@@ -832,11 +831,10 @@ export default {
       }
     },
     uploadError(response) {
-      var jsonStr = response.message.substring(4);
-      var resp = eval("(" + jsonStr + ")");
+      var json = JSON.parse(response.message);
       if (response.status == 500) {
         this.$notify({
-          message: resp.desc,
+          message: json.desc,
           type: "error"
         });
       }

+ 137 - 128
src/modules/basic/view/user.vue

@@ -3,82 +3,68 @@
     <div class="box box-info">
       <div class="box-body">
         <!-- 搜索 -->
-        <el-form
-          :inline="true"
-          :model="searchForm"
-          label-position="right"
-          label-width="80px"
-        >
-          <el-row>
-            <el-form-item label="顶级机构" class="pull-left">
-              <el-select
-                style="width: 180px"
-                class="input_width_lg"
-                v-model="searchForm.rootOrgId"
-                placeholder="请选择"
-                :disabled="!isSuperAdmin"
-                @change="rootOrgChanged4Search"
-              >
-                <el-option
-                  v-for="item in rootOrgList"
-                  :label="item.name"
-                  :value="item.id"
-                  :key="item.id"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="角色" class="pull-left">
-              <el-select
-                style="width: 180px"
-                class="input_width_lg"
-                clearable
-                v-model="searchForm.roleId"
-                placeholder="请选择"
-              >
-                <el-option
-                  v-for="item in roleList4Search"
-                  :label="item.roleName"
-                  :value="item.roleId"
-                  :key="item.roleId"
-                />
-              </el-select>
-            </el-form-item>
-            <el-form-item label="登录名" class="pull-left">
-              <el-input
-                style="width: 180px"
-                class="input_width_lg"
-                placeholder="请输入登录名"
-                v-model="searchForm.loginName"
+        <ecs-form-search :model="searchForm">
+          <el-form-item label="顶级机构">
+            <el-select
+              v-model="searchForm.rootOrgId"
+              placeholder="请选择"
+              :disabled="!isSuperAdmin"
+              @change="rootOrgChanged4Search"
+            >
+              <el-option
+                v-for="item in rootOrgList"
+                :label="item.name"
+                :value="item.id"
+                :key="item.id"
               />
-            </el-form-item>
-            <el-form-item label="姓名" class="pull-left">
-              <el-input
-                style="width: 180px"
-                class="input_width_lg"
-                placeholder="请输入姓名"
-                v-model="searchForm.name"
+            </el-select>
+          </el-form-item>
+          <el-form-item label="角色">
+            <el-select
+              clearable
+              v-model="searchForm.roleId"
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="item in roleList4Search"
+                :label="item.roleName"
+                :value="item.roleId"
+                :key="item.roleId"
               />
-            </el-form-item>
-            <el-form-item class="pull-right">
-              <el-button
-                size="small"
-                type="primary"
-                icon="search"
-                @click="search"
-              >
-                查询
-              </el-button>
-              <el-button
-                size="small"
-                type="primary"
-                icon="plus"
-                @click="openAddingDialog"
-              >
-                新增
-              </el-button>
-            </el-form-item>
-          </el-row>
-        </el-form>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="登录名">
+            <el-input
+              placeholder="请输入登录名"
+              v-model="searchForm.loginName"
+            />
+          </el-form-item>
+          <el-form-item label="姓名">
+            <el-input placeholder="请输入姓名" v-model="searchForm.name" />
+          </el-form-item>
+          <div></div>
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-search"
+              @click="search"
+            >
+              查询
+            </el-button>
+            <el-button size="small" @click="resetEcsFormSearch">
+              重置
+            </el-button>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-plus"
+              @click="openAddingDialog"
+            >
+              新增
+            </el-button>
+          </el-form-item>
+        </ecs-form-search>
 
         <!-- 添加用户信息弹出框 -->
         <el-dialog title="用户信息" :visible.sync="addingDialog">
@@ -344,71 +330,81 @@
         <el-table
           :data="tableData"
           border
+          resizable
           style="width: 100%;"
           @selection-change="selectChange"
         >
-          <el-table-column type="selection" width="40" />
           <el-table-column prop="id" width="80" label="ID" />
           <el-table-column prop="name" width="120" label="姓名" />
           <el-table-column prop="loginName" width="100" label="登录名" />
           <el-table-column prop="rootOrgName" width="150" label="顶级机构" />
-          <el-table-column prop="roleNamesStr" width="250" label="角色" />
+          <!-- <el-table-column prop="roleNamesStr" width="110" label="角色" /> -->
+          <el-table-column width="120" label="角色">
+            <span
+              slot-scope="scope"
+              v-html="scope.row.roleNamesStr.replace(/,/g, '<br />')"
+            >
+            </span>
+          </el-table-column>
           <el-table-column prop="updateTime" width="160" label="更新时间" />
           <el-table-column width="70" label="状态">
-            <span slot-scope="scope">
-              <el-tag :type="getTag(scope.row.enable)">
-                {{ getEnable(scope.row.enable) }}
-              </el-tag>
-            </span>
+            <span slot-scope="scope"> {{ getEnable(scope.row.enable) }} </span>
           </el-table-column>
           <el-table-column label="操作">
             <div slot-scope="scope">
-              <span>
-                <el-button
-                  size="mini"
-                  type="primary"
-                  @click="openUpdateDialog(scope.row)"
-                >
-                  <i class="el-icon-edit"></i> 修改
-                </el-button>
-              </span>
-              <span>
-                <el-button
-                  v-if="false"
-                  size="mini"
-                  type="danger"
-                  @click="deleteById(scope.row)"
-                >
-                  <i class="el-icon-delete"></i> 删除
-                </el-button>
-              </span>
-              <span>
-                <el-button
-                  size="mini"
-                  type="primary"
-                  @click="resetPass(scope.row)"
-                >
-                  <i class="el-icon-reset"></i>重置密码
-                </el-button>
-              </span>
-              <span v-if="!scope.row.enable">
-                <el-button
-                  size="mini"
-                  type="success"
-                  @click="enableById(scope.row)"
-                >
-                  <i class="fa fa-check" aria-hidden="true"></i>启用
-                </el-button>
-              </span>
-              <span v-if="scope.row.enable">
-                <el-button
-                  size="mini"
-                  type="warning"
-                  @click="disableById(scope.row)"
-                >
-                  <i class="fa fa-close" aria-hidden="true"></i>禁用
+              <el-button
+                v-if="!scope.row.enable"
+                size="mini"
+                type="danger"
+                @click="enableById(scope.row)"
+              >
+                <i class="fa fa-check" aria-hidden="true"></i>启用
+              </el-button>
+              <el-button
+                v-if="scope.row.enable"
+                size="mini"
+                type="danger"
+                @click="disableById(scope.row)"
+              >
+                <i class="fa fa-close" aria-hidden="true"></i>禁用
+              </el-button>
+              &nbsp;
+              <el-dropdown>
+                <el-button type="primary" plain size="mini">
+                  更多<i class="el-icon-arrow-down el-icon--right"></i>
                 </el-button>
-              </span>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item>
+                    <el-button
+                      size="mini"
+                      type="primary"
+                      plain
+                      @click="openUpdateDialog(scope.row)"
+                    >
+                      <i class="el-icon-edit"></i> 编辑
+                    </el-button>
+                  </el-dropdown-item>
+                  <el-dropdown-item>
+                    <el-button
+                      v-if="false"
+                      size="mini"
+                      type="danger"
+                      @click="deleteById(scope.row)"
+                    >
+                      <i class="el-icon-delete"></i> 删除
+                    </el-button>
+                  </el-dropdown-item>
+                  <el-dropdown-item>
+                    <el-button
+                      size="mini"
+                      type="danger"
+                      @click="resetPass(scope.row)"
+                    >
+                      <i class="el-icon-reset"></i>重置密码
+                    </el-button>
+                  </el-dropdown-item>
+                </el-dropdown-menu>
+              </el-dropdown>
             </div>
           </el-table-column>
         </el-table>
@@ -417,7 +413,9 @@
             @current-change="handleCurrentChange"
             :current-page="currentPage"
             :page-size="10"
-            layout="total, prev, pager, next, jumper"
+            :page-sizes="[10, 30, 50, 100]"
+            @size-change="handleSizeChange"
+            layout="total, sizes, prev, pager, next, jumper"
             :total="total"
           />
         </div>
@@ -550,6 +548,17 @@ export default {
     }
   },
   methods: {
+    resetEcsFormSearch() {
+      this.searchForm = Object.assign(this.searchForm, {
+        roleId: "",
+        loginName: "",
+        name: ""
+      });
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.search();
+    },
     validateOrg(rule, value, callback) {
       if (0 != value && !value) {
         callback(new Error("请选择子机构"));
@@ -562,7 +571,7 @@ export default {
       for (let cur of this.roleList4InsertOrUpdate) {
         if (
           cur.roleCode == "LC_USER" &&
-          this.userForm.roleIds.contains(cur.roleId)
+          this.userForm.roleIds.includes(cur.roleId)
         ) {
           isLC = true;
           break;

+ 0 - 17
src/modules/examwork/view/examInfo.vue

@@ -163,23 +163,6 @@
     </section>
   </div>
 </template>
-<style>
-.page {
-  margin-top: 10px;
-}
-
-.buttonframe {
-  margin-left: 20px;
-}
-
-.el-table th > .cell {
-  text-align: center;
-}
-
-.el-textarea__inner {
-  resize: none;
-}
-</style>
 <script>
 import { CORE_API, EXAM_WORK_API, EXAM_TYPE } from "@/constants/constants.js";
 import { mapState } from "vuex";

+ 2 - 3
src/modules/examwork/view/examStudent.vue

@@ -1667,11 +1667,10 @@ export default {
       console.log(file);
       console.log(fileList);
 
-      var jsonStr = response.message.substring(4);
-      var resp = eval("(" + jsonStr + ")");
+      var json = JSON.parse(response.message);
       if (response.status == 500) {
         this.$notify({
-          message: resp.desc,
+          message: json.desc,
           type: "error"
         });
       }

+ 2 - 3
src/modules/examwork/view/examStudentImport.vue

@@ -229,11 +229,10 @@ export default {
       console.log(response);
       console.log(file);
       console.log(fileList);
-      var jsonStr = response.message.substring(4);
-      var resp = eval("(" + jsonStr + ")");
+      var json = JSON.parse(response.message);
       if (response.status == 500) {
         this.$notify({
-          message: resp.desc,
+          message: json.desc,
           type: "error"
         });
       }

+ 7 - 10
src/modules/examwork/view/onlineExam.vue

@@ -134,20 +134,18 @@
                 </el-row>
               </el-tab-pane>
               <el-tab-pane label="显示设置" name="tab3">
-                <el-row>
+                <el-row v-if="show_ckeditor">
                   <el-form-item label="考前说明" label-width="110px">
                     <ckeditor
-                      width="1000px"
                       v-model="form.properties.BEFORE_EXAM_REMARK"
                     ></ckeditor>
                   </el-form-item>
                 </el-row>
-                <el-row>
+                <el-row v-if="show_ckeditor">
                   <el-form-item label="考后说明" label-width="110px">
-                    <el-input
+                    <ckeditor
                       v-model="form.properties.AFTER_EXAM_REMARK"
-                      auto-complete="off"
-                    ></el-input>
+                    ></ckeditor>
                   </el-form-item>
                 </el-row>
                 <el-row>
@@ -160,12 +158,11 @@
                     </el-radio-group>
                   </el-form-item>
                 </el-row>
-                <el-row>
+                <el-row v-if="show_ckeditor">
                   <el-form-item label="作弊说明" label-width="110px">
-                    <el-input
+                    <ckeditor
                       v-model="form.properties.CHEATING_REMARK"
-                      auto-complete="off"
-                    ></el-input>
+                    ></ckeditor>
                   </el-form-item>
                 </el-row>
                 <el-row>

+ 7 - 4
src/modules/examwork/view/practiceExam.vue

@@ -134,12 +134,11 @@
                 </el-row>
               </el-tab-pane>
               <el-tab-pane label="显示设置" name="tab3">
-                <el-row>
+                <el-row v-if="show_ckeditor">
                   <el-form-item label="考前说明" label-width="110px">
-                    <el-input
+                    <ckeditor
                       v-model="form.properties.BEFORE_EXAM_REMARK"
-                      auto-complete="off"
-                    ></el-input>
+                    ></ckeditor>
                   </el-form-item>
                 </el-row>
                 <el-row>
@@ -173,6 +172,7 @@
 <script>
 import { EXAM_TYPE, EXAM_WORK_API } from "@/constants/constants.js";
 import moment from "moment";
+import ckeditor from "@/components/ckeditor.vue";
 
 let _this = null;
 
@@ -243,6 +243,9 @@ let validateExamReconnectTime = (rule, value, callback) => {
 };
 
 export default {
+  components: {
+    ckeditor
+  },
   data() {
     return {
       activeName: "tab1",

+ 2 - 3
src/modules/examwork/view/student.vue

@@ -813,11 +813,10 @@ export default {
       console.log(response);
       console.log(file);
       console.log(fileList);
-      var jsonStr = response.message.substring(4);
-      var resp = eval("(" + jsonStr + ")");
+      var json = JSON.parse(response.message);
       if (response.status == 500) {
         this.$notify({
-          message: resp.desc,
+          message: json.desc,
           type: "error"
         });
       }

+ 2 - 3
src/modules/marking/views/Marking.vue

@@ -673,7 +673,6 @@ small {
   margin-top: 20px;
 }
 .content-header {
-  margin-top: 10px;
   margin-left: 15px;
   overflow: hidden;
   background-color: rgb(77, 124, 196);
@@ -700,7 +699,7 @@ li {
   color: white;
 }
 .titlefont {
-  font-size: 12px;
+  font-size: 14px;
   display: inline-block;
 }
 .box-card {
@@ -730,7 +729,7 @@ li {
 .box {
   position: relative;
   border-radius: 3px;
-  margin-bottom: 20px;
+  margin-bottom: 0px;
   width: 100%;
 }
 .pull-right {

+ 4 - 1
src/modules/marking/views/TpMain.vue

@@ -382,7 +382,7 @@ export default {
 .markmain {
   width: 74%;
   overflow: auto;
-  height: 600px;
+  max-height: calc(100vh - 65px);
 }
 .markmain::-webkit-scrollbar {
   /*滚动条整体样式*/
@@ -452,4 +452,7 @@ img {
   font-weight: bold;
   color: black;
 }
+.paper >>> .max-number {
+  font-size: 20px;
+}
 </style>

+ 124 - 47
src/modules/marking/views/TpScoreBoard.vue

@@ -13,18 +13,14 @@
         ></el-switch>
       </div>
       <div class="second-board">
-        <div class="board-title">
-          <span>总分</span>
-        </div>
+        <div class="board-title"><span>总分</span></div>
         <div class="board-score">
           <span>{{ this.totalScore }}分</span>
         </div>
       </div>
       <!-- 鼠标模式 -->
       <div v-if="isMouseMode">
-        <div class="title-board">
-          <span class="title-font">评分</span>
-        </div>
+        <div class="title-board"><span class="title-font">评分</span></div>
         <div class="itemScroll">
           <div
             :key="resultItem.markItem.id"
@@ -40,26 +36,38 @@
               )
             "
           >
-            <div v-bind:class="{ 'active-btn': itemClass[index] }" class="title-item-top">
+            <div
+              v-bind:class="{ 'active-btn': itemClass[index] }"
+              class="title-item-top"
+            >
               <span>
                 {{ resultItem.markItem.mainNumber }}({{
-                resultItem.markItem.orders
+                  resultItem.markItem.orders
                 }})
               </span>
             </div>
-            <div class="title-item-bottom" v-bind:class="{ 'active-text': itemClass[index] }">
+            <div
+              class="title-item-bottom"
+              v-bind:class="{ 'active-text': itemClass[index] }"
+            >
               <span>{{ resultItem.score }}分</span>
             </div>
           </div>
         </div>
         <div v-if="markTypeView">
           <div class="step-board"></div>
-          <div class="title-board">
-            <span class="title-font">打分</span>
-          </div>
+          <div class="title-board"><span class="title-font">打分</span></div>
           <div class="itemScroll">
-            <div :key="score" v-for="score in itemScores" class="pull-left scoretitle">
-              <div @click="scoreClick(score)" class="scorebutton">
+            <div
+              :key="score"
+              v-for="(score, index) in itemScores"
+              class="pull-left scoretitle"
+            >
+              <div
+                @click="scoreClick(score, index)"
+                class="scorebutton"
+                v-bind:class="{ 'score-btn': itemScoreBtn[index] }"
+              >
                 <span class="score-item">{{ score }}</span>
               </div>
             </div>
@@ -68,9 +76,7 @@
       </div>
       <!-- 键盘模式 -->
       <div v-if="!isMouseMode">
-        <div class="title-board">
-          <span class="title-font">评分</span>
-        </div>
+        <div class="title-board"><span class="title-font">评分</span></div>
         <div>
           <div class="itemScroll">
             <div
@@ -82,13 +88,15 @@
                 <div class="item-title">
                   <div class="pull-left item-number">
                     {{ resultItem.markItem.mainNumber }}({{
-                    resultItem.markItem.orders
+                      resultItem.markItem.orders
                     }})
                   </div>
                   <div class="pull-left item-number2">
                     <span>{{ resultItem.markItem.maxScore }}分</span>
                   </div>
-                  <div class="pull-left item-number3">间隔:{{ resultItem.markItem.scoreInterval }}</div>
+                  <div class="pull-left item-number3">
+                    间隔:{{ resultItem.markItem.scoreInterval }}
+                  </div>
                 </div>
                 <div class="item-score">
                   <input
@@ -100,7 +108,7 @@
                     @change="scoreChange(index, resultItem.score)"
                     v-model="resultItem.score"
                     class="score-input"
-                  >
+                  />
                 </div>
               </div>
@@ -113,13 +121,23 @@
         <div class="step-board"></div>
         <div class="title-board">
           <span class="title-font">备注</span>
+          <div
+            v-if="!textareaflag"
+            class="el-icon-caret-right remark-board"
+            @click="showTextarea"
+          ></div>
+          <div
+            v-if="textareaflag"
+            class="el-icon-caret-top remark-board"
+            @click="showTextarea"
+          ></div>
         </div>
-        <div class="remark-step">
+        <div class="remark-step" v-if="textareaflag">
           <textarea
             id="remark"
             type="text"
-            rows="5"
-            cols="42"
+            rows="3"
+            cols="35"
             placeholder="请输入内容"
             v-model="markedResult.markRemark"
           />
@@ -130,19 +148,28 @@
         <div v-if="problemView">
           <div class="problem-button"></div>
           <span v-if="tagFlag">
-            <el-radio-group v-model="markedResult.tag" @change="processTagPaper">
-              <div class="pull-left scoretitle" v-for="tag in tags" :key="tag.code">
+            <el-radio-group
+              v-model="markedResult.tag"
+              @change="processTagPaper"
+            >
+              <div
+                class="pull-left scoretitle"
+                v-for="tag in tags"
+                :key="tag.code"
+              >
                 <el-radio :label="tag.code">{{ tag.name }}</el-radio>
               </div>
             </el-radio-group>
           </span>
           <span v-if="!tagFlag">
             <el-radio-group v-model="unusualType" @change="processTagPaper">
-              <div class="pull-left scoretitle" v-for="tag in tags" :key="tag.code">
+              <div
+                class="pull-left scoretitle"
+                v-for="tag in tags"
+                :key="tag.code"
+              >
                 <el-radio :label="tag.code" :key="tag.code">
-                  {{
-                  tag.name
-                  }}
+                  {{ tag.name }}
                 </el-radio>
               </div>
             </el-radio-group>
@@ -159,15 +186,26 @@
             @click="submitMark"
             v-bind:round="true"
           >
-            <span class="sub-btn">提</span>
-            <span>交</span>
+            <span class="sub-btn">提</span> <span>交</span>
           </el-button>
         </div>
         <div class="pull-left btn" v-if="paperMark">
-          <el-button type="danger" v-bind:round="true" size="small" @click="problemClick">问题卷</el-button>
+          <el-button
+            type="danger"
+            v-bind:round="true"
+            size="small"
+            @click="problemClick"
+            >问题卷</el-button
+          >
         </div>
         <div class="pull-left btn" v-if="paperMark && problemView">
-          <el-button type="danger" v-bind:round="true" size="small" @click="resetProblem">清除问题卷</el-button>
+          <el-button
+            type="danger"
+            v-bind:round="true"
+            size="small"
+            @click="resetProblem"
+            >清除问题卷</el-button
+          >
         </div>
       </div>
     </div>
@@ -201,10 +239,13 @@ export default {
       curIndex: 0,
       steps: [],
       loading: false,
+      btnflag: false,
+      textareaflag: false,
       tmpSignItem: this.signItem,
       tags: [],
       unusualType: "",
-      scoreError: []
+      scoreError: [],
+      itemScoreBtn: []
     };
   },
   props: [
@@ -292,6 +333,8 @@ export default {
         this.signScores.splice(0, this.signScores.length);
       }
       this.positionDiv(order);
+      //重置打分板样式
+      this.itemScoreBtn = [];
     },
     positionDiv(order) {
       EVENTHUB.$emit("positionDiv", order);
@@ -353,7 +396,7 @@ export default {
       }
       return true;
     },
-    scoreClick(score) {
+    scoreClick(score, index1) {
       //轨迹模式处理分值问题
       if (this.markSign) {
         if (this.checkSignScore(score)) {
@@ -371,6 +414,15 @@ export default {
         //正常模式
         this.resultItem.score = score;
         this.resultItems[this.curIndex].score = score;
+        //设置动态样式(打分板)
+        this.itemScoreBtn = [];
+        for (let i = 0; i < this.itemScores.length; i++) {
+          if (i == index1) {
+            this.itemScoreBtn.push(true);
+          } else {
+            this.itemScoreBtn.push(false);
+          }
+        }
       }
     },
     //键盘打分板change事件
@@ -631,6 +683,13 @@ export default {
         }, 1);
         this.positionDiv(order);
       }
+    },
+    showTextarea() {
+      if (this.textareaflag) {
+        this.textareaflag = false;
+      } else {
+        this.textareaflag = true;
+      }
     }
   },
   watch: {
@@ -837,6 +896,11 @@ li {
   border: 1px solid rgb(77, 124, 196);
   text-align: center;
 }
+.scorebutton:hover {
+  background: rgb(85, 191, 255);
+  color: white;
+  border-color: rgb(85, 191, 255);
+}
 .titlebutton {
   border-radius: 15px;
   cursor: pointer;
@@ -854,10 +918,10 @@ li {
   border-bottom: 1px solid #ccc;
 }
 .board-title {
-  height: 40px;
+  height: 50px;
   width: 80px;
-  background: red;
-  border: 2px solid red;
+  background: rgb(255, 109, 109);
+  border: 2px solid rgb(255, 109, 109);
   text-align: center;
   padding-top: 20px;
   font-weight: 600;
@@ -865,21 +929,21 @@ li {
   border-bottom-left-radius: 15px;
   float: left;
   font-size: 30px;
-  line-height: 1;
+  line-height: 0.5;
 }
 .board-score {
-  height: 40px;
+  height: 50px;
   width: 110px;
-  border: 2px solid red;
+  border: 2px solid rgb(255, 109, 109);
   margin-left: 80px;
   text-align: center;
   padding-top: 20px;
   font-weight: 600;
-  color: red;
+  color: rgb(255, 109, 109);
   border-top-right-radius: 15px;
   border-bottom-right-radius: 15px;
   font-size: 30px;
-  line-height: 1;
+  line-height: 0.5;
 }
 .title-board {
   margin-top: 20px;
@@ -919,8 +983,9 @@ li {
   line-height: 2.5;
 }
 textarea {
-  background: #ccc;
+  background: rgb(245, 245, 245);
   border-radius: 10px;
+  outline: none;
 }
 .step-board {
   margin-top: 20px;
@@ -929,6 +994,7 @@ textarea {
 .problem-button {
   border-bottom: 1px solid #ccc;
   margin-bottom: 15px;
+  margin-top: 20px;
 }
 .remark-step {
   height: 100px;
@@ -977,9 +1043,20 @@ textarea {
   text-align: center;
   line-height: 1.5;
 }
-.btn{
-  margin-right: 10px;
+.btn {
+  margin-top: 20px;
   margin-bottom: 10px;
+  padding-right: 1px;
+}
+.score-btn {
+  background: rgb(85, 191, 255);
+  color: white;
+  border-color: rgb(85, 191, 255);
+}
+.remark-board {
+  cursor: pointer;
+}
+.el-button {
+  outline: none;
 }
-
 </style>

+ 36 - 9
src/modules/portal/views/Login.vue

@@ -35,6 +35,20 @@
       </div>
     </main>
 
+    <el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
+      <input
+        @keyup.enter="loginWithSms"
+        type="number"
+        v-model="loginInfo.smsCode"
+        style="width: 80%"
+        placeholder="请向王伟咨询手机验证码"
+      />
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="loginWithSms">确 定</el-button>
+      </span>
+    </el-dialog>
+
     <footer class="login-footer">
       Copyright &copy; 2019 <a href="javascript:void(0)">讯飞启明</a>.
     </footer>
@@ -52,12 +66,14 @@ export default {
       errorInfo: "",
       title: "考试云平台",
       jwptCustomize: false,
+      dialogVisible: false,
       loginInfo: {
         rootOrgId: "",
         domain: "",
         accountType: "COMMON_LOGIN_NAME",
         accountValue: "",
-        password: ""
+        password: "",
+        smsCode: null
       }
     };
   },
@@ -104,15 +120,26 @@ export default {
         return;
       }
       var url = CORE_API + "/auth/login";
-      this.$httpWithMsg.post(url, this.loginInfo).then(response => {
-        var user = response.data;
-        this.USER_SIGNIN(user);
-        this.$router.replace({ path: "/home/overview" });
-        this.$notify({
-          message: "登录成功",
-          type: "success"
+      this.$httpWithMsg
+        .post(url, this.loginInfo)
+        .then(response => {
+          var user = response.data;
+          this.USER_SIGNIN(user);
+          this.$router.replace({ path: "/home/overview" });
+          this.$notify({
+            message: "登录成功",
+            type: "success"
+          });
+        })
+        .catch(error => {
+          if (error.response.data.code === "B-001100") {
+            this.dialogVisible = true;
+          }
         });
-      });
+    },
+    loginWithSms() {
+      this.dialogVisible = false;
+      this.login();
     },
     jwptCustomizeMethod() {
       // 普通高校考试综合管理平台 定制

+ 2 - 1
src/modules/portal/views/home/Home.vue

@@ -250,7 +250,7 @@ body > .el-container {
 }
 
 .main-body {
-  min-height: calc(100vh - 60px);
+  min-height: calc(100vh - 100px);
   display: flex;
   flex-direction: column;
   justify-content: space-between;
@@ -261,6 +261,7 @@ body > .el-container {
 .main-content {
   min-height: calc(100vh - 60px - 60px - 40px);
   margin-top: 20px;
+  margin-right: 20px;
 }
 
 .footer {

+ 2 - 1
src/modules/portal/views/home/HomeSide.vue

@@ -10,6 +10,7 @@
       background-color="#304156"
       text-color="#fff"
       active-text-color="#409eff"
+      router
     >
       <el-submenu
         v-for="menu1 in menuList1"
@@ -32,7 +33,7 @@
           v-for="menu2 in menuList2(menu1)"
           :index="menu2.nodeCode"
           :key="menu2.id"
-          @click="() => $router.push({ path: menu2.ext5 })"
+          :route="{ path: menu2.ext5 }"
         >
           <router-link
             :to="{ path: menu2.ext5 }"

+ 1 - 1
src/modules/portal/views/home/LinkTitles.vue

@@ -2,7 +2,7 @@
   <el-breadcrumb
     v-if="currentPaths.length > 0"
     separator-class="el-icon-arrow-right"
-    style="border-bottom: 1px solid #aaa; padding-bottom: 5px;"
+    style="border-bottom: 1px solid #eee; padding-bottom: 5px;"
   >
     <el-breadcrumb-item :to="{ path: '/home/overview' }"
       >首页</el-breadcrumb-item

+ 11 - 4
src/modules/print/view/CourseStatistic.vue

@@ -187,11 +187,13 @@
         <!-- 分页 -->
         <div class="page pull-right">
           <el-pagination
-            @current-change="handlePager"
+            @current-change="handlePagerNo"
             :current-page="formSearch.pageNo"
+            @size-change="handlePagerSize"
             :page-size="formSearch.pageSize"
+            :page-sizes="[10, 20, 50]"
             :total="totalElements"
-            layout="total, prev, pager, next, jumper"
+            layout="total, sizes, prev, pager, next, jumper"
           ></el-pagination>
         </div>
       </div>
@@ -507,9 +509,14 @@ export default {
       /* 处理选中记录 */
       this.selectElements = elements;
     },
-    handlePager(current) {
+    handlePagerNo(pageNo) {
       /* 处理分页 */
-      this.searchRecords(current);
+      this.searchRecords(pageNo);
+    },
+    handlePagerSize(pageSize) {
+      /* 处理每页条数 */
+      this.formSearch.pageSize = pageSize;
+      this.searchRecords(1);
     },
     searchRecords(pageNo) {
       this.formSearch.pageNo = pageNo;

+ 11 - 4
src/modules/print/view/ExamStructure.vue

@@ -105,11 +105,13 @@
         <!-- 分页 -->
         <div class="page pull-right">
           <el-pagination
-            @current-change="handlePager"
+            @current-change="handlePagerNo"
             :current-page="formSearch.pageNo"
+            @size-change="handlePagerSize"
             :page-size="formSearch.pageSize"
+            :page-sizes="[10, 20, 50]"
             :total="totalElements"
-            layout="total, prev, pager, next, jumper"
+            layout="total, sizes, prev, pager, next, jumper"
           ></el-pagination>
         </div>
       </div>
@@ -414,9 +416,14 @@ export default {
     };
   },
   methods: {
-    handlePager(current) {
+    handlePagerNo(pageNo) {
       /* 处理分页 */
-      this.searchRecords(current);
+      this.searchRecords(pageNo);
+    },
+    handlePagerSize(pageSize) {
+      /* 处理每页条数 */
+      this.formSearch.pageSize = pageSize;
+      this.searchRecords(1);
     },
     searchRecords(pageNo) {
       this.formSearch.pageNo = pageNo;

+ 11 - 4
src/modules/print/view/Project.vue

@@ -131,11 +131,13 @@
         <!-- 分页 -->
         <div class="page pull-right">
           <el-pagination
-            @current-change="handlePager"
+            @current-change="handlePagerNo"
             :current-page="formSearch.pageNo"
+            @size-change="handlePagerSize"
             :page-size="formSearch.pageSize"
+            :page-sizes="[10, 20, 50]"
             :total="totalElements"
-            layout="total, prev, pager, next, jumper"
+            layout="total, sizes, prev, pager, next, jumper"
           ></el-pagination>
         </div>
       </div>
@@ -560,9 +562,14 @@ export default {
         }
       };
     },
-    handlePager(current) {
+    handlePagerNo(pageNo) {
       /* 处理分页 */
-      this.searchRecords(current);
+      this.searchRecords(pageNo);
+    },
+    handlePagerSize(pageSize) {
+      /* 处理每页条数 */
+      this.formSearch.pageSize = pageSize;
+      this.searchRecords(1);
     },
     searchRecords(pageNo) {
       this.formSearch.pageNo = pageNo;

+ 42 - 0
src/styles/bootstrap.scss

@@ -0,0 +1,42 @@
+/*!
+ * Bootstrap v4.2.1 (https://getbootstrap.com/)
+ * 启明泰和根据bootstrap定制UI规范
+ */
+
+@import "bootstrap/scss/_functions.scss";
+@import "bootstrap/scss/_variables.scss";
+@import "bootstrap/scss/_mixins.scss";
+@import "bootstrap/scss/_root.scss";
+@import "bootstrap/scss/_reboot.scss";
+@import "bootstrap/scss/_type.scss";
+@import "bootstrap/scss/_images.scss";
+@import "bootstrap/scss/_code.scss";
+@import "bootstrap/scss/_grid.scss";
+@import "bootstrap/scss/_tables.scss";
+@import "bootstrap/scss/_forms.scss";
+@import "bootstrap/scss/_buttons.scss";
+// @import "transitions";
+// @import "dropdown";
+@import "bootstrap/scss/_button-group.scss";
+@import "bootstrap/scss/_input-group.scss";
+// @import "custom-forms";
+@import "bootstrap/scss/_nav.scss";
+@import "bootstrap/scss/_navbar.scss";
+@import "bootstrap/scss/_card.scss";
+// @import "breadcrumb";
+// @import "pagination";
+@import "bootstrap/scss/_badge.scss";
+// @import "jumbotron";
+// @import "alert";
+// @import "progress";
+@import "bootstrap/scss/_media.scss";
+@import "bootstrap/scss/_list-group.scss";
+@import "bootstrap/scss/_close.scss";
+// @import "toasts";
+// @import "modal";
+// @import "tooltip";
+// @import "popover";
+// @import "carousel";
+// @import "spinners";
+@import "bootstrap/scss/_utilities.scss";
+// @import "print";

+ 11 - 0
src/styles/elementuiCustomize.css

@@ -0,0 +1,11 @@
+.el-table td {
+  padding: 4px 0;
+}
+
+.el-table label {
+  margin-bottom: 0;
+}
+
+.el-form .el-form-item {
+  margin-bottom: 0px;
+}

+ 2 - 0
src/styles/global.css

@@ -1,3 +1,5 @@
+@import "./elementuiCustomize.css";
+
 body {
   margin: 0;
 }

+ 395 - 17
yarn.lock

@@ -1139,6 +1139,11 @@ alphanum-sort@^1.0.0:
   resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
   integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=
 
+amdefine@>=0.0.4:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+  integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
+
 ansi-colors@^3.0.0:
   version "3.2.3"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
@@ -1253,6 +1258,11 @@ array-filter@~0.0.0:
   resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec"
   integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw=
 
+array-find-index@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+  integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
+
 array-flatten@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@@ -1343,6 +1353,11 @@ async-each@^1.0.0:
   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
   integrity sha1-GdOGodntxufByF04iu28xW0zYC0=
 
+async-foreach@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
+  integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=
+
 async-limiter@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
@@ -1707,6 +1722,13 @@ binary-extensions@^1.0.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14"
   integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==
 
+block-stream@*:
+  version "0.0.9"
+  resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+  integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=
+  dependencies:
+    inherits "~2.0.0"
+
 bluebird@^3.1.1, bluebird@^3.5.1, bluebird@^3.5.3:
   version "3.5.3"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
@@ -1750,6 +1772,11 @@ boolbase@^1.0.0, boolbase@~1.0.0:
   resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
   integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
 
+bootstrap@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.2.1.tgz#8f8bdca024dbf0e8644da32e918c8a03a90a5757"
+  integrity sha512-tt/7vIv3Gm2mnd/WeDx36nfGGHleil0Wg8IeB7eMrVkY0fZ5iTaBisSh8oNANc2IBsCc6vCgCNTIM/IEN0+50Q==
+
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -2030,6 +2057,24 @@ camel-case@3.0.x:
     no-case "^2.2.0"
     upper-case "^1.1.1"
 
+camelcase-keys@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+  integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
+  dependencies:
+    camelcase "^2.0.0"
+    map-obj "^1.0.0"
+
+camelcase@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+  integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
+
+camelcase@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+  integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
+
 camelcase@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -2067,7 +2112,7 @@ caseless@~0.12.0:
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
   integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
 
-chalk@^1.1.3:
+chalk@^1.1.1, chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
@@ -2194,6 +2239,15 @@ clipboardy@^1.2.3:
     arch "^2.1.0"
     execa "^0.8.0"
 
+cliui@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+  integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wrap-ansi "^2.0.0"
+
 cliui@^4.0.0, cliui@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@@ -2203,6 +2257,16 @@ cliui@^4.0.0, cliui@^4.1.0:
     strip-ansi "^4.0.0"
     wrap-ansi "^2.0.0"
 
+clone-deep@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713"
+  integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==
+  dependencies:
+    for-own "^1.0.0"
+    is-plain-object "^2.0.4"
+    kind-of "^6.0.0"
+    shallow-clone "^1.0.0"
+
 clone@2.x:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
@@ -2510,6 +2574,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
+cross-spawn@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+  integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI=
+  dependencies:
+    lru-cache "^4.0.1"
+    which "^1.2.9"
+
 cross-spawn@^5.0.1, cross-spawn@^5.1.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@@ -2755,6 +2827,13 @@ cssstyle@^1.0.0:
   dependencies:
     cssom "0.3.x"
 
+currently-unhandled@^0.4.1:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+  integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
+  dependencies:
+    array-find-index "^1.0.1"
+
 cyclist@~0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
@@ -2814,7 +2893,7 @@ debug@^4.0.1, debug@^4.1.0:
   dependencies:
     ms "^2.1.1"
 
-decamelize@^1.1.1:
+decamelize@^1.1.1, decamelize@^1.1.2:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -3968,6 +4047,11 @@ follow-redirects@^1.0.0, follow-redirects@^1.3.0:
   dependencies:
     debug "=3.1.0"
 
+for-in@^0.1.3:
+  version "0.1.8"
+  resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
+  integrity sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=
+
 for-in@^1.0.1, for-in@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -3980,6 +4064,13 @@ for-own@^0.1.4:
   dependencies:
     for-in "^1.0.1"
 
+for-own@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
+  integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=
+  dependencies:
+    for-in "^1.0.1"
+
 forever-agent@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -4076,6 +4167,16 @@ fsevents@^1.2.2, fsevents@^1.2.3:
     nan "^2.9.2"
     node-pre-gyp "^0.10.0"
 
+fstream@^1.0.0, fstream@^1.0.2:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
+  integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=
+  dependencies:
+    graceful-fs "^4.1.2"
+    inherits "~2.0.0"
+    mkdirp ">=0.5 0"
+    rimraf "2"
+
 function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -4100,6 +4201,13 @@ gauge@~2.7.3:
     strip-ansi "^3.0.1"
     wide-align "^1.1.0"
 
+gaze@^1.0.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a"
+  integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==
+  dependencies:
+    globule "^1.0.0"
+
 get-caller-file@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
@@ -4110,6 +4218,11 @@ get-own-enumerable-property-symbols@^3.0.0:
   resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203"
   integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==
 
+get-stdin@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+  integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
+
 get-stdin@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
@@ -4167,7 +4280,7 @@ glob-to-regexp@^0.3.0:
   resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
   integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
 
-glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1:
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
   integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
@@ -4225,6 +4338,15 @@ globby@^8.0.1:
     pify "^3.0.0"
     slash "^1.0.0"
 
+globule@^1.0.0:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d"
+  integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==
+  dependencies:
+    glob "~7.1.1"
+    lodash "~4.17.10"
+    minimatch "~3.0.2"
+
 graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
   version "4.1.15"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
@@ -4632,6 +4754,18 @@ imurmurhash@^0.1.4:
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
   integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
 
+in-publish@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51"
+  integrity sha1-4g/146KvwmkDILbcVSaCqcf631E=
+
+indent-string@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+  integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
+  dependencies:
+    repeating "^2.0.0"
+
 indexes-of@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
@@ -4650,7 +4784,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
   integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
@@ -5537,6 +5671,11 @@ joi@^13.0.0:
     isemail "3.x.x"
     topo "3.x.x"
 
+js-base64@^2.1.8:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.0.tgz#42255ba183ab67ce59a0dee640afdc00ab5ae93e"
+  integrity sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==
+
 js-beautify@^1.6.12, js-beautify@^1.6.14:
   version "1.8.9"
   resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.9.tgz#08e3c05ead3ecfbd4f512c3895b1cda76c87d523"
@@ -5833,7 +5972,7 @@ loader-utils@^0.2.16:
     json5 "^0.5.0"
     object-assign "^4.0.1"
 
-loader-utils@^1.0.2, loader-utils@^1.1.0:
+loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.1.tgz#64bbbac69aa5840d03754ba676a963dec568e844"
   integrity sha512-3Zhx4qDqBQ9U8udWB3RMJ29nLu5a3ObNOSzk87woPvge01pi0wABowgv7F79Z4mL0DGtHRi/oOndT34EVhInoQ==
@@ -5863,6 +6002,16 @@ lodash._reinterpolate@~3.0.0:
   resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
   integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
 
+lodash.assign@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
+  integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=
+
+lodash.clonedeep@^4.3.2:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+  integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+
 lodash.debounce@^4.0.8:
   version "4.0.8"
   resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -5883,11 +6032,21 @@ lodash.memoize@^4.1.2:
   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
   integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
 
+lodash.mergewith@^4.6.0:
+  version "4.6.1"
+  resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
+  integrity sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==
+
 lodash.sortby@^4.7.0:
   version "4.7.0"
   resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
   integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
 
+lodash.tail@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
+  integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=
+
 lodash.template@^4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
@@ -5913,7 +6072,7 @@ lodash.uniq@^4.5.0:
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
   integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
 
-lodash@4.x, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0:
+lodash@4.x, lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.10:
   version "4.17.11"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
   integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
@@ -5937,6 +6096,14 @@ loose-envify@^1.0.0:
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
+loud-rejection@^1.0.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+  integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
+  dependencies:
+    currently-unhandled "^0.4.1"
+    signal-exit "^3.0.0"
+
 lower-case@^1.1.1:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
@@ -5983,6 +6150,11 @@ map-cache@^0.2.2:
   resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
   integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
 
+map-obj@^1.0.0, map-obj@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+  integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
+
 map-visit@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
@@ -6038,6 +6210,22 @@ memory-fs@^0.4.0, memory-fs@~0.4.1:
     errno "^0.1.3"
     readable-stream "^2.0.1"
 
+meow@^3.7.0:
+  version "3.7.0"
+  resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+  integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
+  dependencies:
+    camelcase-keys "^2.0.0"
+    decamelize "^1.1.2"
+    loud-rejection "^1.0.0"
+    map-obj "^1.0.1"
+    minimist "^1.1.3"
+    normalize-package-data "^2.3.4"
+    object-assign "^4.0.1"
+    read-pkg-up "^1.0.1"
+    redent "^1.0.0"
+    trim-newlines "^1.0.0"
+
 merge-descriptors@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@@ -6164,7 +6352,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
   resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
   integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
 
-minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
+minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -6176,7 +6364,7 @@ minimist@0.0.8:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
   integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
 
-minimist@^1.1.1, minimist@^1.2.0:
+minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
@@ -6241,7 +6429,15 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
-mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
+mixin-object@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e"
+  integrity sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=
+  dependencies:
+    for-in "^0.1.3"
+    is-extendable "^0.1.1"
+
+mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@@ -6293,7 +6489,7 @@ mute-stream@0.0.7:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
   integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
 
-nan@^2.9.2:
+nan@^2.10.0, nan@^2.9.2:
   version "2.12.1"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
   integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==
@@ -6364,6 +6560,24 @@ node-forge@0.7.5:
   resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df"
   integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==
 
+node-gyp@^3.8.0:
+  version "3.8.0"
+  resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+  integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
+  dependencies:
+    fstream "^1.0.0"
+    glob "^7.0.3"
+    graceful-fs "^4.1.2"
+    mkdirp "^0.5.0"
+    nopt "2 || 3"
+    npmlog "0 || 1 || 2 || 3 || 4"
+    osenv "0"
+    request "^2.87.0"
+    rimraf "2"
+    semver "~5.3.0"
+    tar "^2.0.0"
+    which "1"
+
 node-int64@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@@ -6440,6 +6654,38 @@ node-releases@^1.1.1:
   dependencies:
     semver "^5.3.0"
 
+node-sass@^4.9.0:
+  version "4.11.0"
+  resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a"
+  integrity sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==
+  dependencies:
+    async-foreach "^0.1.3"
+    chalk "^1.1.1"
+    cross-spawn "^3.0.0"
+    gaze "^1.0.0"
+    get-stdin "^4.0.1"
+    glob "^7.0.3"
+    in-publish "^2.0.0"
+    lodash.assign "^4.2.0"
+    lodash.clonedeep "^4.3.2"
+    lodash.mergewith "^4.6.0"
+    meow "^3.7.0"
+    mkdirp "^0.5.1"
+    nan "^2.10.0"
+    node-gyp "^3.8.0"
+    npmlog "^4.0.0"
+    request "^2.88.0"
+    sass-graph "^2.2.4"
+    stdout-stream "^1.4.0"
+    "true-case-path" "^1.0.2"
+
+"nopt@2 || 3":
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+  integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+  dependencies:
+    abbrev "1"
+
 nopt@^4.0.1, nopt@~4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
@@ -6448,7 +6694,7 @@ nopt@^4.0.1, nopt@~4.0.1:
     abbrev "1"
     osenv "^0.1.4"
 
-normalize-package-data@^2.3.2:
+normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
   integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==
@@ -6505,7 +6751,7 @@ npm-run-path@^2.0.0:
   dependencies:
     path-key "^2.0.0"
 
-npmlog@^4.0.2:
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
   integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@@ -6720,6 +6966,13 @@ os-homedir@^1.0.0:
   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
   integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
 
+os-locale@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+  integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
+  dependencies:
+    lcid "^1.0.0"
+
 os-locale@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
@@ -6743,7 +6996,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
 
-osenv@^0.1.4:
+osenv@0, osenv@^0.1.4:
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
   integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
@@ -7703,6 +7956,14 @@ realpath-native@^1.0.0:
   dependencies:
     util.promisify "^1.0.0"
 
+redent@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+  integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
+  dependencies:
+    indent-string "^2.1.0"
+    strip-indent "^1.0.1"
+
 regenerate-unicode-properties@^7.0.0:
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
@@ -7861,7 +8122,7 @@ request-promise-native@^1.0.5:
     stealthy-require "^1.1.0"
     tough-cookie ">=2.3.3"
 
-request@^2.87.0:
+request@^2.87.0, request@^2.88.0:
   version "2.88.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
   integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
@@ -7982,7 +8243,7 @@ rgba-regex@^1.0.0:
   resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
   integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
 
-rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
   integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
@@ -8073,6 +8334,28 @@ sane@^2.0.0:
   optionalDependencies:
     fsevents "^1.2.3"
 
+sass-graph@^2.2.4:
+  version "2.2.4"
+  resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
+  integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=
+  dependencies:
+    glob "^7.0.0"
+    lodash "^4.0.0"
+    scss-tokenizer "^0.2.3"
+    yargs "^7.0.0"
+
+sass-loader@^7.0.1:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d"
+  integrity sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==
+  dependencies:
+    clone-deep "^2.0.1"
+    loader-utils "^1.0.1"
+    lodash.tail "^4.1.1"
+    neo-async "^2.5.0"
+    pify "^3.0.0"
+    semver "^5.5.0"
+
 sax@^1.2.4, sax@~1.2.4:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@@ -8095,6 +8378,14 @@ schema-utils@^1.0.0:
     ajv-errors "^1.0.0"
     ajv-keywords "^3.1.0"
 
+scss-tokenizer@^0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
+  integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE=
+  dependencies:
+    js-base64 "^2.1.8"
+    source-map "^0.4.2"
+
 select-hose@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -8112,6 +8403,11 @@ selfsigned@^1.9.1:
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
   integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
 
+semver@~5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+  integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
+
 send@0.16.2:
   version "0.16.2"
   resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
@@ -8202,6 +8498,15 @@ sha.js@^2.4.0, sha.js@^2.4.8:
     inherits "^2.0.1"
     safe-buffer "^5.0.1"
 
+shallow-clone@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571"
+  integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==
+  dependencies:
+    is-extendable "^0.1.1"
+    kind-of "^5.0.0"
+    mixin-object "^2.0.1"
+
 shebang-command@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -8363,6 +8668,13 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
   integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
 
+source-map@^0.4.2:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
+  integrity sha1-66T12pwNyZneaAMti092FzZSA2s=
+  dependencies:
+    amdefine ">=0.0.4"
+
 source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
@@ -8496,6 +8808,13 @@ statuses@~1.4.0:
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
   integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
 
+stdout-stream@^1.4.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de"
+  integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==
+  dependencies:
+    readable-stream "^2.0.1"
+
 stealthy-require@^1.1.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
@@ -8541,7 +8860,7 @@ string-length@^2.0.0:
     astral-regex "^1.0.0"
     strip-ansi "^4.0.0"
 
-string-width@^1.0.1:
+string-width@^1.0.1, string-width@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
   integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
@@ -8650,6 +8969,13 @@ strip-eof@^1.0.0:
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
   integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
 
+strip-indent@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+  integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
+  dependencies:
+    get-stdin "^4.0.1"
+
 strip-indent@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
@@ -8740,6 +9066,15 @@ tapable@^1.0.0, tapable@^1.1.0:
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e"
   integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==
 
+tar@^2.0.0:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
+  integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=
+  dependencies:
+    block-stream "*"
+    fstream "^1.0.2"
+    inherits "2"
+
 tar@^4:
   version "4.4.8"
   resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d"
@@ -8935,11 +9270,23 @@ tr46@^1.0.1:
   dependencies:
     punycode "^2.1.0"
 
+trim-newlines@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+  integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
+
 trim-right@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
   integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
 
+"true-case-path@^1.0.2":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
+  integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==
+  dependencies:
+    glob "^7.1.2"
+
 tryer@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
@@ -9547,12 +9894,17 @@ whatwg-url@^7.0.0:
     tr46 "^1.0.1"
     webidl-conversions "^4.0.2"
 
+which-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+  integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=
+
 which-module@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
   integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
 
-which@^1.2.12, which@^1.2.9, which@^1.3.0:
+which@1, which@^1.2.12, which@^1.2.9, which@^1.3.0:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
   integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -9800,6 +10152,13 @@ yargs-parser@^10.1.0:
   dependencies:
     camelcase "^4.1.0"
 
+yargs-parser@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
+  integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=
+  dependencies:
+    camelcase "^3.0.0"
+
 yargs-parser@^9.0.2:
   version "9.0.2"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
@@ -9843,6 +10202,25 @@ yargs@^11.0.0:
     y18n "^3.2.1"
     yargs-parser "^9.0.2"
 
+yargs@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
+  integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=
+  dependencies:
+    camelcase "^3.0.0"
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    os-locale "^1.4.0"
+    read-pkg-up "^1.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^1.0.2"
+    which-module "^1.0.0"
+    y18n "^3.2.1"
+    yargs-parser "^5.0.0"
+
 yorkie@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/yorkie/-/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9"