Bläddra i källkod

feat: 创建命题任务修改

zhangjie 8 månader sedan
förälder
incheckning
abc256b362

+ 1 - 1
src/modules/card/autoBuild/simplePaperCard.js

@@ -178,7 +178,7 @@ export function buildCardFromPaperSimpleStruct(
   elementTypePreSetInfo
 ) {
   const structList = parsePaperStruct(paperSimpleStruct);
-  console.log(structList);
+  // console.log(structList);
   const cardElements = buildCardElements(structList, elementTypePreSetInfo);
   // console.log(cardElements);
   return cardElements;

+ 2 - 1
src/modules/card/components/CardBuildDialog.vue

@@ -196,7 +196,7 @@ export default {
       this.$nextTick(() => {
         this.rebuildPages();
         this.cachePages = deepCopy(this.pages);
-        console.log(this.cachePages);
+        // console.log(this.cachePages);
         this.updatePageField();
 
         this.$nextTick(() => {
@@ -306,6 +306,7 @@ export default {
       config.aOrB = false;
       config.requiredFields = JSON.parse(config.requiredFields);
       config.extendFields = JSON.parse(config.extendFields);
+      config.relationList = JSON.parse(config.relationList || "[]");
       config.cardTitle = this.getCardTitle(config.titleRule);
       return config;
     },

+ 220 - 141
src/modules/exam/components/createExamAndPrintTask/InfoExamTask.vue

@@ -191,140 +191,153 @@
                   }}
                 </el-button>
               </td>
-              <td v-if="IS_TIKU_TAB">
-                <el-select
-                  v-model="attachment.cardId"
-                  placeholder="请选择"
-                  style="width: 260px; margin-right: 10px"
-                  @change="(val) => tkCardChange(val, attachment)"
-                >
-                  <el-option
-                    v-for="item in attachment.cards"
-                    :key="item.id"
-                    :value="item.id"
-                    :label="item.title"
-                  >
-                    <div class="box-justify">
-                      <div class="box-grow">{{ item.title }}</div>
-                      <el-button
-                        class="btn-danger btn-icon box-static"
-                        type="text"
-                        icon="el-icon-remove"
-                        @click="toDeleteCard(item, attachment)"
-                      ></el-button>
-                    </div>
-                  </el-option>
-                </el-select>
-                <el-button
-                  class="btn-primary"
-                  type="text"
-                  :disabled="!attachment.cardId"
-                  @click="toViewCard(attachment)"
-                  >预览</el-button
-                >
-                <el-button
-                  v-if="!IS_REBUILD"
-                  class="btn-primary"
-                  type="text"
-                  :disabled="!attachment.cardId"
-                  @click="toEditCard(attachment)"
-                  >编辑</el-button
+              <template v-if="IS_TIKU_TAB">
+                <td
+                  v-if="index === 0"
+                  :rowspan="paperAttachment.paperAttachmentIds.length"
                 >
-              </td>
-              <td v-else>
-                <el-select
-                  class="mr-2"
-                  v-model="attachment.cardId"
-                  placeholder="请选择"
-                  style="width: 200px"
-                  filterable
-                  @change="cardChange(attachment)"
-                >
-                  <el-option
-                    v-for="item in cards"
-                    :key="item.id"
-                    :value="item.id"
-                    :label="item.title"
-                    :disabled="item.disabled"
+                  <el-select
+                    v-model="attachment.cardId"
+                    placeholder="请选择"
+                    style="width: 260px; margin-right: 10px"
+                    @change="(val) => tkCardChange(val, attachment)"
                   >
-                    <div class="box-justify">
-                      <div class="box-grow">
-                        <span
-                          :class="[
-                            item.type === 'GENERIC'
-                              ? 'color-success'
-                              : 'color-primary',
-                            'mr-1',
-                            {
-                              'color-danger': item.used,
-                            },
-                          ]"
-                          >[{{ item.type === "GENERIC" ? "通" : "专" }}]</span
-                        >
-                        {{ item.title }}
+                    <el-option
+                      v-for="item in attachment.cards"
+                      :key="item.id"
+                      :value="item.id"
+                      :label="item.title"
+                    >
+                      <div class="box-justify">
+                        <div class="box-grow">{{ item.title }}</div>
+                        <el-button
+                          class="btn-danger btn-icon box-static"
+                          type="text"
+                          icon="el-icon-remove"
+                          @click="toDeleteCard(item, attachment)"
+                        ></el-button>
                       </div>
-                      <el-button
-                        v-if="item.type !== 'GENERIC'"
-                        class="btn-danger btn-icon box-static"
-                        type="text"
-                        icon="el-icon-remove"
-                        @click="toDeleteCard(item, attachment)"
-                      ></el-button>
-                    </div>
-                  </el-option>
-                </el-select>
-                <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"
-                  :disabled="!attachment.cardId"
-                  @click="toViewCard(attachment)"
-                  >预览</el-button
-                >
-                <template v-if="!IS_REBUILD">
+                    </el-option>
+                  </el-select>
                   <el-button
                     class="btn-primary"
                     type="text"
-                    :disabled="
-                      !attachment.cardId ||
-                      (attachment.cardType === 'GENERIC' &&
-                        attachment.createMethod !== 'STANDARD')
-                    "
-                    @click="toCopyCard(attachment)"
-                    >复制</el-button
+                    :disabled="!attachment.cardId"
+                    @click="toViewCard(attachment)"
+                    >预览</el-button
                   >
                   <el-button
+                    v-if="!IS_REBUILD"
                     class="btn-primary"
                     type="text"
-                    :disabled="
-                      !attachment.cardId ||
-                      attachment.cardType === 'GENERIC' ||
-                      !(!attachment.used && attachment.createId === user.id)
-                    "
+                    :disabled="!attachment.cardId"
                     @click="toEditCard(attachment)"
                     >编辑</el-button
                   >
+                </td>
+              </template>
+              <template v-else>
+                <td
+                  v-if="index === 0"
+                  :rowspan="paperAttachment.paperAttachmentIds.length"
+                >
+                  <el-select
+                    class="mr-2"
+                    v-model="attachment.cardId"
+                    placeholder="请选择"
+                    style="width: 200px"
+                    filterable
+                    @change="cardChange(attachment)"
+                  >
+                    <el-option
+                      v-for="item in cards"
+                      :key="item.id"
+                      :value="item.id"
+                      :label="item.title"
+                      :disabled="item.disabled"
+                    >
+                      <div class="box-justify">
+                        <div class="box-grow">
+                          <span
+                            :class="[
+                              item.type === 'GENERIC'
+                                ? 'color-success'
+                                : 'color-primary',
+                              'mr-1',
+                              {
+                                'color-danger': item.used,
+                              },
+                            ]"
+                            >[{{ item.type === "GENERIC" ? "通" : "专" }}]</span
+                          >
+                          {{ item.title }}
+                        </div>
+                        <el-button
+                          v-if="item.type !== 'GENERIC'"
+                          class="btn-danger btn-icon box-static"
+                          type="text"
+                          icon="el-icon-remove"
+                          @click="toDeleteCard(item, attachment)"
+                        ></el-button>
+                      </div>
+                    </el-option>
+                  </el-select>
+                  <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"
-                    :disabled="!canCreateCard"
-                    @click="toCreateCard(attachment)"
-                    >新建</el-button
+                    :disabled="!attachment.cardId"
+                    @click="toViewCard(attachment)"
+                    >预览</el-button
                   >
-                </template>
-              </td>
+                  <template v-if="!IS_REBUILD">
+                    <el-button
+                      class="btn-primary"
+                      type="text"
+                      :disabled="
+                        !attachment.cardId ||
+                        (attachment.cardType === 'GENERIC' &&
+                          attachment.createMethod !== 'STANDARD')
+                      "
+                      @click="toCopyCard(attachment)"
+                      >复制</el-button
+                    >
+                    <el-button
+                      class="btn-primary"
+                      type="text"
+                      :disabled="
+                        !attachment.cardId ||
+                        attachment.cardType === 'GENERIC' ||
+                        !(!attachment.used && attachment.createId === user.id)
+                      "
+                      @click="toEditCard(attachment)"
+                      >编辑</el-button
+                    >
+                    <el-button
+                      v-if="index === 0"
+                      class="btn-primary"
+                      type="text"
+                      :disabled="!canCreateCard"
+                      @click="toCreateCard(attachment)"
+                      >新建</el-button
+                    >
+                  </template>
+                </td>
+              </template>
               <td
                 v-if="!IS_REBUILD && index === 0"
                 :rowspan="paperAttachment.paperAttachmentIds.length"
@@ -657,6 +670,11 @@ export default {
           paperAttachment.paperAttachmentIds.push(
             Object.assign(deepCopy(attachment), {
               name: "B",
+              attachmentId: "",
+              filename: "",
+              paperId: null,
+              paperUrl: null,
+              pages: 0,
             })
           );
         });
@@ -705,7 +723,16 @@ export default {
         examId: this.examTask.examId,
         paperId: attachment.paperId,
       });
-      attachment.cards = data || [];
+      attachment.cards = (data || []).map((item) => {
+        return {
+          id: item.id,
+          title: item.title,
+          type: item.type,
+          createId: item.createId,
+          makeMethod: item.makeMethod,
+          used: item.used,
+        };
+      });
     },
     async getCourses() {
       if (!this.examTask.teachingRoomId || !this.examTask.examId) return;
@@ -759,6 +786,19 @@ export default {
       this.getCardList();
     },
     updateExamTaskDetail() {
+      if (this.examTask.openAb) {
+        this.paperAttachments.forEach((paperAttachment) => {
+          const aAttachment = paperAttachment.paperAttachmentIds[0];
+          Object.assign(paperAttachment.paperAttachmentIds[1], {
+            cardId: aAttachment.cardId,
+            cardType: aAttachment.cardType,
+            createMethod: aAttachment.createMethod,
+            cardTitle: aAttachment.cardTitle,
+            used: aAttachment.used,
+            createId: aAttachment.createId,
+          });
+        });
+      }
       this.examTaskDetail = this.paperAttachments.map((item) => {
         return {
           ...item,
@@ -792,15 +832,32 @@ export default {
         });
       }
     },
-    cardChange(attachment) {
+    async cardChange(attachment) {
       const card = this.cards.find((item) => item.id === attachment.cardId);
-      if (card) {
-        attachment.cardType = card.type;
-        attachment.createMethod = card.createMethod;
-        attachment.cardTitle = card.title;
-        attachment.used = card.used;
-        attachment.createId = card.createId;
-      }
+      if (!card) return;
+
+      attachment.cardType = card.type;
+      attachment.createMethod = card.createMethod;
+      attachment.cardTitle = card.title;
+      attachment.used = card.used;
+      attachment.createId = card.createId;
+    },
+    updateAttachmentBFromA(attachment) {
+      if (!this.examTask.openAb) return;
+
+      const pos = this.getAttachmentPos(attachment);
+      if (!pos) return;
+
+      const paperAttachment = this.paperAttachments[pos.pindex];
+      const aAttachment = paperAttachment.paperAttachmentIds[0];
+      Object.assign(paperAttachment.paperAttachmentIds[1], {
+        cardId: aAttachment.cardId,
+        cardType: aAttachment.cardType,
+        createMethod: aAttachment.createMethod,
+        cardTitle: aAttachment.cardTitle,
+        used: aAttachment.used,
+        createId: aAttachment.createId,
+      });
     },
     async toCreateCard(attachment) {
       if (!this.examTask.cardRuleId) {
@@ -853,7 +910,7 @@ export default {
     async toCopyCard(attachment) {
       this.curAttachment = { ...attachment };
       const newCardId = await copyCard(
-        attachment.cardId,
+        attachment.toCopyCardId,
         this.examTask.courseId
       );
       this.cardModified({ id: newCardId });
@@ -875,19 +932,19 @@ export default {
 
       await this.getCardList();
       let card = this.cards.find((item) => item.id === data.id);
-      if (card) {
-        Object.assign(
-          this.paperAttachments[pos.pindex].paperAttachmentIds[pos.index],
-          {
-            cardId: card.id,
-            cardType: card.type,
-            createMethod: card.createMethod,
-            cardTitle: card.title,
-            used: card.used,
-            createId: card.createId,
-          }
-        );
-      }
+      if (!card) return;
+
+      Object.assign(
+        this.paperAttachments[pos.pindex].paperAttachmentIds[pos.index],
+        {
+          cardId: card.id,
+          cardType: card.type,
+          createMethod: card.createMethod,
+          cardTitle: card.title,
+          used: card.used,
+          createId: card.createId,
+        }
+      );
     },
     tkCardChange(card, attachment) {
       attachment.cardTitle = card.title;
@@ -908,6 +965,7 @@ export default {
         attachment.cardId = null;
         attachment.cardTitle = "";
       }
+
       if (this.IS_TIKU_TAB) {
         attachment.cards = attachment.cards.filter(
           (item) => item.id !== card.id
@@ -920,6 +978,8 @@ export default {
       const valid = await this.$refs.examTaskComp.validate().catch(() => {});
       if (!valid) return Promise.reject();
 
+      this.updateExamTaskDetail();
+
       const paperAttachments = this.paperAttachments
         .map((item) => item.paperAttachmentIds)
         .flat();
@@ -1008,9 +1068,28 @@ export default {
       return { pindex, index };
     },
     toSelect(attachment) {
+      if (!this.examTask.courseId) {
+        this.$message.error("请先选择课程!");
+        return;
+      }
+
+      let comparePaperId = null;
+      if (this.examTask.openAb) {
+        const pos = this.getAttachmentPos(attachment);
+        if (!pos) return;
+        const paperAttachment = this.paperAttachments[pos.pindex];
+        const otherAttachment = paperAttachment.paperAttachmentIds.find(
+          (item) => item.name !== attachment.name
+        );
+        if (otherAttachment) comparePaperId = otherAttachment.paperId;
+      }
+
       this.curAttachment = {
         ...attachment,
+        comparePaperId,
         courseId: this.examTask.courseId,
+        examId: this.examTask.examId,
+        uuid: this.examTask.uuid,
       };
       this.$refs.SelectTikuPaperDialog.open();
       // this.tikuPaperSelected({ id: "1", name: "paper-name" });
@@ -1077,7 +1156,7 @@ export default {
         filename: "",
         paperId: null,
         paperUrl: null,
-        uuid: null,
+        uuid: this.examTask.uuid,
         cardId: "",
         cardType: "",
         createMethod: "",

+ 58 - 2
src/modules/exam/components/createExamAndPrintTask/SelectTikuPaperDialog.vue

@@ -81,7 +81,8 @@
 </template>
 
 <script>
-import { tikuPaperListQuery } from "../../api";
+import json5 from "json5";
+import { tikuPaperListQuery, tikuPaperDetail } from "../../api";
 
 export default {
   name: "select-tiku-paper-dialog",
@@ -140,7 +141,62 @@ export default {
       this.current = page;
       this.getList();
     },
-    toSelect(row) {
+    getPaperStruct(paperJson) {
+      const structs = [];
+      paperJson.details.forEach((detail) => {
+        detail.questions.forEach((question) => {
+          if (question.subQuestions && question.subQuestions.length) {
+            question.subQuestions.forEach((subq) => {
+              structs.push(
+                `${detail.number}_${question.number}_${question.structType}_${subq.number}_${subq.structType}`
+              );
+            });
+          } else {
+            structs.push(
+              `${detail.number}_${question.number}_${question.structType}`
+            );
+          }
+        });
+      });
+
+      return structs.join();
+    },
+    async comparePaperStruct(paperIds) {
+      const allFunc = paperIds.map((paperId) =>
+        tikuPaperDetail({
+          paperId,
+          examId: this.row.examId,
+          uuid: this.row.uuid,
+        })
+      );
+
+      const result = await Promise.all(allFunc).catch(() => {});
+      if (!result) return;
+
+      const paperStructs = result.map((item) => {
+        const paperJson = item.paperJson
+          ? json5.parse(item.paperJson)
+          : { details: [] };
+
+        return this.getPaperStruct(paperJson);
+      });
+
+      const compareStruct = paperStructs[0];
+      const valid = !paperStructs.some((item) => item !== compareStruct);
+      return { valid };
+    },
+    async toSelect(row) {
+      if (this.row.comparePaperId && this.row.comparePaperId !== row.id) {
+        const res = await this.comparePaperStruct([
+          row.id,
+          this.row.comparePaperId,
+        ]).catch(() => {});
+        if (!res) return;
+        if (!res.valid) {
+          this.$message.error("试卷结构不一致,请重新选择!");
+          return;
+        }
+      }
       this.$emit("confirm", row);
       this.cancel();
     },

+ 24 - 1
src/modules/exam/components/createExamAndPrintTask/data.json

@@ -21,7 +21,30 @@
     {
       "serialNumber": "Ⅰ",
       "paperType": "A",
-      "paperAttachmentIds": "[{\"name\":\"A\",\"attachmentId\":\"563738306609676288\",\"filename\":\"解剖生理学1.pdf\",\"paperId\":null,\"paperUrl\":null,\"uuid\":null,\"cardId\":\"563738420979957760\",\"cardType\":\"CUSTOM\",\"createMethod\":null,\"cardTitle\":\"dy2\",\"pages\":2,\"used\":false,\"createId\":\"539033700742987776\",\"cards\":[],\"original\":{\"id\":\"563738306609676288\",\"updateTime\":1725346486093,\"pages\":2,\"pageSize\":\"A3\"}}]"
+      "paperAttachmentIds": [
+        {
+          "name": "A",
+          "attachmentId": "563738306609676288",
+          "filename": "解剖生理学1.pdf",
+          "paperId": null,
+          "paperUrl": null,
+          "uuid": null,
+          "cardId": "563738420979957760",
+          "cardType": "CUSTOM",
+          "createMethod": null,
+          "cardTitle": "dy2",
+          "pages": 2,
+          "used": false,
+          "createId": "539033700742987776",
+          "cards": [],
+          "original": {
+            "id": "563738306609676288",
+            "updateTime": 1725346486093,
+            "pages": 2,
+            "pageSize": "A3"
+          }
+        }
+      ]
     }
   ],
   "examDetail": {