zhangjie 2 gadi atpakaļ
vecāks
revīzija
d8a92ce690

+ 2 - 2
src/api/invigilation.js

@@ -168,8 +168,8 @@ export function examActivityRoomList(examId) {
   );
 }
 // 考试属性统计接口
-export function examPropCount(examId) {
-  const data = pickBy({ examId }, paramFilter);
+export function examPropCount(examId, examActivityId = null) {
+  const data = pickBy({ examId, examActivityId }, paramFilter);
   return httpApp.post(
     "/api/admin/exam/prop/count?" + object2QueryString(data),
     {}

+ 3 - 0
src/features/examwork/StudentManagement/StudentManagement.vue

@@ -49,6 +49,9 @@
       <el-table-column width="200" label="证件号">
         <span slot-scope="scope">{{ scope.row.identity }}</span>
       </el-table-column>
+      <el-table-column width="170" label="手机号">
+        <span slot-scope="scope">{{ scope.row.mobileNumber }}</span>
+      </el-table-column>
       <!-- <el-table-column width="100" label="机构">
         <span slot-scope="scope">{{ scope.row.orgName }}</span>
       </el-table-column> -->

+ 18 - 2
src/features/invigilation/InvigilationDetail/InvigilationDetail.vue

@@ -191,6 +191,7 @@
           class="part-filter-info-main"
           data-type="complete"
           :exam-id="filter.examId"
+          :exam-activity-id="filter.examActivityId"
         ></summary-line>
       </div>
     </div>
@@ -338,8 +339,8 @@ export default {
         (item) => item.id === this.filter.examId
       );
       this.curExamBatch = curExamBatch || {};
+      await this.getExamActivityRoomList();
       this.toSearch();
-      this.getExamActivityRoomList();
     },
     async getList() {
       const datas = {
@@ -394,9 +395,24 @@ export default {
     async getExamActivityRoomList() {
       if (!this.filter.examId) return;
       const res = await examActivityRoomList(this.filter.examId);
-      this.examActivities = res.data.data.examActivitys;
+      this.examActivities = this.getExamActivities(res.data.data.examActivitys);
       this.examRooms = res.data.data.examRooms;
       this.examCourses = res.data.data.examCourses;
+      this.filter.examActivityId =
+        this.examActivities[0] && this.examActivities[0].id;
+    },
+    getExamActivities(examActivitys) {
+      if (!examActivitys.length) return [];
+      const now = Date.now();
+      examActivitys.forEach((item) => {
+        item.endRemainTime = item.finishTime - now;
+      });
+      examActivitys.sort((a, b) => {
+        if (a.endRemainTime < 0) return 1;
+        if (b.endRemainTime < 0) return -1;
+        return a.endRemainTime - b.endRemainTime;
+      });
+      return examActivitys;
     },
     examChange() {
       const curExamBatch = this.examBatchs.find(

+ 56 - 4
src/features/invigilation/ProgressDetail/ProgressDetail.vue

@@ -20,6 +20,20 @@
               ></el-option>
             </el-select>
           </el-form-item>
+          <el-form-item>
+            <el-select
+              v-model="form.examActivityId"
+              placeholder="请选择场次"
+              clearable
+            >
+              <el-option
+                v-for="item in examActivities"
+                :key="item.id"
+                :value="item.id"
+                :label="item.code"
+              ></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item>
             <el-select
               v-model="form.roomCode"
@@ -58,6 +72,20 @@
               ></el-option>
             </el-select>
           </el-form-item>
+          <el-form-item>
+            <el-select
+              v-model="form.breachStatus"
+              placeholder="违纪状态"
+              clearable
+            >
+              <el-option
+                v-for="(val, key) in BOOLEAN_TYPE"
+                :key="key"
+                :value="key * 1"
+                :label="key === '0' ? '违纪' : '正常'"
+              ></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item>
             <el-input
               v-model.trim="form.name"
@@ -79,10 +107,11 @@
       </div>
       <div class="part-filter-info">
         <summary-line
+          v-if="form.examId"
           class="part-filter-info-main"
           data-type="progress"
           :exam-id="form.examId"
-          v-if="form.examId"
+          :exam-activity-id="form.examActivityId"
         ></summary-line>
         <div class="part-filter-info-sub">
           <el-button
@@ -110,7 +139,6 @@
       </el-table-column>
       <el-table-column prop="identity" label="证件号"></el-table-column>
       <el-table-column prop="name" label="姓名"></el-table-column>
-      <el-table-column prop="mobileNumber" label="联系电话"></el-table-column>
       <el-table-column prop="courseName" label="科目(代码)">
         <span slot-scope="scope"
           >{{ scope.row.courseName }}({{ scope.row.courseCode }})</span
@@ -121,6 +149,13 @@
         label="剩余考试次数"
       ></el-table-column>
       <el-table-column prop="status" label="完成状态"></el-table-column>
+      <el-table-column prop="breachStatus" label="违纪状态" width="100">
+        <template slot-scope="scope">
+          <span :class="{ 'color-danger': !scope.row.breachStatus }">
+            {{ !scope.row.breachStatus ? "违纪" : "正常" }}
+          </span>
+        </template>
+      </el-table-column>
       <el-table-column :context="_self" label="操作" width="120" fixed="right">
         <div slot-scope="scope">
           <el-button
@@ -178,11 +213,13 @@ export default {
     return {
       form: {
         examId: "",
+        examActivityId: "",
         roomCode: "",
         courseCode: "",
         name: "",
         identity: "",
         status: null,
+        breachStatus: null,
       },
       currentPage: 1,
       total: 0,
@@ -216,7 +253,7 @@ export default {
       });
       this.form.examId = this.selectedExamId;
       // this.form.examId = this.examBatchs[0] && this.examBatchs[0].id;
-      this.getExamActivityRoomList();
+      await this.getExamActivityRoomList();
       this.toPage(1);
       window.sessionStorage.removeItem("studentManageCache");
     },
@@ -246,9 +283,24 @@ export default {
     async getExamActivityRoomList() {
       if (!this.form.examId) return;
       const res = await examActivityRoomList(this.form.examId);
-      this.examActivities = res.data.data.examActivitys;
+      this.examActivities = this.getExamActivities(res.data.data.examActivitys);
       this.examRooms = res.data.data.examRooms;
       this.examCourses = res.data.data.examCourses;
+      this.form.examActivityId =
+        this.examActivities[0] && this.examActivities[0].id;
+    },
+    getExamActivities(examActivitys) {
+      if (!examActivitys.length) return [];
+      const now = Date.now();
+      examActivitys.forEach((item) => {
+        item.endRemainTime = item.finishTime - now;
+      });
+      examActivitys.sort((a, b) => {
+        if (a.endRemainTime < 0) return 1;
+        if (b.endRemainTime < 0) return -1;
+        return a.endRemainTime - b.endRemainTime;
+      });
+      return examActivitys;
     },
     examChange() {
       this.form.examActivityId = null;

+ 35 - 2
src/features/invigilation/RealtimeMonitoring/RealtimeMonitoring.vue

@@ -50,10 +50,23 @@
               ></el-input>
             </div>
           </el-form-item>
+          <el-form-item>
+            <el-select
+              v-model="filter.examActivityId"
+              placeholder="场次"
+              clearable
+            >
+              <el-option
+                v-for="item in examActivities"
+                :key="item.id"
+                :value="item.id"
+                :label="item.code"
+              ></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item>
             <el-select
               v-model="filter.roomCode"
-              class="size-select"
               placeholder="考场"
               @change="examRoomChange"
             >
@@ -80,6 +93,7 @@
           class="part-filter-info-main"
           data-type="trouble"
           :exam-id="filter.examId"
+          :exam-activity-id="filter.examActivityId"
           ref="SummaryLine"
         ></summary-line>
         <div class="part-filter-info-sub">
@@ -362,6 +376,7 @@ export default {
       initExamid: this.$route.params.examId,
       filter: {
         examId: "",
+        examActivityId: "",
         roomCode: "",
         paperDownload: null,
         status: null,
@@ -400,6 +415,7 @@ export default {
       cachePaperType: "",
       dataList: [],
       examRooms: [],
+      examActivities: [],
       videoSourceStatusParams: {
         CLIENT_CAMERA: "cameraMonitorStatusSource",
         CLIENT_SCREEN: "screenMonitorStatusSource",
@@ -497,10 +513,27 @@ export default {
       if (!this.curExamBatch.id) return;
       const res = await examActivityRoomList(this.curExamBatch.id);
       this.examRooms = res.data.data.examRooms || [];
-
       this.filter.roomCode = this.examRooms[0] && this.examRooms[0].roomCode;
+
+      this.examActivities = this.getExamActivities(res.data.data.examActivitys);
+      this.filter.examActivityId =
+        this.examActivities[0] && this.examActivities[0].id;
+
       this.examRoomChange();
     },
+    getExamActivities(examActivitys) {
+      if (!examActivitys.length) return [];
+      const now = Date.now();
+      examActivitys.forEach((item) => {
+        item.endRemainTime = item.finishTime - now;
+      });
+      examActivitys.sort((a, b) => {
+        if (a.endRemainTime < 0) return 1;
+        if (b.endRemainTime < 0) return -1;
+        return a.endRemainTime - b.endRemainTime;
+      });
+      return examActivitys;
+    },
     examRoomChange() {
       this.toSearch();
 

+ 6 - 1
src/features/invigilation/RealtimeMonitoring/RealtimeMonitoringFull.vue

@@ -13,7 +13,11 @@
         </div>
         <div class="monitor-view-content-right">
           <div class="card-box monitor-view-content-right-header">
-            <SummaryLineFull data-type="trouble" :examId="filter.examId" />
+            <SummaryLineFull
+              data-type="trouble"
+              :exam-id="filter.examId"
+              :exam-activity-id="filter.examActivityId"
+            />
           </div>
           <div class="monitor-view-content-video-table">
             <div
@@ -117,6 +121,7 @@ export default {
   data() {
     return {
       filter: {
+        examActivityId: "",
         examId: "",
         roomCode: "",
         monitorVideoSource: "",

+ 34 - 0
src/features/invigilation/RealtimeMonitoring/components/RealtimeMonitoringFullHeader.vue

@@ -16,6 +16,20 @@
             ></el-input>
           </div>
         </el-form-item>
+        <el-form-item class="exam-room-select">
+          <el-select
+            v-model="filter.examActivityId"
+            placeholder="场次"
+            clearable
+          >
+            <el-option
+              v-for="item in examActivities"
+              :key="item.id"
+              :value="item.id"
+              :label="item.code"
+            ></el-option>
+          </el-select>
+        </el-form-item>
         <el-form-item class="exam-room-select">
           <el-select v-model="filter.roomCode" placeholder="考场">
             <el-option
@@ -68,11 +82,14 @@ export default {
     return {
       /** 筛选条件 */
       filter: {
+        examActivityId: "",
         examId: "",
         roomCode: "",
         monitorVideoSource: "",
         monitorStatus: "",
       },
+      /** 场次列表 */
+      examActivities: [],
       /** 考场列表 */
       examRooms: [],
       /** 视频源 */
@@ -119,6 +136,23 @@ export default {
       const res = await examActivityRoomList(this.curExamBatch.id);
       this.examRooms = res.data.data.examRooms ?? [];
       this.filter.roomCode = this.examRooms[0]?.roomCode;
+
+      this.examActivities = this.getExamActivities(res.data.data.examActivitys);
+      this.filter.examActivityId =
+        this.examActivities[0] && this.examActivities[0].id;
+    },
+    getExamActivities(examActivitys) {
+      if (!examActivitys.length) return [];
+      const now = Date.now();
+      examActivitys.forEach((item) => {
+        item.endRemainTime = item.finishTime - now;
+      });
+      examActivitys.sort((a, b) => {
+        if (a.endRemainTime < 0) return 1;
+        if (b.endRemainTime < 0) return -1;
+        return a.endRemainTime - b.endRemainTime;
+      });
+      return examActivitys;
     },
   },
 };

+ 32 - 2
src/features/invigilation/WarningManage/WarningManage.vue

@@ -34,6 +34,20 @@
               </el-option>
             </el-select>
           </el-form-item>
+          <el-form-item>
+            <el-select
+              v-model="filter.examActivityId"
+              placeholder="请选择场次"
+              clearable
+            >
+              <el-option
+                v-for="item in examActivities"
+                :key="item.id"
+                :value="item.id"
+                :label="item.code"
+              ></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item>
             <el-select
               v-model="filter.roomCode"
@@ -232,6 +246,7 @@ export default {
     return {
       filter: {
         examId: null,
+        examActivityId: null,
         roomCode: null,
         courseCode: null,
         approveStatus: null,
@@ -291,8 +306,8 @@ export default {
       });
       this.filter.examId = this.selectedExamId;
       // this.filter.examId = this.examBatchs[0] && this.examBatchs[0].id;
+      await this.getExamActivityRoomList();
       this.toSearch();
-      this.getExamActivityRoomList();
     },
     async getList() {
       const datas = {
@@ -332,9 +347,24 @@ export default {
     async getExamActivityRoomList() {
       if (!this.filter.examId) return;
       const res = await examActivityRoomList(this.filter.examId);
-      this.examActivities = res.data.data.examActivitys;
+      this.examActivities = this.getExamActivities(res.data.data.examActivitys);
       this.examRooms = res.data.data.examRooms;
       this.examCourses = res.data.data.examCourses;
+      this.filter.examActivityId =
+        this.examActivities[0] && this.examActivities[0].id;
+    },
+    getExamActivities(examActivitys) {
+      if (!examActivitys.length) return [];
+      const now = Date.now();
+      examActivitys.forEach((item) => {
+        item.endRemainTime = item.finishTime - now;
+      });
+      examActivitys.sort((a, b) => {
+        if (a.endRemainTime < 0) return 1;
+        if (b.endRemainTime < 0) return -1;
+        return a.endRemainTime - b.endRemainTime;
+      });
+      return examActivitys;
     },
     examChange() {
       this.filter.examActivityId = null;

+ 12 - 1
src/features/invigilation/common/mixins/summaryLineMixin.js

@@ -63,6 +63,9 @@ export default {
     examId: {
       type: String,
     },
+    examActivityId: {
+      type: String,
+    },
     dataType: {
       type: String,
       required: true,
@@ -81,6 +84,12 @@ export default {
         this.initData();
       },
     },
+    examActivityId: {
+      immediate: true,
+      handler() {
+        this.initData();
+      },
+    },
   },
   data() {
     return {
@@ -91,7 +100,9 @@ export default {
   methods: {
     async initData() {
       if (!this.examId) return;
-      const res = await examPropCount(this.examId).catch(() => {});
+      const res = await examPropCount(this.examId, this.examActivityId).catch(
+        () => {}
+      );
       this.examPropData = (res && res.data && res.data.data) || {};
       if (this.examPropData["completionRate"])
         this.examPropData["completionRate"] = Math.round(