zhangjie 4 년 전
부모
커밋
1823cb2a0c
37개의 변경된 파일649개의 추가작업 그리고 230개의 파일을 삭제
  1. BIN
      src/assets/bg-angle.png
  2. BIN
      src/assets/icon-add.png
  3. BIN
      src/assets/icon-copy.png
  4. BIN
      src/assets/icon-download.png
  5. BIN
      src/assets/icon-right.png
  6. BIN
      src/assets/icon-ring.png
  7. BIN
      src/assets/icon-wrong.png
  8. 1 1
      src/components/ActivitySelect.vue
  9. 1 1
      src/components/CourseSelect.vue
  10. 1 1
      src/components/ExamRoomSelect.vue
  11. 1 1
      src/components/ExamSelect.vue
  12. 2 2
      src/components/ExamTypeSelect.vue
  13. 1 1
      src/components/InvigilatorSelect.vue
  14. 1 1
      src/components/OrgSelect.vue
  15. 1 1
      src/components/RoleSelect.vue
  16. 2 2
      src/components/StateSelect.vue
  17. 1 1
      src/components/TaskSelect.vue
  18. 35 22
      src/features/examwork/CourseManagement/CourseManagement.vue
  19. 50 15
      src/features/examwork/ExamManagement/ExamEdit.vue
  20. 35 17
      src/features/examwork/ExamManagement/ExamManagement.vue
  21. 29 13
      src/features/examwork/ExamStudentImport/ExamStudentImport.vue
  22. 56 38
      src/features/examwork/ExamStudentManagement/ExamStudentManagement.vue
  23. 19 10
      src/features/examwork/ImportExportTask/ImportExportTask.vue
  24. 36 15
      src/features/examwork/InvigilateManagement/InvigilateManagement.vue
  25. 24 15
      src/features/examwork/StudentManagement/StudentManagement.vue
  26. 73 12
      src/features/invigilation/RealtimeMonitoring/RealtimeMonitoring.vue
  27. 12 0
      src/features/invigilation/WainingManage/WainingManage.vue
  28. 23 0
      src/features/invigilation/common/RightOrWrong.vue
  29. 31 17
      src/features/system/OrgManagement/OrgManagement.vue
  30. 37 23
      src/features/system/UserManagement/UserManagement.vue
  31. 6 0
      src/router/index.js
  32. 57 0
      src/styles/base.scss
  33. 54 5
      src/styles/element-ui-custom.scss
  34. 23 0
      src/styles/icons.scss
  35. 10 8
      src/views/Layout/Layout.vue
  36. 18 3
      src/views/Layout/components/NavBar.vue
  37. 9 5
      src/views/Layout/components/SideBar.vue

BIN
src/assets/bg-angle.png


BIN
src/assets/icon-add.png


BIN
src/assets/icon-copy.png


BIN
src/assets/icon-download.png


BIN
src/assets/icon-right.png


BIN
src/assets/icon-ring.png


BIN
src/assets/icon-wrong.png


+ 1 - 1
src/components/ActivitySelect.vue

@@ -29,7 +29,7 @@ export default {
   props: {
     value: String,
     examId: String,
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/CourseSelect.vue

@@ -29,7 +29,7 @@ export default {
   props: {
     value: String,
     examId: String,
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/ExamRoomSelect.vue

@@ -27,7 +27,7 @@ export default {
   name: "ExamRoomSelect",
   props: {
     value: [String, Array],
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/ExamSelect.vue

@@ -28,7 +28,7 @@ export default {
   name: "ExamSelect",
   props: {
     value: String,
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 2 - 2
src/components/ExamTypeSelect.vue

@@ -2,7 +2,7 @@
   <el-select
     v-model="selected"
     class="size-select"
-    placeholder="请选择"
+    placeholder="考试类型"
     @change="select"
     :style="styles"
     clearable
@@ -26,7 +26,7 @@ export default {
       type: String,
       default: "",
     },
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/InvigilatorSelect.vue

@@ -26,7 +26,7 @@ export default {
   props: {
     value: [String, Array],
     multiple: Boolean,
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/OrgSelect.vue

@@ -23,7 +23,7 @@ export default {
   name: "OrgSelect",
   props: {
     value: [String, Array],
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/RoleSelect.vue

@@ -25,7 +25,7 @@ export default {
   props: {
     value: [String, Array],
     multiple: Boolean,
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 2 - 2
src/components/StateSelect.vue

@@ -2,7 +2,7 @@
   <el-select
     v-model="selected"
     class="size-select"
-    placeholder="请选择"
+    placeholder="考试状态"
     @change="select"
     :style="styles"
     clearable
@@ -27,7 +27,7 @@ export default {
       default: 1,
     },
     options: { type: Array, default: () => null },
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 1 - 1
src/components/TaskSelect.vue

@@ -27,7 +27,7 @@ export default {
       default: "",
     },
     options: { type: Array, default: () => null },
-    styles: { type: String, default: "width: 100px;" },
+    styles: { type: String },
   },
   data() {
     return {

+ 35 - 22
src/features/examwork/CourseManagement/CourseManagement.vue

@@ -1,26 +1,39 @@
 <template>
-  <div>
-    <el-form ref="form" :model="form" :rules="rules" inline>
-      <el-form-item label="批次名称" prop="examId">
-        <ExamSelect v-model="form.examId" />
-      </el-form-item>
-      <el-form-item label="科目名称">
-        <CourseSelect :examId="form.examId" v-model="form.code" />
-      </el-form-item>
-      <el-form-item label="状态">
-        <StateSelect
-          :options="[
-            { code: 0, name: '未绑卷' },
-            { code: 1, name: '已绑卷' },
-          ]"
-          v-model="form.hasPaper"
-        />
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="importPaper">导入试卷</el-button>
-    </el-form>
+  <div class="course-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>预警提醒</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form ref="form" :model="form" :rules="rules" inline>
+          <el-form-item label="批次名称" prop="examId">
+            <ExamSelect v-model="form.examId" />
+          </el-form-item>
+          <el-form-item label="科目名称">
+            <CourseSelect :examId="form.examId" v-model="form.code" />
+          </el-form-item>
+          <el-form-item label="状态">
+            <StateSelect
+              :options="[
+                { code: 0, name: '未绑卷' },
+                { code: 1, name: '已绑卷' },
+              ]"
+              v-model="form.hasPaper"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+        <div class="part-filter-form-action">
+          <el-button type="primary" icon="icon icon-upload" @click="importPaper"
+            >导入试卷</el-button
+          >
+        </div>
+      </div>
+    </div>
 
-    <el-table :data="tableData" stripe style="width: 100%;">
+    <el-table :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -62,7 +75,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 50 - 15
src/features/examwork/ExamManagement/ExamEdit.vue

@@ -160,10 +160,10 @@
 
       <el-tab-pane label="监考设置" name="second">
         <el-form :model="form" label-width="180px" inline>
-          <el-row>
+          <el-row class="tab-invililation">
             <h2>开考检测</h2>
             <el-form-item label="">
-              <div class="d-flex flex-column" style="padding-left: 80px;">
+              <div class="d-flex flex-column tab-invililation-radio">
                 <el-radio v-model="form.entryAuthenticationPolicy" label="OFF">
                   安全级别:<span style="color: #202b4b; font-size: 20px;">
@@ -202,8 +202,8 @@
               </div>
             </el-form-item>
           </el-row>
-          <h2>过程监控</h2>
-          <el-row>
+          <el-row class="tab-invililation">
+            <h2>过程监控</h2>
             <el-form-item label="是否考中人脸识别">
               <el-radio v-model="form.inProcessFaceVerify" :label="1"
                 >是
@@ -265,8 +265,8 @@
               </el-radio>
             </el-form-item>
           </el-row>
-          <h2>监考直播</h2>
-          <el-row>
+          <el-row class="tab-invililation">
+            <h2>监考直播</h2>
             <el-form-item label="是否开启考生端监考直播">
               <el-radio v-model="form.monitorProxy" :label="true">是 </el-radio>
               <el-radio v-model="form.monitorProxy" :label="false"
@@ -334,8 +334,10 @@
       </el-tab-pane>
     </el-tabs>
 
-    <el-button @click="save">保存</el-button>
-    <el-button @click="cancel">取消</el-button>
+    <div class="tab-footer">
+      <el-button type="primary" @click="save">保存</el-button>
+      <el-button @click="cancel">取消</el-button>
+    </div>
   </div>
 </template>
 
@@ -457,12 +459,45 @@ export default {
 };
 </script>
 
-<style>
-.desc-txt {
-  color: #fe5863;
-  border: 1px solid #fe5863;
-  border-radius: 4px;
-  padding: 4px;
-  margin-left: 10px;
+<style lang="scss" scoped>
+.tab-invililation {
+  > h2 {
+    font-size: 20px;
+    font-weight: 500;
+    color: #8c94ac;
+    line-height: 28px;
+    margin-bottom: 26px;
+  }
+
+  &-radio {
+    padding-left: 30px;
+    .el-radio {
+      margin-bottom: 18px;
+      height: 30px;
+    }
+  }
+
+  .desc-txt {
+    color: #fe5863;
+    border: 1px solid #fe5863;
+    border-radius: 0 6px 6px 0;
+    padding: 6px 10px 6px 16px;
+    margin-left: 20px;
+    border-left: 0;
+    position: relative;
+
+    &::before {
+      content: "";
+      display: block;
+      position: absolute;
+      width: 12px;
+      height: 30px;
+      left: -11px;
+      top: -1px;
+      background-image: url(../../../assets/bg-angle.png);
+      background-repeat: no-repeat;
+      background-size: 100% 100%;
+    }
+  }
 }
 </style>

+ 35 - 17
src/features/examwork/ExamManagement/ExamManagement.vue

@@ -1,21 +1,39 @@
 <template>
-  <div>
-    <el-form :model="form" inline>
-      <el-form-item label="批次名称">
-        <el-input v-model.trim="form.name"></el-input>
-      </el-form-item>
-      <el-form-item label="类型">
-        <ExamTypeSelect v-model="form.mode"></ExamTypeSelect>
-      </el-form-item>
-      <el-form-item label="状态">
-        <StateSelect v-model="form.enableState"></StateSelect>
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="add">新增</el-button>
-      <el-button @click="copy">复制</el-button>
-    </el-form>
+  <div class="exam-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>批次管理</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form :model="form" inline>
+          <el-form-item label="批次名称">
+            <el-input
+              v-model.trim="form.name"
+              placeholder="输入批次名称"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="类型">
+            <ExamTypeSelect v-model="form.mode"></ExamTypeSelect>
+          </el-form-item>
+          <el-form-item label="状态">
+            <StateSelect v-model="form.enableState"></StateSelect>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+        <div class="part-filter-form-action">
+          <el-button type="primary" icon="icon icon-add" @click="add"
+            >新增</el-button
+          >
+          <el-button type="primary" icon="icon icon-copy" @click="copy"
+            >复制</el-button
+          >
+        </div>
+      </div>
+    </div>
 
-    <el-table ref="table" :data="tableData" stripe style="width: 100%;">
+    <el-table ref="table" :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -89,7 +107,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 29 - 13
src/features/examwork/ExamStudentImport/ExamStudentImport.vue

@@ -1,17 +1,33 @@
 <template>
-  <div>
-    <!-- 下载链接 -->
-    <el-form ref="form" :model="form" :rules="rules" inline>
-      <el-form-item label="批次名称" prop="examId">
-        <ExamSelect v-model="form.examId" />
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="importFile">导入</el-button>
-      <!-- <el-button>导入</el-button> -->
-      <a :href="downloadUrl" download class="mx-2">下载模板</a>
-    </el-form>
+  <div class="exam-student-import">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>考生导入</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <!-- 下载链接 -->
+        <el-form ref="form" :model="form" :rules="rules" inline>
+          <el-form-item label="批次名称" prop="examId">
+            <ExamSelect v-model="form.examId" />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+
+        <div class="part-filter-form-action">
+          <el-button type="primary" icon="icon icon-upload" @click="importFile"
+            >导入</el-button
+          >
+          <!-- <el-button>导入</el-button> -->
+          <el-button type="text">
+            <a :href="downloadUrl" download class="mx-2">下载模板</a>
+          </el-button>
+        </div>
+      </div>
+    </div>
 
-    <el-table :data="tableData" stripe style="width: 100%;">
+    <el-table :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -61,7 +77,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 56 - 38
src/features/examwork/ExamStudentManagement/ExamStudentManagement.vue

@@ -1,42 +1,60 @@
 <template>
-  <div>
-    <el-form ref="form" :model="form" :rules="rules" inline>
-      <el-form-item label="批次名称" prop="examId">
-        <ExamSelect v-model="form.examId" />
-      </el-form-item>
-      <el-form-item label="场次代码">
-        <ActivitySelect :examId="form.examId" v-model="form.activityId" />
-      </el-form-item>
-      <el-form-item label="考场名称">
-        <ExamRoomSelect v-model="form.roomCode" />
-      </el-form-item>
-      <el-form-item label="科目">
-        <CourseSelect :examId="form.examId" v-model="form.courseCode" />
-      </el-form-item>
-      <el-form-item label="姓名">
-        <el-input v-model.trim="form.name"></el-input>
-      </el-form-item>
-      <el-form-item label="证件号">
-        <el-input v-model.trim="form.identity"></el-input>
-      </el-form-item>
-      <el-form-item label="年级">
-        <el-input v-model.trim="form.grade"></el-input>
-      </el-form-item>
-      <el-form-item label="教学班级">
-        <el-input v-model.trim="form.classNo"></el-input>
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="add">新增</el-button>
-      <el-button @click="toggleEnableExamStudentArray({ enable: 1 })"
-        >启用</el-button
-      >
-      <el-button @click="toggleEnableExamStudentArray({ enable: 0 })"
-        >禁用</el-button
-      >
-      <!-- <el-button>导入</el-button> -->
-    </el-form>
+  <div class="exam-student-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>考生管理</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form ref="form" :model="form" :rules="rules" inline>
+          <el-form-item label="批次名称" prop="examId">
+            <ExamSelect v-model="form.examId" />
+          </el-form-item>
+          <el-form-item label="场次代码">
+            <ActivitySelect :examId="form.examId" v-model="form.activityId" />
+          </el-form-item>
+          <el-form-item label="考场名称">
+            <ExamRoomSelect v-model="form.roomCode" />
+          </el-form-item>
+          <el-form-item label="科目">
+            <CourseSelect :examId="form.examId" v-model="form.courseCode" />
+          </el-form-item>
+          <el-form-item label="姓名">
+            <el-input v-model.trim="form.name"></el-input>
+          </el-form-item>
+          <el-form-item label="证件号">
+            <el-input v-model.trim="form.identity"></el-input>
+          </el-form-item>
+          <el-form-item label="年级">
+            <el-input v-model.trim="form.grade"></el-input>
+          </el-form-item>
+          <el-form-item label="教学班级">
+            <el-input v-model.trim="form.classNo"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+
+        <div class="part-filter-form-action">
+          <el-button type="primary" icon="icon icon-add" @click="add"
+            >新增</el-button
+          >
+          <el-button
+            type="success"
+            @click="toggleEnableExamStudentArray({ enable: 1 })"
+            >启用</el-button
+          >
+          <el-button
+            type="danger"
+            @click="toggleEnableExamStudentArray({ enable: 0 })"
+            >禁用</el-button
+          >
+          <!-- <el-button>导入</el-button> -->
+        </div>
+      </div>
+    </div>
 
-    <el-table ref="table" :data="tableData" stripe style="width: 100%;">
+    <el-table ref="table" :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -89,7 +107,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 19 - 10
src/features/examwork/ImportExportTask/ImportExportTask.vue

@@ -1,14 +1,23 @@
 <template>
-  <div>
-    <!-- 下载链接 -->
-    <el-form ref="form" :model="form" :rules="rules" inline>
-      <el-form-item label="任务名称" prop="type">
-        <TaskSelect v-model="form.type" />
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-    </el-form>
+  <div class="import-export-task">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>预警提醒</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <!-- 下载链接 -->
+        <el-form ref="form" :model="form" :rules="rules" inline>
+          <el-form-item label="任务名称" prop="type">
+            <TaskSelect v-model="form.type" />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
 
-    <el-table :data="tableData" stripe style="width: 100%;">
+    <el-table :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -58,7 +67,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 36 - 15
src/features/examwork/InvigilateManagement/InvigilateManagement.vue

@@ -1,21 +1,42 @@
 <template>
-  <div>
-    <el-form :model="form" inline>
-      <!-- <el-form-item v-if="$store.state.user.orgId === null" label="机构">
+  <div class="invigilate-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>考场监考设置</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form :model="form" inline>
+          <!-- <el-form-item v-if="$store.state.user.orgId === null" label="机构">
         <OrgSelect v-model="form.orgId"></OrgSelect>
       </el-form-item> -->
-      <el-form-item label="考场">
-        <ExamRoomSelect v-model="form.roomCode"></ExamRoomSelect>
-      </el-form-item>
-      <el-form-item label="监考老师">
-        <InvigilatorSelect v-model="form.userId"></InvigilatorSelect>
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="importDialog">导入考场设置</el-button>
-      <el-button @click="exportInvigilate">导出考场安排</el-button>
-      <a :href="downloadUrl" download class="mx-2">下载导入模板</a>
-      <!-- <el-button>导入</el-button> -->
-    </el-form>
+          <el-form-item label="考场">
+            <ExamRoomSelect v-model="form.roomCode"></ExamRoomSelect>
+          </el-form-item>
+          <el-form-item label="监考老师">
+            <InvigilatorSelect v-model="form.userId"></InvigilatorSelect>
+          </el-form-item>
+          <el-button type="primary" @click="searchForm">查询</el-button>
+        </el-form>
+        <div class="part-filter-form-action">
+          <el-button
+            type="primary"
+            icon="icon icon-upload"
+            @click="importDialog"
+            >导入考场设置</el-button
+          >
+          <el-button
+            type="primary"
+            icon="icon icon-upload"
+            @click="exportInvigilate"
+            >导出考场安排</el-button
+          >
+          <el-button type="text">
+            <a :href="downloadUrl" download class="mx-2">下载导入模板</a>
+          </el-button>
+          <!-- <el-button>导入</el-button> -->
+        </div>
+      </div>
+    </div>
 
     <el-table :data="tableData" stripe style="width: 100%;">
       <!-- <el-table-column type="selection" width="42" />

+ 24 - 15
src/features/examwork/StudentManagement/StudentManagement.vue

@@ -1,19 +1,28 @@
 <template>
-  <div>
-    <el-form :model="form" inline>
-      <el-form-item label="姓名">
-        <el-input v-model.trim="form.name"></el-input>
-      </el-form-item>
-      <el-form-item label="证件号">
-        <el-input v-model.trim="form.identity"></el-input>
-      </el-form-item>
-      <el-form-item label="状态">
-        <StateSelect v-model="form.enable"></StateSelect>
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-    </el-form>
+  <div class="student-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>学生档案设置</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form :model="form" inline>
+          <el-form-item label="姓名">
+            <el-input v-model.trim="form.name"></el-input>
+          </el-form-item>
+          <el-form-item label="证件号">
+            <el-input v-model.trim="form.identity"></el-input>
+          </el-form-item>
+          <el-form-item label="状态">
+            <StateSelect v-model="form.enable"></StateSelect>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
 
-    <el-table :data="tableData" stripe style="width: 100%;">
+    <el-table :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -83,7 +92,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 73 - 12
src/features/invigilation/RealtimeMonitoring/RealtimeMonitoring.vue

@@ -60,12 +60,18 @@
           :exam-id="filter.examId"
         ></summary-line>
         <div class="part-filter-info-sub">
-          <el-button
-            icon="el-icon-phone-outline"
-            type="success"
-            @click="toCommunication"
-            >通话待办</el-button
+          <el-badge
+            :value="communicationCount"
+            :max="99"
+            :hidden="!communicationCount"
           >
+            <el-button
+              icon="icon icon-ring"
+              type="success"
+              @click="toCommunication"
+              >通话待办</el-button
+            >
+          </el-badge>
         </div>
       </div>
 
@@ -187,11 +193,20 @@
       <el-table-column prop="paperDownload" label="试题下载"></el-table-column>
       <el-table-column prop="status" label="考试状态"></el-table-column>
       <el-table-column prop="progress" label="进度"></el-table-column>
-      <el-table-column
-        prop="clientCommunicationStatus"
-        label="通讯"
-      ></el-table-column>
-      <el-table-column prop="subjectCode" label="推流通讯"></el-table-column>
+      <el-table-column prop="clientCommunicationStatus" label="通讯">
+        <template slot-scope="scope">
+          <right-or-wrong
+            :status="scope.row.clientCommunicationStatus"
+          ></right-or-wrong>
+        </template>
+      </el-table-column>
+      <el-table-column prop="subjectCode" label="推流通讯">
+        <template slot-scope="scope">
+          <right-or-wrong
+            :status="scope.row.clientCommunicationStatus"
+          ></right-or-wrong>
+        </template>
+      </el-table-column>
       <el-table-column prop="clientCurrentIp" label="IP"></el-table-column>
       <el-table-column prop="updateTime" label="更新时间"></el-table-column>
       <el-table-column prop="warningCount" label="预警数"></el-table-column>
@@ -251,6 +266,7 @@ import {
   invigilateExamFinish,
 } from "@/api/invigilation";
 import ExamBatchDialog from "./ExamBatchDialog";
+import RightOrWrong from "../common/RightOrWrong";
 import InvigilationStudent from "../common/InvigilationStudent";
 import SummaryLine from "../common/SummaryLine";
 import handleRollupDialog from "./handleRollupDialog";
@@ -260,6 +276,7 @@ export default {
   name: "realtime-monitoring",
   components: {
     ExamBatchDialog,
+    RightOrWrong,
     InvigilationStudent,
     SummaryLine,
     handleRollupDialog,
@@ -277,6 +294,7 @@ export default {
         minWarningCount: undefined,
       },
       hasNewWarning: false,
+      communicationCount: 0,
       curExamBatch: {},
       curViewingAngle: {},
       current: 1,
@@ -291,7 +309,29 @@ export default {
       dataList: [
         {
           breachStatus: 0,
-          clientCommunicationStatus: "12",
+          clientCommunicationStatus: 0,
+          clientCurrentIp: "192.168.10.12",
+          courseCode: "F001",
+          courseName: "数学",
+          examActivityId: 0,
+          examId: 111,
+          examRecordId: 222,
+          examStudentId: 333,
+          identity: "000000000000008",
+          monitorStatusSource: "",
+          name: "楚一一",
+          paperDownload: 0,
+          progress: 0,
+          roomCode: "123",
+          roomName: "第一教师",
+          status: "1",
+          statusCode: "1",
+          updateTime: "2020-12-12",
+          warningCount: 0,
+        },
+        {
+          breachStatus: 0,
+          clientCommunicationStatus: 1,
           clientCurrentIp: "192.168.10.12",
           courseCode: "F001",
           courseName: "数学",
@@ -329,7 +369,25 @@ export default {
       ],
     };
   },
-  mounted() {},
+  mounted() {
+    window.inviligateWaining = (id) => {
+      console.log(id);
+    };
+    this.$notify({
+      duration: 0,
+      dangerouslyUseHTMLString: true,
+      customClass: "msg-monitor-magbox",
+      position: "bottom-right",
+      offset: 50,
+      message: `
+        <div class="msg-monitor">
+          <span class="msg-monitor-icon"><i class="icon icon-warning"></i></span>
+          <span>注意:<b>张三意识</b>发现违纪,</span>
+          <span class="msg-monitor-action" onclick="window.inviligateWaining(12)">立即处理</span>
+        </div>
+      `,
+    });
+  },
   methods: {
     async getList() {
       const datas = {
@@ -412,6 +470,9 @@ export default {
       });
     },
   },
+  beforeDestroy() {
+    delete window.inviligateWaining;
+  },
 };
 </script>
 

+ 12 - 0
src/features/invigilation/WainingManage/WainingManage.vue

@@ -132,6 +132,18 @@
       </div>
     </div>
 
+    <!-- <div class="part-box-head">
+      <div class="part-box-head-left"><h1>预警提醒</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+
+        <div class="part-filter-form-action">
+
+        </div>
+      </div>
+    </div> -->
+
     <el-table
       ref="TableList"
       :data="dataList"

+ 23 - 0
src/features/invigilation/common/RightOrWrong.vue

@@ -0,0 +1,23 @@
+<template>
+  <i :class="classes"></i>
+</template>
+
+<script>
+export default {
+  name: "right-or-wrong",
+  props: {
+    status: {
+      type: Boolean,
+    },
+  },
+  computed: {
+    classes() {
+      return [
+        "right-or-wrong",
+        "icon",
+        this.status ? "icon-right" : "icon-wrong",
+      ];
+    },
+  },
+};
+</script>

+ 31 - 17
src/features/system/OrgManagement/OrgManagement.vue

@@ -1,21 +1,34 @@
 <template>
-  <div>
-    <el-form :model="form" inline>
-      <el-form-item label="中心代码">
-        <el-input v-model.trim="form.code"></el-input>
-      </el-form-item>
-      <el-form-item label="中心名称">
-        <el-input v-model.trim="form.name"></el-input>
-      </el-form-item>
-      <el-form-item label="状态">
-        <StateSelect v-model="form.enableState"></StateSelect>
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="add">新增</el-button>
-      <!-- <el-button>导入</el-button> -->
-    </el-form>
+  <div class="org-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>机构管理</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form :model="form" inline>
+          <el-form-item label="中心代码">
+            <el-input v-model.trim="form.code"></el-input>
+          </el-form-item>
+          <el-form-item label="中心名称">
+            <el-input v-model.trim="form.name"></el-input>
+          </el-form-item>
+          <el-form-item label="状态">
+            <StateSelect v-model="form.enableState"></StateSelect>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+        <div class="part-filter-form-action">
+          <el-button type="primary" icon="icon icon-add" @click="add"
+            >新增</el-button
+          >
+          <!-- <el-button>导入</el-button> -->
+        </div>
+      </div>
+    </div>
 
-    <el-table :data="tableData" stripe style="width: 100%;">
+    <el-table :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -61,7 +74,7 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"
@@ -72,6 +85,7 @@
         :total="total"
       />
     </div>
+
     <OrgManagementDialog
       ref="theDialog"
       :org="selectedOrg"

+ 37 - 23
src/features/system/UserManagement/UserManagement.vue

@@ -1,27 +1,40 @@
 <template>
-  <div>
-    <el-form :model="form" inline>
-      <!-- <el-form-item v-if="$store.state.user.orgId === null" label="机构">
-        <OrgSelect v-model="form.orgId"></OrgSelect>
-      </el-form-item> -->
-      <el-form-item label="角色">
-        <RoleSelect v-model="form.roleCode"></RoleSelect>
-      </el-form-item>
-      <el-form-item label="登录名">
-        <el-input v-model.trim="form.loginName"></el-input>
-      </el-form-item>
-      <el-form-item label="姓名">
-        <el-input v-model.trim="form.name"></el-input>
-      </el-form-item>
-      <el-form-item label="状态">
-        <StateSelect v-model="form.enableState"></StateSelect>
-      </el-form-item>
-      <el-button @click="searchForm">查询</el-button>
-      <el-button @click="add">新增</el-button>
-      <!-- <el-button>导入</el-button> -->
-    </el-form>
+  <div class="user-management">
+    <div class="part-box-head">
+      <div class="part-box-head-left"><h1>用户管理</h1></div>
+    </div>
+    <div class="part-filter">
+      <div class="part-filter-form">
+        <el-form :model="form" inline>
+          <!-- <el-form-item v-if="$store.state.user.orgId === null" label="机构">
+            <OrgSelect v-model="form.orgId"></OrgSelect>
+          </el-form-item> -->
+          <el-form-item label="角色">
+            <RoleSelect v-model="form.roleCode"></RoleSelect>
+          </el-form-item>
+          <el-form-item label="登录名">
+            <el-input v-model.trim="form.loginName"></el-input>
+          </el-form-item>
+          <el-form-item label="姓名">
+            <el-input v-model.trim="form.name"></el-input>
+          </el-form-item>
+          <el-form-item label="状态">
+            <StateSelect v-model="form.enableState"></StateSelect>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="searchForm">查询</el-button>
+          </el-form-item>
+        </el-form>
+        <div class="part-filter-form-action">
+          <el-button icon="icon icon-add" type="primary" @click="add"
+            >新增</el-button
+          >
+          <!-- <el-button>导入</el-button> -->
+        </div>
+      </div>
+    </div>
 
-    <el-table :data="tableData" stripe style="width: 100%;">
+    <el-table :data="tableData">
       <el-table-column type="selection" width="42" />
       <el-table-column width="100" label="ID">
         <span slot-scope="scope">{{ scope.row.id }}</span>
@@ -79,7 +92,8 @@
         </div>
       </el-table-column>
     </el-table>
-    <div class="page float-right">
+
+    <div class="part-page">
       <el-pagination
         @current-change="handleCurrentChange"
         :current-page="currentPage"

+ 6 - 0
src/router/index.js

@@ -89,6 +89,9 @@ const routes = [
           import(
             /* webpackChunkName: "exam" */ "../features/examwork/ExamManagement/ExamEdit.vue"
           ),
+        meta: {
+          relate: "ExamManagement",
+        },
       },
       {
         path: ":examId/activity",
@@ -105,6 +108,9 @@ const routes = [
           import(
             /* webpackChunkName: "exam" */ "../features/examwork/ActivityManagement/ActivityEdit.vue"
           ),
+        meta: {
+          relate: "ActivityManagement",
+        },
       },
       {
         path: "examstudent",

+ 57 - 0
src/styles/base.scss

@@ -164,6 +164,14 @@ body {
 .tips-error {
   color: rgba(254, 88, 99, 1);
 }
+.tab-footer {
+  padding: 30px;
+  background-color: #fff;
+  border-radius: 0 0 6px 6px;
+  .el-button {
+    width: 83px;
+  }
+}
 
 // :fullscreen
 .app-fullscreen {
@@ -241,6 +249,45 @@ body {
   }
 }
 
+// realtim-monitoring msg-monitor
+.msg-monitor {
+  color: #202b4b;
+  > span {
+    display: inline-block;
+    vertical-align: middle;
+    > b {
+      margin: 0 3px;
+    }
+  }
+  &-icon {
+    height: 36px;
+    width: 36px;
+    background-color: #fe5863;
+    padding-top: 6px;
+    text-align: center;
+    border-radius: 50%;
+    margin-right: 10px;
+    > i {
+      width: 18px;
+      height: 17px;
+    }
+  }
+  &-action {
+    color: #1886fe;
+    cursor: pointer;
+
+    &:hover {
+      font-weight: 600;
+    }
+  }
+}
+.msg-monitor-magbox {
+  width: 400px;
+  .el-notification__closeBtn {
+    top: 28px;
+  }
+}
+
 // communication-dialog
 .communication-dialog {
   background-color: transparent;
@@ -382,3 +429,13 @@ body {
     font-weight: 400;
   }
 }
+
+// student-log-detail-dialog
+.student-log-detail-dialog {
+  .el-dialog {
+    background: #f0f4f9;
+  }
+  .el-dialog__footer {
+    display: none;
+  }
+}

+ 54 - 5
src/styles/element-ui-custom.scss

@@ -117,6 +117,10 @@
       }
     }
   }
+  span:not([class*="suffix"]) {
+    height: 32px;
+    line-height: 32px;
+  }
   &__total {
     color: #8c94ac;
     margin: 0 16px 0 6px;
@@ -164,9 +168,6 @@
 .el-message-box {
   color: #202b4b;
   border-radius: 10px;
-}
-.el-message-box__error {
-  width: 540px;
   .el-message-box__header {
     padding: 16px 20px;
     border-bottom: 1px solid rgba(240, 244, 249, 1);
@@ -182,12 +183,60 @@
   }
   .el-message-box__message {
     padding-left: 50px;
+    padding-top: 4px;
+    font-size: 16px;
+    color: #202b4b;
+    line-height: 22px;
   }
-  .el-icon-warning {
-    color: #fe5863;
+  .el-message-box__status {
     font-size: 32px !important;
     top: 0;
     left: 0;
     transform: none;
   }
 }
+.el-message-box__error {
+  width: 540px;
+  .el-message-box__status {
+    color: #fe5863;
+  }
+}
+.el-message-box__warning {
+  .el-message-box__status {
+    color: #5fc9fa;
+  }
+}
+
+// el-tabs
+.el-tabs {
+  .el-tabs__header {
+    margin-bottom: 0;
+  }
+  .el-tabs__content {
+    background-color: #fff;
+    padding: 30px;
+  }
+
+  .el-tabs__item {
+    color: #626a82;
+    border: none;
+    background-color: #fff;
+    border-radius: 6px 6px 0 0;
+    margin-right: 12px;
+
+    &.is-active {
+      color: #202b4b;
+      font-weight: 600;
+    }
+  }
+}
+.el-tabs--card > .el-tabs__header .el-tabs__nav {
+  border: none;
+}
+
+// .el-form
+.el-form {
+  &-item__label {
+    color: #202b4b;
+  }
+}

+ 23 - 0
src/styles/icons.scss

@@ -79,12 +79,35 @@
     height: 12px;
     background-image: url(../assets/icon-upload.png);
   }
+  &-download {
+    height: 12px;
+    background-image: url(../assets/icon-download.png);
+  }
   &-analysis {
     background-image: url(../assets/icon-analysis.png);
   }
   &-rate {
     background-image: url(../assets/icon-rate.png);
   }
+  &-add {
+    background-image: url(../assets/icon-add.png);
+  }
+  &-copy {
+    background-image: url(../assets/icon-copy.png);
+  }
+  &-ring {
+    background-image: url(../assets/icon-ring.png);
+  }
+  &-right {
+    width: 15px;
+    height: 12px;
+    background-image: url(../assets/icon-right.png);
+  }
+  &-wrong {
+    width: 13px;
+    height: 12px;
+    background-image: url(../assets/icon-wrong.png);
+  }
   &-users {
     height: 13px;
     background-image: url(../assets/icon-users.png);

+ 10 - 8
src/views/Layout/Layout.vue

@@ -1,11 +1,7 @@
 <template>
   <div class="app-wrapper">
     <nav-bar :navs="navs" @on-nav-change="navChange" v-if="navs.length" />
-    <side-bar
-      class="sidebar-container"
-      :menus="curMenus"
-      v-if="curMenus.length"
-    />
+    <side-bar class="sidebar-container" :menus="curMenus" />
     <div class="main-container">
       <app-main />
       <app-footer />
@@ -49,12 +45,18 @@ export default {
       const res = await sysMenu();
       this.navs = this.menusToTree(res.data.data);
 
-      if (this.$route.name === "Home") {
+      const curRouterName = this.$route.meta.relate || this.$route.name;
+      if (curRouterName === "Home") {
+        const firstRoute =
+          this.navs[0] &&
+          this.navs[0].children[0] &&
+          this.navs[0].children[0].children[0] &&
+          this.navs[0].children[0].children[0].name;
         this.$router.replace({
-          name: this.navs[0].children[0].children[0].name,
+          name: firstRoute,
         });
       } else {
-        if (!this.validRoutes.includes(this.$route.name)) {
+        if (!this.validRoutes.includes(curRouterName)) {
           this.$router.replace({
             name: "404",
           });

+ 18 - 3
src/views/Layout/components/NavBar.vue

@@ -80,8 +80,15 @@ export default {
       isFullscreen: false,
     };
   },
+  watch: {
+    $route: {
+      immediate: true,
+      handler() {
+        this.actCurNav();
+      },
+    },
+  },
   mounted() {
-    this.actCurNav();
     this.registFullscreenChange();
     this.$store.commit("setIsFullScreen", this.checkDocIsFullscreen());
   },
@@ -104,8 +111,16 @@ export default {
       this.curNav = nav.name;
       this.$emit("on-nav-change", nav.name);
     },
-    toLogout() {
-      // console.log('Logout');
+    async toLogout() {
+      const result = await this.$confirm("确定要退出登录吗?", "退出确认", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        iconClass: "el-icon-question",
+        customClass: "el-message-box__warning",
+      }).catch(() => {});
+
+      if (!result) return;
+
       this.$router.push("/login");
     },
     checkDocIsFullscreen() {

+ 9 - 5
src/views/Layout/components/SideBar.vue

@@ -15,8 +15,9 @@
               'nav-sub-item',
               { 'nav-item-act': subnav.name === curRouterName },
             ]"
+            @click="toRouter(subnav)"
           >
-            <p @click="toRouter(subnav)">
+            <p>
               <span>{{ subnav.title }}</span>
               <span></span>
             </p>
@@ -42,13 +43,16 @@ export default {
     },
   },
   data() {
-    return {
-      curRouterName: this.$route.meta.relate || this.$route.name,
-    };
+    return {};
+  },
+  computed: {
+    curRouterName() {
+      return this.$route.meta.relate || this.$route.name;
+    },
   },
   methods: {
     toRouter(nav) {
-      this.curRouterName = nav.name;
+      // this.curRouterName = nav.name;
       this.$router.push({ name: nav.name });
     },
   },