فهرست منبع

批次编辑布局,考试记录以及图片放大

zhangjie 3 سال پیش
والد
کامیت
30d30d5e67

+ 37 - 0
src/api/examwork-student.js

@@ -61,3 +61,40 @@ export function searchStudentExamRecord({
     "/api/admin/student/exam_record/query?" + object2QueryString(data)
   );
 }
+
+// student-exam-detail
+export function searchStudentExamDetailList({
+  examId = "",
+  activityId = "",
+  roomCode = "",
+  courseCode = "",
+  name = "",
+  identity = "",
+  finishType = "",
+  pageNumber = 1,
+  pageSize = 10,
+}) {
+  const data = pickBy(
+    {
+      activityId,
+      examId,
+      roomCode,
+      courseCode,
+      name,
+      identity,
+      finishType,
+      pageNumber,
+      pageSize,
+    },
+    (v) => v !== ""
+  );
+  return httpApp.post(
+    "/api/admin/examStudent/exam_record_detail/query?" +
+      object2QueryString(data)
+  );
+}
+export function studentExamDetailInfo(examRecordId) {
+  return httpApp.post(
+    "/api/admin/examStudent/exam_record/paper_view?examRecordId=" + examRecordId
+  );
+}

+ 1 - 1
src/components/StateSelect.vue

@@ -2,7 +2,7 @@
   <el-select
     v-model="selected"
     class="size-select"
-    placeholder="考试状态"
+    placeholder="状态"
     @change="select"
     :style="styles"
     clearable

+ 1 - 1
src/features/examwork/ExamManagement/ExamEdit.vue

@@ -1,5 +1,5 @@
 <template>
-  <div v-loading="!orgSetting">
+  <div class="exam-edit" v-loading="!orgSetting">
     <el-tabs v-model="activeName" type="card">
       <el-tab-pane label="考试规则设置" name="first">
         <el-form

+ 53 - 0
src/features/examwork/StudentExamDetail/PreviewPaperDialog.vue

@@ -0,0 +1,53 @@
+<template>
+  <el-dialog
+    class="preview-paper-dialog"
+    :visible.sync="visible"
+    title="查看原卷"
+    width="1200px"
+    top="0"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { studentExamDetailInfo } from "@/api/examwork-student";
+
+export default {
+  name: "preview-paper-dialog",
+  props: {
+    examRecordId: {
+      type: String,
+    },
+  },
+  data() {
+    return {
+      visible: false,
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.getRecordDetail();
+    },
+    openDialog() {
+      this.visible = true;
+    },
+    closeDialog() {
+      this.visible = false;
+    },
+    async getRecordDetail() {
+      const res = await studentExamDetailInfo(this.examRecordId);
+      const paperStructJson = JSON.parse(res.data.data.paperStructJson);
+      const answerJson = JSON.parse(res.data.data.answerJson);
+      const examStudentAnswerJson = JSON.parse(
+        res.data.data.examStudentAnswerJson
+      );
+      console.log(paperStructJson, answerJson, examStudentAnswerJson);
+    },
+  },
+};
+</script>

+ 197 - 0
src/features/examwork/StudentExamDetail/StudentExamDetail.vue

@@ -0,0 +1,197 @@
+<template>
+  <div class="student-exam-detail">
+    <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"
+              exam-required
+            />
+          </el-form-item>
+          <el-form-item label="考场名称">
+            <ExamRoomSelect :examId="form.examId" v-model="form.roomCode" />
+          </el-form-item>
+          <el-form-item label="科目">
+            <CourseSelect
+              :examId="form.examId"
+              v-model="form.courseCode"
+              exam-required
+            />
+          </el-form-item>
+          <el-form-item label="交卷方式">
+            <el-select
+              v-model="form.finishType"
+              placeholder="交卷方式"
+              clearable
+            >
+              <el-option
+                v-for="(val, key) in STUDENT_FINISH_EXAM_TYPE"
+                :key="key"
+                :value="key"
+                :label="val"
+              ></el-option>
+            </el-select>
+          </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>
+            <el-button type="primary" @click="handleCurrentChange(0)"
+              >查询</el-button
+            >
+          </el-form-item>
+        </el-form>
+
+        <div class="part-filter-form-action"></div>
+      </div>
+    </div>
+
+    <el-table ref="table" :data="tableData">
+      <el-table-column width="170" label="考试ID">
+        <span slot-scope="scope">{{ scope.row.examRecordId }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="批次名称">
+        <span slot-scope="scope">{{ scope.row.name }}</span>
+      </el-table-column>
+      <el-table-column width="100" label="场次">
+        <span slot-scope="scope">{{ scope.row.code }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="姓名">
+        <span slot-scope="scope">{{ scope.row.examStudentName }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="证件号">
+        <span slot-scope="scope">{{ scope.row.identity }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="科目代码">
+        <span slot-scope="scope">{{ scope.row.courseCode }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="科目名称">
+        <span slot-scope="scope">{{ scope.row.courseName }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="考场代码">
+        <span slot-scope="scope">{{ scope.row.roomCode }}</span>
+      </el-table-column>
+      <el-table-column width="150" label="考场名称">
+        <span slot-scope="scope">{{ scope.row.roomName }}</span>
+      </el-table-column>
+      <el-table-column width="170" label="进入考试时间">
+        <span slot-scope="scope">{{
+          scope.row.firstStartTime | datetimeFilter
+        }}</span>
+      </el-table-column>
+      <el-table-column width="170" label="结束考试时间">
+        <span slot-scope="scope">{{
+          scope.row.finishTime | datetimeFilter
+        }}</span>
+      </el-table-column>
+      <el-table-column width="120" label="交卷方式">
+        <span slot-scope="scope">{{ scope.row.finishTypeStr }}</span>
+      </el-table-column>
+      <el-table-column :context="_self" label="操作" width="110" fixed="right">
+        <div slot-scope="scope">
+          <el-button
+            size="mini"
+            type="primary"
+            plain
+            @click="toViewPaper(scope.row)"
+          >
+            查看原卷
+          </el-button>
+        </div>
+      </el-table-column>
+    </el-table>
+    <div class="part-page">
+      <el-pagination
+        background
+        @current-change="handleCurrentChange"
+        :current-page="currentPage"
+        :page-size="pageSize"
+        :page-sizes="[10, 20, 50, 100, 200, 300]"
+        @size-change="handleSizeChange"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+      />
+    </div>
+
+    <!-- PreviewPaperDialog -->
+    <PreviewPaperDialog
+      ref="PreviewPaperDialog"
+      :examRecordId="curExamRecordId"
+    />
+  </div>
+</template>
+
+<script>
+import { STUDENT_FINISH_EXAM_TYPE } from "@/constant/constants";
+import { searchStudentExamDetailList } from "@/api/examwork-student";
+import PreviewPaperDialog from "./PreviewPaperDialog.vue";
+
+export default {
+  name: "student-exam-detail",
+  components: { PreviewPaperDialog },
+  data() {
+    return {
+      form: {
+        examId: "",
+        activityId: "",
+        roomCode: "",
+        courseCode: "",
+        name: "",
+        identity: "",
+        finishType: "",
+      },
+      rules: {
+        examId: [{ required: true, message: "批次必选" }],
+      },
+      STUDENT_FINISH_EXAM_TYPE,
+      tableData: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 10,
+      curExamRecordId: null,
+    };
+  },
+  methods: {
+    async searchForm() {
+      const valid = await this.$refs.form.validate();
+      if (!valid) return;
+
+      const res = await searchStudentExamDetailList({
+        ...this.form,
+        pageNumber: this.currentPage,
+        pageSize: this.pageSize,
+      });
+      this.tableData = res.data.data.records;
+      this.total = res.data.data.total;
+      if (this.total > 0 && this.tableData.length === 0) {
+        this.handleCurrentChange(this.currentPage - 1);
+      }
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.searchForm();
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.currentPage = 1;
+      this.searchForm();
+    },
+    toViewPaper(row) {
+      console.log(row);
+      this.curExamRecordId = row.examRecordId;
+      this.$refs.PreviewPaperDialog.openDialog();
+    },
+  },
+};
+</script>

+ 8 - 34
src/features/examwork/StudentManagement/StudentManagementDialog.vue

@@ -3,31 +3,17 @@
     <el-dialog
       ref="dialog"
       title="考试记录"
-      width="760px"
+      width="800px"
+      top="20px"
       :visible.sync="visible"
+      @open="dialogOpen"
       @close="closeDialog"
     >
-      <el-form
-        :model="form"
-        ref="form"
-        :rules="rules"
-        label-position="right"
-        label-width="120px"
-        inline
-      >
-        <el-form-item label="批次名称" prop="examId">
-          <ExamSelect v-model="form.examId" />
-        </el-form-item>
-        <el-button type="primary" @click="handleCurrentChange(0)"
-          >查询</el-button
-        >
-      </el-form>
-
       <el-table :data="tableData" stripe style="width: 100%;">
         <el-table-column width="100" label="姓名">
           <span slot-scope="scope">{{ scope.row.name }}</span>
         </el-table-column>
-        <el-table-column width="180" label="证件号">
+        <el-table-column width="120" label="证件号">
           <span slot-scope="scope">{{ scope.row.identity }}</span>
         </el-table-column>
         <el-table-column label="批次名称">
@@ -55,7 +41,7 @@
           </template>
         </el-table-column>
       </el-table>
-      <div class="page float-right">
+      <div class="part-page">
         <el-pagination
           background
           @current-change="handleCurrentChange"
@@ -84,18 +70,11 @@ export default {
       this.tableData = [];
       this.pageSize = 10;
       this.total = 0;
-      this.form.examId = "";
     },
   },
   data() {
     return {
       visible: false,
-      form: {
-        examId: "",
-      },
-      rules: {
-        examId: [{ required: true, message: "批次必选" }],
-      },
       tableData: [],
       currentPage: 1,
       pageSize: 10,
@@ -103,6 +82,9 @@ export default {
     };
   },
   methods: {
+    dialogOpen() {
+      this.handleCurrentChange(0);
+    },
     openDialog() {
       this.visible = true;
     },
@@ -119,15 +101,7 @@ export default {
       this.searchForm();
     },
     async searchForm() {
-      try {
-        const valid = await this.$refs.form.validate();
-        if (!valid) return;
-      } catch (error) {
-        console.log("校验失败", error);
-        return;
-      }
       const res = await searchStudentExamRecord({
-        examId: this.form.examId,
         studentId: this.student.id,
         pageNumber: this.currentPage,
         pageSize: this.pageSize,

+ 6 - 1
src/features/invigilation/OnlinePatrol/PatrolWarningDetail.vue

@@ -163,7 +163,12 @@
           <div class="warning-history-media">
             <ul class="media-list" v-if="log.photos">
               <li v-for="(photo, pindex) in log.photos" :key="pindex">
-                <img :src="photo" />
+                <!-- <img :src="photo" /> -->
+                <el-image
+                  :src="photo"
+                  fit="contain"
+                  :preview-src-list="[photo]"
+                ></el-image>
               </li>
             </ul>
           </div>

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

@@ -227,7 +227,12 @@
           <div class="warning-history-media">
             <ul class="media-list" v-if="log.photos">
               <li v-for="(photo, pindex) in log.photos" :key="pindex">
-                <img :src="photo" />
+                <!-- <img :src="photo" /> -->
+                <el-image
+                  :src="photo"
+                  fit="contain"
+                  :preview-src-list="[photo]"
+                ></el-image>
               </li>
             </ul>
           </div>

+ 8 - 0
src/router/index.js

@@ -160,6 +160,14 @@ const routes = [
             /* webpackChunkName: "exam" */ "../features/examwork/InvigilateManagement/InvigilateManagement.vue"
           ),
       },
+      {
+        path: "student-exam-detail",
+        name: "StudentExamDetail",
+        component: () =>
+          import(
+            /* webpackChunkName: "exam" */ "../features/examwork/StudentExamDetail/StudentExamDetail.vue"
+          ),
+      },
       {
         path: "task",
         name: "ImportExportTask",

+ 52 - 11
src/styles/base.scss

@@ -215,14 +215,6 @@ 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 {
@@ -668,11 +660,16 @@ body {
       background-color: #e8edf3;
       overflow: hidden;
 
-      > img {
-        width: 100%;
+      .el-image {
+        display: block;
         height: 100%;
-        object-fit: contain;
       }
+
+      // > img {
+      //   width: 100%;
+      //   height: 100%;
+      //   object-fit: contain;
+      // }
     }
   }
 }
@@ -840,3 +837,47 @@ body {
     }
   }
 }
+
+// exam-edit
+.exam-edit {
+  position: absolute;
+  top: 90px;
+  right: 30px;
+  bottom: 40px;
+  left: 30px;
+  overflow: hidden;
+
+  .tab-footer {
+    position: absolute;
+    width: 100%;
+    bottom: 0;
+    left: 0;
+    z-index: 9;
+    border-top: 1px solid #f0f4f9;
+
+    padding: 15px 30px;
+    background-color: #fff;
+    border-radius: 0 0 6px 6px;
+    .el-button {
+      width: 83px;
+    }
+  }
+
+  .el-tabs {
+    flex-grow: 2;
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    position: relative;
+    z-index: 8;
+    padding-bottom: 62px;
+  }
+  .el-tabs__header {
+    flex-grow: 0;
+    flex-shrink: 0;
+  }
+  .el-tabs__content {
+    flex-grow: 2;
+    overflow: auto;
+  }
+}

+ 10 - 6
src/views/Layout/components/menu.js

@@ -60,22 +60,26 @@ const examMenuConfig = [
         title: "调卷规则",
         name: "CourseManagement",
       },
-      {
-        title: "学生档案",
-        name: "StudentManagement",
-      },
       {
         title: "考场监考设置",
         name: "InvigilateManagement",
       },
       {
-        title: "导入导出任务",
-        name: "ImportExportTask",
+        title: "考试明细",
+        name: "StudentExamDetail",
       },
       {
         title: "成绩查询",
         name: "MarkResultManagement",
       },
+      {
+        title: "学生档案",
+        name: "StudentManagement",
+      },
+      {
+        title: "导入导出任务",
+        name: "ImportExportTask",
+      },
     ],
   },
 ];