zhangjie 4 年之前
父節點
當前提交
5d65698b5e

+ 9 - 0
src/api/invigilation.js

@@ -145,6 +145,15 @@ export function communicationList(datas) {
   );
   );
 }
 }
 
 
+export function communicationCalling({ recordId, source }) {
+  return httpApp.post(
+    "/api/admin/monitor/call/calling",
+    { recordId, source },
+    {
+      noErrorMessage: true,
+    }
+  );
+}
 export function communicationOver({ recordId, source }) {
 export function communicationOver({ recordId, source }) {
   return httpApp.post(
   return httpApp.post(
     "/api/admin/monitor/call/cancel",
     "/api/admin/monitor/call/cancel",

+ 2 - 2
src/constant/constants.js

@@ -13,8 +13,8 @@ export const EXAM_STUDENT_IMPORT_TEMPLATE_DOWNLOAD_URL =
 
 
 // 交卷方式
 // 交卷方式
 export const STUDENT_FINISH_EXAM_TYPE = {
 export const STUDENT_FINISH_EXAM_TYPE = {
-  MANUAL: "手动卷",
-  AUTO: "正常交卷",
+  MANUAL: "手动卷",
+  AUTO: "自动交卷",
   BREACH: "违纪交卷",
   BREACH: "违纪交卷",
   INTERRUPT: "监考强制交卷",
   INTERRUPT: "监考强制交卷",
 };
 };

+ 26 - 9
src/features/invigilation/OnlinePatrol/PatrolWarningDetail.vue

@@ -81,13 +81,14 @@
           <ul>
           <ul>
             <li v-for="(log, index) in exceptionSummary" :key="index">
             <li v-for="(log, index) in exceptionSummary" :key="index">
               <i>{{ index + 1 }}</i>
               <i>{{ index + 1 }}</i>
-              <h4>{{ log.info }}</h4>
-              <p>
+              <h4>{{ log.title }}</h4>
+              <p v-if="log.desc">{{ log.desc }}</p>
+              <!-- <p>
                 时间段:
                 时间段:
                 <span v-if="log.startTime">{{ log.startTime }} ~ </span>
                 <span v-if="log.startTime">{{ log.startTime }} ~ </span>
                 <span>{{ log.endTime }}</span>
                 <span>{{ log.endTime }}</span>
               </p>
               </p>
-              <p v-if="log.durationTime">持续时长约:{{ log.durationTime }}</p>
+              <p v-if="log.durationTime">持续时长约:{{ log.durationTime }}</p> -->
             </li>
             </li>
           </ul>
           </ul>
         </div>
         </div>
@@ -133,7 +134,8 @@
           :key="log.id"
           :key="log.id"
         >
         >
           <div class="warning-history-info">
           <div class="warning-history-info">
-            <h3>{{ log.info }}</h3>
+            <h3>{{ log.title }}</h3>
+            <p v-if="log.desc">{{ log.desc }}</p>
             <p>
             <p>
               时间段:
               时间段:
               <span v-if="log.startTime">{{ log.startTime }} ~ </span>
               <span v-if="log.startTime">{{ log.startTime }} ~ </span>
@@ -174,7 +176,7 @@
 <script>
 <script>
 import FlvMedia from "../common/FlvMedia";
 import FlvMedia from "../common/FlvMedia";
 import { invigilateDetail, warningStudentDetail } from "@/api/invigilation";
 import { invigilateDetail, warningStudentDetail } from "@/api/invigilation";
-import { formatDate, timeNumberToText } from "@/utils/utils";
+import { formatDate, timeNumberToText, objTypeOf } from "@/utils/utils";
 import { mapState } from "vuex";
 import { mapState } from "vuex";
 
 
 export default {
 export default {
@@ -283,6 +285,13 @@ export default {
         let info = { ...item };
         let info = { ...item };
         info.endTime = formatDate("HH:mm:ss", new Date(info.createTime));
         info.endTime = formatDate("HH:mm:ss", new Date(info.createTime));
         info.viewType = statusTypeMap[info.type] || "common";
         info.viewType = statusTypeMap[info.type] || "common";
+        const content = info.info.split(/【|】/);
+        if (content.length === 3) {
+          info.title = content[1];
+          info.desc = content[2];
+        } else {
+          info.title = content[0];
+        }
         if (info.remark && info.remark.includes('{"')) {
         if (info.remark && info.remark.includes('{"')) {
           info.remark = JSON.parse(info.remark);
           info.remark = JSON.parse(info.remark);
           if (info.remark["MIN_CREATE_TIME"]) {
           if (info.remark["MIN_CREATE_TIME"]) {
@@ -294,10 +303,18 @@ export default {
               info.createTime - info.remark["MIN_CREATE_TIME"]
               info.createTime - info.remark["MIN_CREATE_TIME"]
             );
             );
           }
           }
-          let facePhoto = info.remark["FACE_VERIFY_PHOTO"]
-            ? [info.remark["FACE_VERIFY_PHOTO"]]
-            : "";
-          info.photos = info.remark["PHOTOS"] || facePhoto;
+
+          let photos = [];
+          Object.keys(info.remark).map((key) => {
+            if (key.includes("PHOTO")) {
+              const kPhotos =
+                objTypeOf(info.remark[key]) === "array"
+                  ? info.remark[key]
+                  : [info.remark[key]];
+              photos = [...photos, ...kPhotos];
+            }
+          });
+          info.photos = photos;
         } else if (info.updateTime) {
         } else if (info.updateTime) {
           info.startTime = formatDate("HH:mm:ss", new Date(info.createTime));
           info.startTime = formatDate("HH:mm:ss", new Date(info.createTime));
           info.endTime = formatDate("HH:mm:ss", new Date(info.updateTime));
           info.endTime = formatDate("HH:mm:ss", new Date(info.updateTime));

+ 49 - 10
src/features/invigilation/RealtimeMonitoring/VideoCommunication.vue

@@ -28,13 +28,25 @@
               </div>
               </div>
             </div>
             </div>
             <h4 class="student-name">{{ item.examStudentName }}</h4>
             <h4 class="student-name">{{ item.examStudentName }}</h4>
-            <el-button round type="success" @click="answer(item, 0)"
-              >语音通话</el-button
-            >
-            <br />
-            <el-button round type="primary" @click="answer(item, 1)"
-              >视频通话</el-button
-            >
+            <div v-if="callStatus === 'START'">
+              <el-button round type="success" @click="answer(item, 0)"
+                >语音通话</el-button
+              >
+              <br />
+              <el-button round type="primary" @click="answer(item, 1)"
+                >视频通话</el-button
+              >
+            </div>
+            <div class="student-call-info" v-else>
+              <p>
+                通话时间段:
+                <span>{{ item.startTime }} ~ </span>
+                <span>{{ item.endTime }}</span>
+              </p>
+              <p v-if="item.durationTime">
+                持续时长约:{{ item.durationTime }}
+              </p>
+            </div>
           </div>
           </div>
         </el-col>
         </el-col>
       </el-row>
       </el-row>
@@ -84,10 +96,12 @@
 import { createClient, createStream } from "@/plugins/trtc";
 import { createClient, createStream } from "@/plugins/trtc";
 import {
 import {
   communicationList,
   communicationList,
+  communicationCalling,
   communicationOver,
   communicationOver,
   getUserMonitorKey,
   getUserMonitorKey,
 } from "@/api/invigilation";
 } from "@/api/invigilation";
 import SecondTimer from "../common/SecondTimer";
 import SecondTimer from "../common/SecondTimer";
+import { formatDate, timeNumberToText } from "@/utils/utils";
 
 
 export default {
 export default {
   name: "video-communication",
   name: "video-communication",
@@ -98,6 +112,7 @@ export default {
       callStatus: "START",
       callStatus: "START",
       dialogVisible: false,
       dialogVisible: false,
       students: [],
       students: [],
+      curStudent: {},
       current: 1,
       current: 1,
       total: 0,
       total: 0,
       size: 100,
       size: 100,
@@ -123,7 +138,18 @@ export default {
         pageNumber: this.current,
         pageNumber: this.current,
         pageSize: this.size,
         pageSize: this.size,
       }).catch(() => {});
       }).catch(() => {});
-      this.students = res.data.data.records;
+      this.students = res.data.data.records.map((item) => {
+        item.durationTime = timeNumberToText(item.endTime - item.startTime);
+        item.startTime = formatDate(
+          "YYYY-MM-DD HH:mm:ss",
+          new Date(item.startTime)
+        );
+        item.endTime = formatDate(
+          "YYYY-MM-DD HH:mm:ss",
+          new Date(item.endTime)
+        );
+        return item;
+      });
       this.total = res.data.data.total;
       this.total = res.data.data.total;
       // 当前页没有数据,同时当前页不是第一页,则自动跳到前一页。
       // 当前页没有数据,同时当前页不是第一页,则自动跳到前一页。
       if (!this.students.length && this.current > 1) {
       if (!this.students.length && this.current > 1) {
@@ -150,9 +176,10 @@ export default {
       });
       });
     },
     },
     async answer(student, isVideo) {
     async answer(student, isVideo) {
+      this.curStudent = student;
       await this.initClient(student.examRecordId);
       await this.initClient(student.examRecordId);
-      // 结束学生的通话申请
-      await communicationOver({
+      // 更改学生的通话申请状态
+      await communicationCalling({
         recordId: student.examRecordId,
         recordId: student.examRecordId,
         source: student.source,
         source: student.source,
       });
       });
@@ -227,6 +254,12 @@ export default {
     },
     },
     async hangup() {
     async hangup() {
       this.$refs.SecondTimer.end();
       this.$refs.SecondTimer.end();
+      // 结束学生的通话
+      await communicationOver({
+        recordId: this.curStudent.examRecordId,
+        source: this.curStudent.source,
+      });
+      this.curStudent = {};
 
 
       // 取消发布本地视频
       // 取消发布本地视频
       let unpublishStreamResult = true;
       let unpublishStreamResult = true;
@@ -291,5 +324,11 @@ export default {
     line-height: 25px;
     line-height: 25px;
     color: #202b4b;
     color: #202b4b;
   }
   }
+  .student-call-info {
+    p {
+      margin: 0;
+      text-align: left;
+    }
+  }
 }
 }
 </style>
 </style>

+ 26 - 9
src/features/invigilation/RealtimeMonitoring/WarningDetail.vue

@@ -95,13 +95,14 @@
           <ul>
           <ul>
             <li v-for="(log, index) in exceptionSummary" :key="index">
             <li v-for="(log, index) in exceptionSummary" :key="index">
               <i>{{ index + 1 }}</i>
               <i>{{ index + 1 }}</i>
-              <h4>{{ log.info }}</h4>
-              <p>
+              <h4>{{ log.title }}</h4>
+              <p v-if="log.desc">{{ log.desc }}</p>
+              <!-- <p>
                 时间段:
                 时间段:
                 <span v-if="log.startTime">{{ log.startTime }} ~ </span>
                 <span v-if="log.startTime">{{ log.startTime }} ~ </span>
                 <span>{{ log.endTime }}</span>
                 <span>{{ log.endTime }}</span>
               </p>
               </p>
-              <p v-if="log.durationTime">持续时长约:{{ log.durationTime }}</p>
+              <p v-if="log.durationTime">持续时长约:{{ log.durationTime }}</p> -->
             </li>
             </li>
           </ul>
           </ul>
         </div>
         </div>
@@ -183,7 +184,8 @@
           :key="log.id"
           :key="log.id"
         >
         >
           <div class="warning-history-info">
           <div class="warning-history-info">
-            <h3>{{ log.info }}</h3>
+            <h3>{{ log.title }}</h3>
+            <p v-if="log.desc">{{ log.desc }}</p>
             <p>
             <p>
               时间段:
               时间段:
               <span v-if="log.startTime">{{ log.startTime }} ~ </span>
               <span v-if="log.startTime">{{ log.startTime }} ~ </span>
@@ -291,7 +293,7 @@ import StudentBreachDialog from "./StudentBreachDialog";
 import WarningTextMessageDialog from "./WarningTextMessageDialog";
 import WarningTextMessageDialog from "./WarningTextMessageDialog";
 import AudioRecordDialog from "./audioRecord/AudioRecordDialog";
 import AudioRecordDialog from "./audioRecord/AudioRecordDialog";
 import SecondTimer from "../common/SecondTimer";
 import SecondTimer from "../common/SecondTimer";
-import { formatDate, timeNumberToText } from "@/utils/utils";
+import { formatDate, timeNumberToText, objTypeOf } from "@/utils/utils";
 import { mapState } from "vuex";
 import { mapState } from "vuex";
 
 
 export default {
 export default {
@@ -448,6 +450,13 @@ export default {
         let info = { ...item };
         let info = { ...item };
         info.endTime = formatDate("HH:mm:ss", new Date(info.createTime));
         info.endTime = formatDate("HH:mm:ss", new Date(info.createTime));
         info.viewType = statusTypeMap[info.type] || "common";
         info.viewType = statusTypeMap[info.type] || "common";
+        const content = info.info.split(/【|】/);
+        if (content.length === 3) {
+          info.title = content[1];
+          info.desc = content[2];
+        } else {
+          info.title = content[0];
+        }
         if (info.remark && info.remark.includes('{"')) {
         if (info.remark && info.remark.includes('{"')) {
           info.remark = JSON.parse(info.remark);
           info.remark = JSON.parse(info.remark);
           if (info.remark["MIN_CREATE_TIME"]) {
           if (info.remark["MIN_CREATE_TIME"]) {
@@ -459,10 +468,18 @@ export default {
               info.createTime - info.remark["MIN_CREATE_TIME"]
               info.createTime - info.remark["MIN_CREATE_TIME"]
             );
             );
           }
           }
-          let facePhoto = info.remark["FACE_VERIFY_PHOTO"]
-            ? [info.remark["FACE_VERIFY_PHOTO"]]
-            : "";
-          info.photos = info.remark["PHOTOS"] || facePhoto;
+
+          let photos = [];
+          Object.keys(info.remark).map((key) => {
+            if (key.includes("PHOTO")) {
+              const kPhotos =
+                objTypeOf(info.remark[key]) === "array"
+                  ? info.remark[key]
+                  : [info.remark[key]];
+              photos = [...photos, ...kPhotos];
+            }
+          });
+          info.photos = photos;
         } else if (info.updateTime) {
         } else if (info.updateTime) {
           info.startTime = formatDate("HH:mm:ss", new Date(info.createTime));
           info.startTime = formatDate("HH:mm:ss", new Date(info.createTime));
           info.endTime = formatDate("HH:mm:ss", new Date(info.updateTime));
           info.endTime = formatDate("HH:mm:ss", new Date(info.updateTime));