Browse Source

电子交卷接口调试

zhangjie 1 year ago
parent
commit
10ff0892e9

+ 35 - 18
src/modules/card/autoBuild/paperStruct.js

@@ -1,21 +1,24 @@
-import { getFillBackClozeCount } from "./paperCard";
+const COMMON_QUESTION_TYPES = [1, 2, 3, 4, 5];
+
+export const QUESTION_TYPES = {
+  1: "SINGLE_ANSWER_QUESTION",
+  2: "MULTIPLE_ANSWER_QUESTION",
+  3: "BOOL_ANSWER_QUESTION",
+  4: "FILL_BLANK_QUESTION",
+  5: "TEXT_ANSWER_QUESTION",
+  6: "READING_COMPREHENSION",
+  7: "LISTENING_QUESTION",
+  8: "BANKED_CLOZE",
+};
 
-const COMMON_QUESTION_TYPES = [
-  "SINGLE_ANSWER_QUESTION",
-  "MULTIPLE_ANSWER_QUESTION",
-  "BOOL_ANSWER_QUESTION",
-  "FILL_BLANK_QUESTION",
-  "TEXT_ANSWER_QUESTION",
-];
 // paper json
 export function getPaperJsonSimpleStructInfo(paperJson) {
   let struct = [];
-  paperJson.paperDetails.forEach((detail) => {
+  paperJson.details.forEach((detail) => {
     struct.push(`detail:${detail.number}-${detail.name}`);
-    detail.paperDetailUnits.forEach((question) => {
-      if (COMMON_QUESTION_TYPES.includes(question.questionType)) {
-        question.question.number = question.number;
-        const info = parseCommonTypeQuestion(question.question);
+    detail.questions.forEach((question) => {
+      if (COMMON_QUESTION_TYPES.includes(question.structType)) {
+        const info = parseCommonTypeQuestion(question);
         struct.push(`${detail.number}-${info}`);
       } else {
         let infos = parseNestedTypeQuestion(question);
@@ -29,13 +32,13 @@ export function getPaperJsonSimpleStructInfo(paperJson) {
 }
 
 function parseCommonTypeQuestion(question) {
-  const structType = question.questionType;
+  const structType = QUESTION_TYPES[question.structType];
   let info = `${question.number}:${structType}`;
   const choiceQs = ["SINGLE_ANSWER_QUESTION", "MULTIPLE_ANSWER_QUESTION"];
   if (choiceQs.includes(structType)) {
-    info += `:${question.quesOptions.length}`;
+    info += `:${question.options.length}`;
   } else if (structType === "FILL_BLANK_QUESTION") {
-    info += `:${getFillBackClozeCount(question.quesOptions)}`;
+    info += `:${getFillBackClozeCount(question.body)}`;
   } else {
     info += ":";
   }
@@ -43,11 +46,25 @@ function parseCommonTypeQuestion(question) {
   return info;
 }
 
+export function getFillBackClozeCount(questionBody) {
+  let num = 0;
+  try {
+    questionBody.sections.forEach((section) => {
+      section.blocks.forEach((block) => {
+        if (block.type === "cloze") num++;
+      });
+    });
+  } catch (error) {
+    num = 1;
+  }
+
+  return num;
+}
+
 function parseNestedTypeQuestion(question) {
   let struct = [];
   let qinfo = `${question.number}`;
-  question.question.subQuestions.forEach((subq, sindex) => {
-    subq.number = sindex + 1;
+  question.subQuestions.forEach((subq) => {
     const info = parseCommonTypeQuestion(subq);
     struct.push(`${qinfo}-${info}`);
   });

+ 19 - 12
src/modules/card/components/CardBuildDialog.vue

@@ -70,7 +70,7 @@
 <script>
 import { mapState, mapMutations, mapActions } from "vuex";
 import { saveCard, cardConfigInfos } from "../api";
-// import { tikuPaperDetail } from "../../exam/api";
+import { tikuPaperDetail } from "../../exam/api";
 import { getPaperJsonSimpleStructInfo } from "../autoBuild/paperStruct";
 import { buildCardFromPaperSimpleStruct } from "../autoBuild/simplePaperCard";
 // card components
@@ -79,7 +79,7 @@ import TopicElementPreview from "../../../../card/components/TopicElementPreview
 import CardView from "../../../../card/components/CardView";
 import CardHeadSample from "../../../../card/elements/card-head/CardHead";
 // ceshi
-import paperData from "./paper.json";
+// import paperData from "./paper.json";
 
 export default {
   name: "CardBuild",
@@ -99,6 +99,7 @@ export default {
       cardId: "",
       loading: false,
       modalIsShow: false,
+      paperUuid: "",
     };
   },
   computed: {
@@ -128,17 +129,20 @@ export default {
       this.setCardConfig(cardConfig);
 
       // 试卷信息
-      // const res = await tikuPaperDetail(this.presetData.paperId).catch(
-      //   () => {}
-      // );
-      // if (!res) {
-      //   this.emitResult({ success: false, message: "试卷内容获取失败" });
-      //   return;
-      // }
-      const res = paperData;
+      const res = await tikuPaperDetail({
+        examId: this.presetData.examId,
+        paperId: this.presetData.paperId,
+      }).catch(() => {});
+      if (!res) {
+        this.emitResult({ success: false, message: "试卷内容获取失败" });
+        return;
+      }
+      // const res = paperData;
       // 构建题卡
       try {
-        const paperSimpleStruct = getPaperJsonSimpleStructInfo(res);
+        this.paperUuid = res.uuid;
+        const paperJson = res.paperJson ? JSON.parse(res.paperJson) : {};
+        const paperSimpleStruct = getPaperJsonSimpleStructInfo(paperJson);
         const elementTypePreSetInfo = {
           FILL_QUESTION: {
             pageSize: "A3",
@@ -225,7 +229,10 @@ export default {
         });
       });
       if (!result) return;
-      this.emitResult({ success: true, data: result });
+      this.emitResult({
+        success: true,
+        data: { ...result, paperUuid: this.paperUuid },
+      });
     },
     emitResult(data) {
       console.log(data);

File diff suppressed because it is too large
+ 15 - 89
src/modules/card/components/paper.json


+ 5 - 2
src/modules/exam/api.js

@@ -174,8 +174,11 @@ export const uploadOrFindExamTaskStudent = (datas) => {
 export const tikuPaperListQuery = (datas) => {
   return $postParam("/api/admin/exam/task/page_tiku_paper", datas);
 };
-export const tikuPaperDetail = (paperId) => {
-  return $postParam("/api/admin/exam/task/get_tiku_paper_struct", { paperId });
+export const tikuPaperDetail = ({ examId, paperId }) => {
+  return $postParam("/api/admin/exam/task/get_tiku_paper_data", {
+    examId,
+    paperId,
+  });
 };
 
 // task-review-manage

+ 76 - 47
src/modules/exam/components/createExamAndPrintTask/InfoExamTask.vue

@@ -119,12 +119,10 @@
                 <i
                   :class="[
                     'icon',
-                    attachment.attachmentId ? 'icon-files-act' : 'icon-files',
+                    attachment.filename ? 'icon-files-act' : 'icon-files',
                   ]"
                 ></i
-                >{{
-                  attachment.attachmentId ? attachment.filename : "选择试卷"
-                }}
+                >{{ attachment.filename || "选择试卷" }}
               </el-button>
             </td>
             <td v-else>
@@ -159,6 +157,20 @@
                 >
                 </el-option>
               </el-select>
+              <el-button
+                class="btn-primary"
+                type="text"
+                :disabled="!attachment.cardId"
+                @click="toViewCard(attachment)"
+                >预览</el-button
+              >
+              <el-button
+                class="btn-primary"
+                type="text"
+                :disabled="!attachment.cardId"
+                @click="toEditCard(attachment)"
+                >编辑</el-button
+              >
             </td>
             <td v-else>
               <el-select
@@ -194,21 +206,19 @@
                   {{ item.title }}
                 </el-option>
               </el-select>
-              <template v-if="!IS_TIKU_TAB">
-                <span
-                  v-if="attachment.cardId"
-                  :class="[
-                    attachment.cardType === 'GENERIC'
-                      ? 'color-success'
-                      : 'color-primary',
-                    'mr-1',
-                    {
-                      'color-danger': attachment.used,
-                    },
-                  ]"
-                  >[{{ attachment.cardType === "GENERIC" ? "通" : "专" }}]</span
-                >
-              </template>
+              <span
+                v-if="attachment.cardId"
+                :class="[
+                  attachment.cardType === 'GENERIC'
+                    ? 'color-success'
+                    : 'color-primary',
+                  'mr-1',
+                  {
+                    'color-danger': attachment.used,
+                  },
+                ]"
+                >[{{ attachment.cardType === "GENERIC" ? "通" : "专" }}]</span
+              >
               <el-button
                 class="btn-primary"
                 type="text"
@@ -217,7 +227,6 @@
                 >预览</el-button
               >
               <el-button
-                v-if="!IS_TIKU_TAB"
                 class="btn-primary"
                 type="text"
                 :disabled="
@@ -232,7 +241,6 @@
                 class="btn-primary"
                 type="text"
                 :disabled="
-                  IS_TIKU_TAB ||
                   !attachment.cardId ||
                   attachment.cardType === 'GENERIC' ||
                   !(!attachment.used && attachment.createId === user.id)
@@ -241,7 +249,6 @@
                 >编辑</el-button
               >
               <el-button
-                v-if="!IS_TIKU_TAB"
                 class="btn-primary"
                 type="text"
                 :disabled="!canCreateCard"
@@ -552,28 +559,17 @@ export default {
       // console.log(val);
       if (!val.id) return;
       this.examTask.examModel = val.examModel;
-      this.paperAttachments.forEach((item) => {
-        item.cardId = "";
-        item.cardType = "";
-        item.createMethod = "";
-        item.cardTitle = "";
-      });
+      if (!this.IS_TIKU_TAB) {
+        this.paperAttachments.forEach((item) => {
+          item.cardId = "";
+          item.cardType = "";
+          item.createMethod = "";
+          item.cardTitle = "";
+        });
+      }
       this.cards = [];
       this.getCardList();
     },
-    teachingRoomChange() {
-      this.examTask.courseCode = "";
-      this.examTask.courseName = "";
-      this.courses = [];
-      this.paperAttachments.forEach((item) => {
-        item.cardId = "";
-        item.cardType = "";
-        item.createMethod = "";
-        item.cardTitle = "";
-      });
-      this.cards = [];
-      this.getCourses();
-    },
     courseChange(val) {
       if (val) {
         const course = this.courses.find((item) => item.code === val);
@@ -586,6 +582,11 @@ export default {
         item.cardType = "";
         item.createMethod = "";
         item.cardTitle = "";
+        if (this.IS_TIKU_TAB) {
+          item.paperId = "";
+          item.uuid = "";
+          item.filename = "";
+        }
       });
       this.cards = [];
       this.getCardList();
@@ -721,6 +722,17 @@ export default {
       const valid = await this.$refs.examTaskComp.validate().catch(() => {});
       if (!valid) return Promise.reject();
 
+      if (this.IS_TIKU_TAB) {
+        const attachmentValid = !this.paperAttachments.some(
+          (item) => !item.filename
+        );
+        if (!attachmentValid) {
+          this.$message.error("请完成试卷选择!");
+          return Promise.reject();
+        }
+        return Promise.resolve(true);
+      }
+
       // 设置了入库强制包含试卷时,校验试卷是否上传。
       // 未设置入库强制包含试卷时,若有试卷上传,则需要上传全部。若无试卷上传,则通过。
       if (this.examTaskDetail.includePaper) {
@@ -776,12 +788,16 @@ export default {
     },
     // select-paper
     toSelect(attachment) {
-      this.curAttachment = attachment;
-      // this.$refs.SelectTikuPaperDialog.open();
-      this.tikuPaperSelected({ id: "1", name: "paper-name" });
+      this.curAttachment = {
+        ...attachment,
+        courseCode: this.examTask.courseCode,
+      };
+      this.$refs.SelectTikuPaperDialog.open();
+      // this.tikuPaperSelected({ id: "1", name: "paper-name" });
     },
     async tikuPaperSelected(data) {
       this.cardBuildPresetData = {
+        examId: this.examTask.examId,
         courseCode: this.examTask.courseCode,
         courseName: this.examTask.courseName,
         schoolName: this.$ls.get("schoolName"),
@@ -800,10 +816,21 @@ export default {
         this.$message.error(data.message);
         return;
       }
-      Object.assign(this.curAttachment, {
+      const ind = this.paperAttachments.findIndex(
+        (item) => item.name === this.curAttachment.name
+      );
+      if (ind === -1) return;
+
+      const info = data.data;
+      this.curAttachment = { ...this.paperAttachments[ind] };
+      this.paperAttachments[ind] = Object.assign(this.paperAttachments[ind], {
         paperId: this.cardBuildPresetData.paperId,
-        cardId: data.cardId,
-        cardTitle: data.cardTitle,
+        cardType: this.cardBuildPresetData.type,
+        createMethod: this.cardBuildPresetData.createMethod,
+        filename: this.cardBuildPresetData.paperName,
+        cardId: info.id,
+        cardTitle: info.title,
+        uuid: info.paperUuid,
       });
     },
     // exam-task-detail edit
@@ -818,6 +845,8 @@ export default {
         createMethod: "",
         cardTitle: "",
         filename: "",
+        paperId: null,
+        uuid: null,
         pages: 0,
         used: false,
         createId: null,

+ 56 - 13
src/modules/exam/components/createExamAndPrintTask/SelectTikuPaperDialog.vue

@@ -9,6 +9,7 @@
     :close-on-press-escape="false"
     append-to-body
     destroy-on-close
+    @open="visibleChange"
   >
     <div class="part-box part-box-pad">
       <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
@@ -20,7 +21,7 @@
           ></el-input>
         </el-form-item>
         <el-form-item label-width="0px">
-          <el-checkbox v-model="filter.youSelf">仅显示本人试卷</el-checkbox>
+          <el-checkbox v-model="youSelf">仅显示本人试卷</el-checkbox>
         </el-form-item>
         <el-form-item label-width="0px">
           <el-button type="primary" @click="getList">查询</el-button>
@@ -30,16 +31,23 @@
 
     <div class="part-box part-box-pad">
       <el-table ref="TableList" :data="dataList">
-        <el-table-column type="index" label="序号"></el-table-column>
-        <el-table-column prop="paperName" label="试卷名称"></el-table-column>
-        <el-table-column prop="examPrintPlanName" label="命题人">
+        <el-table-column
+          type="index"
+          label="序号"
+          :index="indexMethod"
+        ></el-table-column>
+        <el-table-column prop="name" label="试卷名称"></el-table-column>
+        <el-table-column prop="createByAccount" label="命题人">
         </el-table-column>
-        <el-table-column prop="createTime" label="创建时间" width="170">
-          <span slot-scope="scope">{{
-            scope.row.createTime | timestampFilter
-          }}</span>
+        <el-table-column prop="paperDetailCount" label="大题数" width="65">
         </el-table-column>
-        <el-table-column class-name="action-column" label="操作" width="100">
+        <el-table-column prop="unitCount" label="小题数" width="65">
+        </el-table-column>
+        <el-table-column prop="totalScore" label="试卷总分" width="80">
+        </el-table-column>
+        <el-table-column prop="creationTime" label="创建时间" width="160">
+        </el-table-column>
+        <el-table-column class-name="action-column" label="操作" width="60">
           <template slot-scope="scope">
             <el-button
               :class="
@@ -52,6 +60,19 @@
           </template>
         </el-table-column>
       </el-table>
+      <div class="part-page">
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next, jumper"
+          :pager-count="5"
+          :current-page="current"
+          :total="total"
+          :page-size="size"
+          @current-change="toPage"
+          @size-change="pageSizeChange"
+        >
+        </el-pagination>
+      </div>
     </div>
     <div slot="footer">
       <el-button @click="cancel">关闭</el-button>
@@ -77,13 +98,25 @@ export default {
       modalIsShow: false,
       filter: {
         paperName: "",
-        youSelf: true,
+        account: "",
       },
+      youSelf: true,
       dataList: [],
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
       loading: false,
     };
   },
   methods: {
+    visibleChange() {
+      this.filter = {
+        paperName: "",
+        account: "",
+      };
+      this.youSelf = true;
+      this.toPage(1);
+    },
     cancel() {
       this.modalIsShow = false;
     },
@@ -91,11 +124,21 @@ export default {
       this.modalIsShow = true;
     },
     async getList() {
-      const res = await tikuPaperListQuery({
+      const datas = {
         courseCode: this.row.courseCode,
         ...this.filter,
-      });
-      this.dataList = res || [];
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      if (this.youSelf)
+        datas.account = this.$ls.get("user", { loginName: "" }).loginName;
+      const res = await tikuPaperListQuery(datas);
+      this.dataList = res.records;
+      this.total = res.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
     },
     toSelect(row) {
       this.$emit("confirm", row);

+ 0 - 1
src/modules/exam/views/ExamTaskManage.vue

@@ -113,7 +113,6 @@
           label="考试"
           min-width="160"
         ></el-table-column>
-        <!-- <el-table-column prop="sequence" label="序号"></el-table-column> -->
         <el-table-column
           prop="paperNumber"
           label="试卷编号"

Some files were not shown because too many files changed in this diff