瀏覽代碼

考生导入排错

Michael Wang 4 年之前
父節點
當前提交
0b823da63e

+ 3 - 3
src/api/examwork-course.js

@@ -4,13 +4,13 @@ import { object2QueryString } from "@/utils/utils";
 
 export function searchCourses({
   examId = "",
-  courseName = "",
-  enable = "",
+  code = "",
+  hasPaper = "",
   pageNumber = 1,
   pageSize = 10,
 }) {
   const data = pickBy(
-    { examId, courseName, enable, pageNumber, pageSize },
+    { examId, code, hasPaper, pageNumber, pageSize },
     (v) => v !== ""
   );
   if (data.examId)

+ 18 - 7
src/api/examwork-task.js

@@ -2,15 +2,26 @@ import { httpApp } from "@/plugins/axiosIndex";
 import { pickBy } from "lodash-es";
 import { object2QueryString } from "@/utils/utils";
 
-export function searchTasks({ type = "", pageNumber = 1, pageSize = 10 }) {
-  const data = pickBy({ type, pageNumber, pageSize }, (v) => v !== "");
+export function searchTasks({
+  type = "",
+  entityId = "",
+  pageNumber = 1,
+  pageSize = 10,
+}) {
+  const data = pickBy(
+    { type, entityId, pageNumber, pageSize },
+    (v) => v !== ""
+  );
   if (data.type)
     return httpApp.post("/api/admin/task/query?" + object2QueryString(data));
 }
 
-export function downloadFile({ id = "", fileType = "" }) {
-  const data = pickBy({ id, fileType }, (v) => v !== "");
-  return httpApp.post(
-    "/api/admin/task/file/download?" + object2QueryString(data)
-  );
+export function importExamStudent({ examId, fileName, file, md5 }) {
+  const form = new FormData();
+  form.append("examId", examId);
+  form.append("fileName", fileName);
+  form.append("file", file);
+  return httpApp.post("/api/admin/examStudent/import", form, {
+    headers: { "Content-Type": "multipart/form-data", md5 },
+  });
 }

+ 9 - 0
src/api/system-info.js

@@ -1,5 +1,6 @@
 import { httpApp } from "@/plugins/axiosIndex";
 import { object2QueryString } from "@/utils/utils";
+import { pickBy } from "lodash-es";
 
 export function uploadFile({ file, md5 }) {
   const form = new FormData();
@@ -10,3 +11,11 @@ export function uploadFile({ file, md5 }) {
     { headers: { "Content-Type": "multipart/form-data", md5: md5 } }
   );
 }
+
+export function downloadFile({ id = "", type = "" }) {
+  const data = pickBy({ id, type }, (v) => v !== "");
+  return httpApp.post(
+    "/api/admin/sys/file/download?" +
+      object2QueryString({ ...data, type: type })
+  );
+}

+ 5 - 0
src/constant/constants.js

@@ -8,3 +8,8 @@ export const DEVICE_ID = localStorage.getItem("deviceId");
 
 export const ORG_CODE =
   process.env.VUE_APP_ORG_CODE || window.location.hostname.split(".")[0];
+
+export const INVIGILATOR_IMPORT_TEMPLATE_DOWNLOAD_URL =
+  "/file/考场监考老师导入.xlsx";
+export const EXAM_STUDENT_IMPORT_TEMPLATE_DOWNLOAD_URL =
+  "/file/考生导入_在线考试.xlsx";

+ 9 - 4
src/features/examwork/CourseManagement/CourseManagement.vue

@@ -33,12 +33,12 @@
       </el-table-column>
       <el-table-column width="120" label="状态">
         <span slot-scope="scope">{{
-          scope.row.enable | zeroOneEnableDisableFilter
+          scope.row.hasPaper === 1 ? "已绑卷" : "未绑卷"
         }}</span>
       </el-table-column>
       <el-table-column width="100" label="音频题">
         <span slot-scope="scope">{{
-          scope.row.hasPaper === 1 ? "已绑卷" : "未绑卷"
+          scope.row.hasAudio === 1 ? "是" : "否"
         }}</span>
       </el-table-column>
       <el-table-column width="100" label="提交答案">
@@ -113,8 +113,13 @@ export default {
   async created() {},
   methods: {
     async searchForm() {
-      const valid = await this.$refs.form.validate();
-      if (!valid) return;
+      try {
+        const valid = await this.$refs.form.validate();
+        if (!valid) return;
+      } catch (error) {
+        console.log(error);
+        return;
+      }
       const res = await searchCourses({
         examId: this.form.examId,
         code: this.form.code,

+ 45 - 12
src/features/examwork/ExamStudentImport/ExamStudentImport.vue

@@ -1,12 +1,14 @@
 <template>
   <div>
     <!-- 下载链接 -->
-    <el-form :model="form" inline>
+    <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="add">导入</el-button>
+      <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>
 
     <el-table :data="tableData" stripe style="width: 100%;">
@@ -37,7 +39,13 @@
             size="mini"
             type="primary"
             plain
-            @click="download({ id: scope.row.id, fileType: 'IMPORTFILE' })"
+            v-if="scope.row.status === 'FINISH'"
+            @click="
+              download({
+                id: scope.row.id,
+                type: scope.row.hasResultFile === '1' ? 'RESULT' : 'IMPORTFILE',
+              })
+            "
           >
             下载文件
           </el-button>
@@ -45,7 +53,8 @@
             size="mini"
             type="primary"
             plain
-            @click="download({ id: scope.row.id, fileType: 'ERROR' })"
+            v-if="scope.row.hasReportFile === '1'"
+            @click="download({ id: scope.row.id, type: 'REPORT' })"
           >
             导出报告
           </el-button>
@@ -63,12 +72,21 @@
         :total="total"
       />
     </div>
+
+    <ExamStudentImportDialog
+      ref="theDialog"
+      :examId="form.examId"
+      @reload="searchForm"
+    />
   </div>
 </template>
 
 <script>
-import { searchTasks, downloadFile } from "@/api/examwork-task";
+import { searchTasks } from "@/api/examwork-task";
 import { downloadFileURL } from "@/utils/utils";
+import ExamStudentImportDialog from "./ExamStudentImportDialog";
+import { EXAM_STUDENT_IMPORT_TEMPLATE_DOWNLOAD_URL } from "@/constant/constants";
+import { downloadFile } from "@/api/system-info";
 
 export default {
   name: "ExamStudentImport",
@@ -84,16 +102,22 @@ export default {
       currentPage: 1,
       pageSize: 10,
       total: 10,
-      selectedActivity: {},
+      downloadUrl: EXAM_STUDENT_IMPORT_TEMPLATE_DOWNLOAD_URL,
     };
   },
-  created() {
-    this.searchForm();
-  },
+  components: { ExamStudentImportDialog },
   methods: {
     async searchForm() {
+      // try {
+      //   const valid = await this.$refs.form.validate();
+      //   if (!valid) return;
+      // } catch (error) {
+      //   console.log(error);
+      //   return;
+      // }
       const res = await searchTasks({
         type: "IMPORT_EXAM_STUDENT",
+        entityId: this.form.examId,
         pageNumber: this.currentPage,
         pageSize: this.pageSize,
       });
@@ -109,9 +133,18 @@ export default {
       this.currentPage = 1;
       this.searchForm();
     },
-    add() {},
-    async download({ id, fileType }) {
-      const res = await downloadFile({ id, fileType });
+    async importFile() {
+      try {
+        const valid = await this.$refs.form.validate();
+        if (!valid) return;
+      } catch (error) {
+        console.log(error);
+        return;
+      }
+      this.$refs.theDialog.openDialog();
+    },
+    async download({ id, type }) {
+      const res = await downloadFile({ id, type });
       const url = res.data.data.url;
       downloadFileURL(url);
     },

+ 92 - 0
src/features/examwork/ExamStudentImport/ExamStudentImportDialog.vue

@@ -0,0 +1,92 @@
+<template>
+  <el-dialog
+    ref="dialog"
+    :title="'导入' + '考生'"
+    width="450px"
+    :visible.sync="visible"
+    @close="closeDialog"
+  >
+    <el-form
+      :model="form"
+      ref="form"
+      :rules="rules"
+      label-position="right"
+      label-width="120px"
+    >
+      <el-row>
+        <el-form-item label="选择文件">
+          <input @change="selectFile" type="file" />
+        </el-form-item>
+      </el-row>
+      <el-row class="d-flex justify-content-center">
+        <el-button type="primary" @click="submitForm">导入</el-button>
+        <el-button @click="closeDialog">取消</el-button>
+      </el-row>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import { importExamStudent } from "@/api/examwork-task";
+import MD5 from "js-md5";
+
+export default {
+  name: "ExamStudentImportDialog",
+  props: {
+    examId: String,
+    examStudent: Object,
+  },
+  computed: {
+    isEdit() {
+      return this.examStudent.id;
+    },
+  },
+  data() {
+    return {
+      visible: false,
+      form: {
+        file: "",
+        fileName: "",
+      },
+      rules: {},
+    };
+  },
+  methods: {
+    openDialog() {
+      this.visible = true;
+    },
+    closeDialog() {
+      this.visible = false;
+    },
+    selectFile(e) {
+      this.form.file = e.target.files[0];
+      this.form.fileName = this.form.file?.name;
+    },
+    async submitForm() {
+      async function blobToArray(blob) {
+        return new Promise((resolve) => {
+          var reader = new FileReader();
+          reader.addEventListener("loadend", function () {
+            // reader.result contains the contents of blob as a typed array
+            resolve(reader.result);
+          });
+          reader.readAsArrayBuffer(blob);
+        });
+      }
+      const ab = await blobToArray(this.form.file);
+      const md5 = MD5(ab);
+
+      await importExamStudent({
+        examId: this.examId,
+        file: this.form.file,
+        fileName: this.form.fileName,
+        md5,
+      });
+      this.$emit("reload");
+      this.closeDialog();
+    },
+  },
+};
+</script>
+
+<style></style>

+ 7 - 3
src/features/examwork/ExamStudentManagement/ExamStudentManagement.vue

@@ -153,9 +153,13 @@ export default {
   async created() {},
   methods: {
     async searchForm() {
-      // console.log(this.form);
-      const valid = await this.$refs.form.validate();
-      if (!valid) return;
+      try {
+        const valid = await this.$refs.form.validate();
+        if (!valid) return;
+      } catch (error) {
+        console.log(error);
+        return;
+      }
       const res = await searchExamStudents({
         ...this.form,
         pageNumber: this.currentPage,

+ 7 - 0
src/features/examwork/ExamStudentManagement/ExamStudentManagementDialog.vue

@@ -134,6 +134,13 @@ export default {
       this.visible = false;
     },
     async submitForm() {
+      try {
+        const valid = await this.$refs.form.validate();
+        if (!valid) return;
+      } catch (error) {
+        console.log(error);
+        return;
+      }
       let data = this.form;
       if (this.isEdit) {
         data = { ...data, id: this.examStudent.id };

+ 7 - 2
src/features/examwork/StudentManagement/StudentManagementDialog.vue

@@ -90,8 +90,13 @@ export default {
       this.searchForm();
     },
     async searchForm() {
-      const valid = await this.$refs.form.validate();
-      if (!valid) return;
+      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,

+ 1 - 0
src/utils/utils.js

@@ -45,6 +45,7 @@ export function object2QueryString(obj) {
 export function downloadFileURL(url, name) {
   const link = document.createElement("a");
   link.style.display = "none";
+  // txt 文件会直接在浏览器里面打开,这时候只能修改服务器设置,加上 Content-Disposition: attachment
   link.href = url;
   const fileName = name || url.split("/").pop();
   link.setAttribute("download", fileName);