Jelajahi Sumber

bugfix和临时需求和UI优化

刘洋 1 tahun lalu
induk
melakukan
0de0229fb3

+ 10 - 4
src/assets/styles/pages.scss

@@ -873,7 +873,7 @@
 }
 
 // question-edit-dialog
-.question-edit-dialog,.question-identify-dialog {
+.question-edit-dialog,.question-identify-dialog,.gpt-question-dialog {
   .el-dialog__header {
     h2 {
       display: inline-block;
@@ -1064,11 +1064,17 @@
     flex-shrink: 0;
     padding: 10px;
     border-radius: 5px;
-    background-color: $--color-background;
+    // background-color: $--color-background;
     margin-right: 10px;
+    border:1px solid #eee;
 
     .el-tree {
-      background-color: $--color-background;
+      // background-color: $--color-background;
+      .el-tree-node__content{
+        &:hover{
+          background:#f0f0f0;
+        }
+      }
     }
   }
   .struct-prop {
@@ -1207,7 +1213,7 @@
     color: $--color-text-primary;
     height: auto;
     min-height: 30px;
-    background-color: transparent !important;
+    // background-color: transparent !important;
   }
   .node-form {
     display: inline-block;

+ 17 - 4
src/modules/card/components/CardDesign.vue

@@ -4,8 +4,15 @@
     <div class="design-action">
       <div class="design-logo">
         <h1>
-          <i class="el-icon-d-arrow-left" title="退出" @click="toExit"></i>
-          答题卡制作
+          <el-button
+            class="is-back"
+            icon="el-icon-arrow-left"
+            @click="toExit"
+            size="mini"
+            style="vertical-align: middle"
+          ></el-button>
+          <!-- <i class="el-icon-d-arrow-left" title="退出" @click="toExit"></i> -->
+          <span style="vertical-align: middle">答题卡制作</span>
         </h1>
       </div>
 
@@ -52,17 +59,23 @@
             :loading="isSubmit"
             :disabled="!pages.length"
             @click="toPreview"
+            icon="el-icon-view"
             >预览</el-button
           >
           <el-button
             v-if="showSaveBtn"
-            type="primary"
+            type="warning"
             :loading="isSubmit"
             :disabled="canSave || !pages.length"
             @click="toSave"
+            icon="el-icon-set-up"
             >暂存</el-button
           >
-          <el-button type="primary" :loading="isSubmit" @click="toSubmit"
+          <el-button
+            type="primary"
+            :loading="isSubmit"
+            @click="toSubmit"
+            icon="el-icon-circle-check"
             >提交</el-button
           >
         </div>

+ 259 - 0
src/modules/paper/components/PaperStructInfo.vue

@@ -0,0 +1,259 @@
+<template>
+  <el-dialog
+    title="试卷结构分析"
+    width="100%"
+    :visible.sync="modalIsShow"
+    :modal="true"
+    append-to-body
+    custom-class="side-dialog"
+    @open="getData"
+  >
+    <el-form label-width="90px">
+      <el-form-item label="整卷属性">
+        <div class="topic-set-list">
+          <div
+            v-for="(paperTag, tagIndex) in paperData.tags"
+            :key="tagIndex"
+            class="topic-set"
+          >
+            <div class="topic-set-title">{{ paperTag.tag }}</div>
+            <div class="topic-set-content">
+              {{ paperTag.content }}
+            </div>
+          </div>
+        </div>
+      </el-form-item>
+      <el-form-item label="组成结构">
+        <el-table :data="paperData.data" border>
+          <el-table-column
+            v-for="(colval, colIndex) in paperData.head"
+            :key="colIndex"
+          >
+            <template slot="header">
+              <span style="margin-left: 10px">{{ colval }}</span>
+            </template>
+            <template slot-scope="scope">
+              <span style="margin-left: 10px">{{ scope.row[colIndex] }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-form-item>
+    </el-form>
+
+    <!-- <el-form>
+      <el-form-item label="统计维度">
+        <el-select v-model="type" @change="getPaperData">
+          <el-option label="题数" value="count"></el-option>
+          <el-option label="分值" value="score"></el-option>
+        </el-select>
+      </el-form-item>
+    </el-form> -->
+    <el-form label-width="90px" style="margin-top: 40px">
+      <el-form-item label="题型分布">
+        <el-select v-model="type" @change="getPaperData">
+          <el-option label="题数" value="count"></el-option>
+          <el-option label="分值" value="score"></el-option>
+        </el-select>
+        <el-table
+          :data="paperData.data"
+          border
+          :span-method="objectSpanMethod"
+          style="margin-top: 10px"
+        >
+          <el-table-column label="题型" align="center">
+            <el-table-column
+              v-for="(colval, colIndex) in headFirst2"
+              :key="colIndex"
+            >
+              <template slot="header">
+                <span style="margin-left: 10px">{{ colval }}</span>
+              </template>
+              <template slot-scope="scope">
+                <span style="margin-left: 10px">{{ scope.row[colIndex] }}</span>
+              </template>
+            </el-table-column>
+          </el-table-column>
+          <el-table-column label="大题" align="center">
+            <el-table-column
+              v-for="(colval, colIndex) in headSecond2"
+              :key="colIndex"
+            >
+              <template slot="header">
+                <span style="margin-left: 10px">{{ colval }}</span>
+              </template>
+              <template slot-scope="scope">
+                <span style="margin-left: 10px">{{
+                  scope.row[colIndex + 2]
+                }}</span>
+              </template>
+            </el-table-column>
+          </el-table-column>
+        </el-table>
+      </el-form-item>
+    </el-form>
+
+    <!-- <h2 style="color: #262626; margin-bottom: 10px">知识点</h2> -->
+    <!-- <el-form>
+      <el-form-item label="可选属性">
+        <property-select
+          v-model="coursePropertyId"
+          :course-id="courseId"
+          @change="getPaperData"
+        >
+        </property-select>
+      </el-form-item>
+    </el-form> -->
+
+    <el-form label-width="90px" style="margin-top: 40px">
+      <el-form-item label="蓝图分布">
+        <el-table
+          :data="paperData3.data"
+          style="width: 100%"
+          border
+          :span-method="objectSpanMethod3"
+        >
+          <el-table-column label="蓝图属性" align="center">
+            <el-table-column
+              v-for="(colval, colIndex) in headFirst3"
+              :key="colIndex"
+            >
+              <template slot="header">
+                <span style="margin-left: 10px">{{ colval }}</span>
+              </template>
+              <template slot-scope="scope">
+                <span style="margin-left: 10px">{{ scope.row[colIndex] }}</span>
+              </template>
+            </el-table-column>
+          </el-table-column>
+          <el-table-column label="大题" align="center">
+            <el-table-column
+              v-for="(colval, colIndex) in headSecond3"
+              :key="colIndex"
+            >
+              <template slot="header">
+                <span style="margin-left: 10px">{{ colval }}</span>
+              </template>
+              <template slot-scope="scope">
+                <span style="margin-left: 10px">{{
+                  scope.row[colIndex + 2]
+                }}</span>
+              </template>
+            </el-table-column>
+          </el-table-column>
+        </el-table>
+      </el-form-item>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import { paperBaseInfoApi, paperQtypeInfoApi, paperBlueInfoApi } from "../api";
+export default {
+  name: "PaperStructInfo",
+  props: {
+    paperId: {
+      type: [String, Number],
+      default: "",
+    },
+    courseId: {
+      type: [String, Number],
+      default: null,
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      paperData: {
+        tags: [],
+        head: [],
+      },
+      type: "count",
+      paperData2: { head: [] },
+      headFirst2: [],
+      headSecond2: [],
+      paperData3: { head: [] },
+      headFirst3: [],
+      headSecond3: [],
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getData() {
+      const res = await paperBaseInfoApi(this.paperId);
+      this.paperData = res.data;
+      this.getPaperData();
+      this.getPaperData3();
+    },
+    async getPaperData() {
+      const res = await paperQtypeInfoApi({
+        paperId: this.paperId,
+        type: this.type,
+      });
+      this.paperData2 = res.data;
+      this.headFirst2 = this.paperData2.head.slice(0, 2);
+      this.headSecond2 = this.paperData2.head.slice(2);
+    },
+    objectSpanMethod({ rowIndex, columnIndex }) {
+      // console.log(row, column);
+      if (columnIndex === 0 && rowIndex === 0) {
+        return {
+          rowspan: 5,
+          colspan: 1,
+        };
+      }
+      if (columnIndex === 0 && rowIndex > 0 && rowIndex < 5) {
+        return {
+          rowspan: 0,
+          colspan: 0,
+        };
+      }
+      if (columnIndex === 0 && rowIndex === 5) {
+        return {
+          rowspan: 4,
+          colspan: 1,
+        };
+      }
+      if (columnIndex === 0 && rowIndex > 5 && rowIndex < 9) {
+        return {
+          rowspan: 0,
+          colspan: 0,
+        };
+      }
+    },
+    async getPaperData3() {
+      // if (!this.coursePropertyId) return;
+      const res = await paperBlueInfoApi({
+        paperId: this.paperId,
+        courseId: this.courseId,
+        // coursePropertyId: this.coursePropertyId,
+        rootOrgId: this.$store.state.user.rootOrgId,
+      });
+      this.paperData3 = res.data;
+      this.headFirst3 = this.paperData3.head.slice(0, 2);
+      this.headSecond3 = this.paperData3.head.slice(2);
+    },
+    objectSpanMethod3({ rowIndex, columnIndex }) {
+      if (columnIndex === 0) {
+        for (let span of this.paperData.rowspan) {
+          if (span[0] == rowIndex) {
+            return {
+              rowspan: span[1] - span[0] + 1,
+              colspan: 1,
+            };
+          } else if (span[0] < rowIndex && span[1] >= rowIndex) {
+            return {
+              rowspan: 0,
+              colspan: 0,
+            };
+          }
+        }
+      }
+    },
+  },
+};
+</script>

+ 15 - 2
src/modules/paper/views/EditPaper.vue

@@ -126,7 +126,10 @@
           >
             新增大题
           </el-button>
-          <el-button plain size="small" @click="toViewBaseInfo">
+          <el-button plain size="small" @click="toViewStructInfo">
+            试卷结构分析
+          </el-button>
+          <!-- <el-button plain size="small" @click="toViewBaseInfo">
             基础构成
           </el-button>
           <el-button plain size="small" @click="toViewQuestypeInfo">
@@ -134,7 +137,7 @@
           </el-button>
           <el-button plain size="small" @click="toViewBlueInfo">
             蓝图分布
-          </el-button>
+          </el-button> -->
           <!-- <el-button plain size="small" @click="toViewAuditInfo">
             审核记录
           </el-button> -->
@@ -739,6 +742,11 @@
       show-selective
       @modified="detailModified"
     ></modify-detail-struct>
+    <paper-struct-info
+      ref="PaperStructInfo"
+      :paper-id="paperId"
+      :course-id="paper.course.id"
+    ></paper-struct-info>
     <!-- 基础构成 -->
     <paper-base-info ref="PaperBaseInfo" :paper-id="paperId"></paper-base-info>
     <!-- 上传答案文件 -->
@@ -813,6 +821,7 @@ import {
 import { QUESTION_API } from "@/constants/constants";
 
 import ImportFileDialog from "@/components/ImportFileDialog.vue";
+import PaperStructInfo from "../components/PaperStructInfo.vue";
 import PaperBaseInfo from "../components/PaperBaseInfo.vue";
 import PaperQuestypeInfo from "../components/PaperQuestypeInfo.vue";
 import PaperBlueInfo from "../components/PaperBlueInfo.vue";
@@ -829,6 +838,7 @@ import { mapGetters } from "vuex";
 export default {
   name: "EditPaper",
   components: {
+    PaperStructInfo,
     PaperBaseInfo,
     PaperQuestypeInfo,
     PaperAuditInfo,
@@ -1028,6 +1038,9 @@ export default {
       this.quesTagShow = !this.quesTagShow;
       sessionStorage.setItem("quesTagShow", this.quesTagShow);
     },
+    toViewStructInfo() {
+      this.$refs.PaperStructInfo.open();
+    },
     // 查看基础构成
     toViewBaseInfo() {
       this.$refs.PaperBaseInfo.open();

+ 12 - 1
src/modules/portal/views/home/Home.vue

@@ -23,8 +23,15 @@
         </li>
       </ul>
     </div>
-    <div v-if="ifShowHomeSide" class="header-breadcrumb">
+    <div
+      v-if="ifShowHomeSide"
+      class="header-breadcrumb box-justify"
+      style="right: 0"
+    >
       <LinkTitles :key="Math.random()" />
+      <el-button type="danger" plain @click="$router.back()" v-if="showBackBtn"
+        >返回</el-button
+      >
     </div>
     <div class="home-body">
       <div class="home-main">
@@ -274,6 +281,10 @@ export default {
       const module = this.$route.fullPath.split("/")[1];
       return module;
     },
+    showBackBtn() {
+      const names = ["check_duplicate_info"];
+      return names.includes(this.$route.name);
+    },
   },
   created() {
     if (this.user.passwordWeak) {

+ 33 - 4
src/modules/question/components/AuditQuestionWait.vue

@@ -38,10 +38,18 @@
         </el-table-column>
         <el-table-column label="修改时间" prop="updateTime" width="153">
         </el-table-column>
-        <el-table-column label="操作" width="170" fixed="right">
+        <el-table-column label="操作" width="100" fixed="right">
           <template slot-scope="scope">
             <div class="operate_left">
               <el-button
+                size="medium"
+                type="text"
+                class="normal"
+                @click="toDetail(scope.row)"
+                >审核</el-button
+              >
+
+              <!-- <el-button
                 size="medium"
                 type="text"
                 class="normal"
@@ -74,7 +82,7 @@
                     </el-button>
                   </el-dropdown-item>
                 </el-dropdown-menu>
-              </el-dropdown>
+              </el-dropdown> -->
             </div>
           </template>
         </el-table-column>
@@ -103,13 +111,16 @@
     <!-- QuestionPreviewDialog -->
     <question-preview-dialog
       ref="QuestionPreviewDialog"
-      :question="curQuestion"
+      :propQuestion="curQuestion"
+      @pass="questionPass"
+      @notPass="questionNotPass"
+      :table-data="tableData"
     ></question-preview-dialog>
   </div>
 </template>
 
 <script>
-import QuestionPreviewDialog from "./QuestionPreviewDialog.vue";
+import QuestionPreviewDialog from "./QuestionPreviewLoopDialog.vue";
 import AuditQuestionDialog from "./AuditQuestionDialog.vue";
 import { auditQuestionWaitPageListApi } from "../api";
 
@@ -129,10 +140,12 @@ export default {
       },
       loading: false,
       curQuestion: {},
+      tableData: [],
     };
   },
   mounted() {
     this.toPage(1);
+    this.getAllList();
   },
   methods: {
     toPage(page) {
@@ -150,6 +163,16 @@ export default {
       if (!res) return;
       this.dataList = res.data.content;
       this.total = res.data.totalElements;
+      this.$refs.QuestionPreviewDialog.cancel();
+    },
+    async getAllList() {
+      const res = await auditQuestionWaitPageListApi({
+        ...this.filter,
+        curPage: 1,
+        pageSize: 1000,
+      }).catch(() => {});
+      if (!res) return;
+      this.tableData = res.data.content;
     },
     handleSizeChange(val) {
       this.pageSize = val;
@@ -163,6 +186,12 @@ export default {
       this.curAuditInfo = { auditResult, questionIds: [questionId] };
       this.$refs.AuditQuestionDialog.open();
     },
+    questionPass(id) {
+      this.toAudit("PASS", id);
+    },
+    questionNotPass(id) {
+      this.toAudit("NOT_PASS", id);
+    },
   },
 };
 </script>

+ 16 - 2
src/modules/question/components/GptQuestionDialog.vue

@@ -10,16 +10,30 @@
       @opened="dialogOpened"
       @close="dialogClose"
     >
-      <div slot="title">
+      <!-- <div slot="title">
         <h2>
           AI命题 --<span
             >{{ formModel.courseName }}({{ formModel.courseCode }})</span
           >
         </h2>
+      </div> -->
+      <div slot="title" class="box-justify">
+        <div>
+          <el-button
+            class="is-back"
+            icon="el-icon-arrow-left"
+            @click="cancel"
+            size="mini"
+          ></el-button>
+          <h2>{{ "创建试题 - AI命题" }}</h2>
+          <span>课程代码:{{ formModel.courseCode }}</span>
+          <span>课程名称:{{ formModel.courseName }}</span>
+        </div>
+        <div></div>
       </div>
 
       <div class="part-box">
-        <h2 class="part-box-title">生成试题</h2>
+        <!-- <h2 class="part-box-title">生成试题</h2> -->
 
         <el-form class="margin-top-20" :model="formModel" label-width="100px">
           <el-form-item label="题型">

+ 16 - 2
src/modules/question/components/KnowledgePoints.vue

@@ -1,8 +1,12 @@
 <template>
   <div class="knowledge-points">
-    <el-button type="primary" @click="showDialog = true" class="choose"
+    <!-- <el-button type="primary" @click="showDialog = true" class="choose"
       >选择知识点</el-button
-    >
+    > -->
+    <div class="bind-knowledge" @click="showDialog = true">
+      <i class="el-icon-link" style="font-size: 16px"></i>
+      <span>绑定知识点</span>
+    </div>
 
     <el-dialog
       :visible.sync="showDialog"
@@ -177,6 +181,16 @@ export default {
 </script>
 <style lang="scss" scoped>
 .knowledge-points {
+  .bind-knowledge {
+    color: #6d5ff6;
+    display: inline-block;
+    vertical-align: middle;
+    cursor: pointer;
+    span {
+      font-size: 14px;
+      margin-left: 3px;
+    }
+  }
   :deep(.choose) {
     span {
       display: inline !important;

+ 1 - 1
src/modules/question/components/QuestionEditDialog.vue

@@ -17,7 +17,7 @@
           @click="cancel"
           size="mini"
         ></el-button>
-        <h2>{{ isEdit ? "编辑试题" : "创建试题" }}</h2>
+        <h2>{{ isEdit ? "编辑试题" : "创建试题 - 手动创建" }}</h2>
         <span>课程代码:{{ questionModel.courseCode }}</span>
         <span>课程名称:{{ questionModel.courseName }}</span>
       </div>

+ 229 - 0
src/modules/question/components/QuestionPreviewLoopDialog.vue

@@ -0,0 +1,229 @@
+<template>
+  <el-dialog
+    custom-class="question-preview-dialog edit-paper"
+    :visible.sync="modalIsShow"
+    title="试题预览"
+    width="1000px"
+    top="20px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+  >
+    <div v-if="modalIsShow" class="edit-part">
+      <div class="edit-cont">
+        <div class="edit-cont-title">
+          <rich-text :text-json="question.quesBody"></rich-text>
+        </div>
+        <div class="edit-cont-body">
+          <div
+            v-for="(quesOption, optionIndex) in question.quesOptions"
+            :key="optionIndex"
+            class="paper-option"
+          >
+            <span>{{ optionIndex | optionOrderWordFilter }}. </span>
+            <rich-text :text-json="quesOption.optionBody"></rich-text>
+          </div>
+          <div v-if="!isNested(question.questionType)" class="paper-answer">
+            <span>答案:</span>
+            <question-answer :data="question"></question-answer>
+          </div>
+        </div>
+        <div
+          v-if="!isNested(question.questionType)"
+          class="edit-cont-props"
+          style="margin-top: 10px"
+        >
+          <el-tag
+            v-for="(content, propIndex) in question.quesProperties"
+            :key="propIndex"
+            type="primary"
+            effect="dark"
+            style="margin-right: 5px; margin-bottom: 5px"
+          >
+            <!-- {{ content.courseProperty && content.courseProperty.name }}
+            <span style="margin: 0 3px">/</span> -->
+            {{ content.firstProperty && content.firstProperty.name }}
+            <span
+              v-if="content.secondProperty && content.secondProperty.name"
+              style="margin: 0 3px"
+              >/</span
+            >
+            {{ content.secondProperty && content.secondProperty.name }}
+          </el-tag>
+        </div>
+        <div
+          v-if="isNested(question.questionType)"
+          class="edit-paper-question-subs"
+        >
+          <div
+            v-for="(subQuestion, subIndex) in question.subQuestions"
+            :key="subIndex"
+            class="edit-part"
+          >
+            <div class="edit-cont">
+              <div class="edit-cont-title">
+                <span>{{ subIndex + 1 }}. </span>
+                <rich-text :text-json="subQuestion.quesBody"></rich-text>
+              </div>
+              <div class="edit-cont-body">
+                <template v-if="!isMatchingQuestion(question.questionType)">
+                  <div
+                    v-for="(
+                      subQuesOption, subOptIndex
+                    ) in subQuestion.quesOptions"
+                    :key="subOptIndex"
+                    class="paper-option"
+                  >
+                    <span>{{ subOptIndex | optionOrderWordFilter }}. </span>
+                    <rich-text
+                      :text-json="subQuesOption.optionBody"
+                    ></rich-text>
+                  </div>
+                </template>
+                <div class="paper-answer">
+                  <span>答案:</span>
+                  <question-answer :data="subQuestion"></question-answer>
+                </div>
+              </div>
+              <div class="edit-cont-props" style="margin-top: 10px">
+                <el-tag
+                  v-for="(content, propIndex) in subQuestion.quesProperties"
+                  :key="propIndex"
+                  type="primary"
+                  effect="dark"
+                  style="margin-right: 5px; margin-bottom: 5px"
+                >
+                  <!-- {{ content.courseProperty && content.courseProperty.name }}
+                  <span style="margin: 0 3px">/</span> -->
+                  {{ content.firstProperty && content.firstProperty.name }}
+                  <span
+                    v-if="content.secondProperty && content.secondProperty.name"
+                    style="margin: 0 3px"
+                    >/</span
+                  >
+                  {{ content.secondProperty && content.secondProperty.name }}
+                </el-tag>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div slot="footer" class="box-justify">
+      <div>
+        <el-button
+          type="default"
+          icon="el-icon-caret-left"
+          :disabled="prevDisabled"
+          @click="toPrev"
+        ></el-button>
+        <el-button
+          type="default"
+          icon="el-icon-caret-right"
+          :disabled="nextDisabled"
+          @click="toNext"
+        ></el-button>
+      </div>
+      <div>
+        <el-button
+          plain
+          class="maintain"
+          type="danger"
+          @click="$emit('notPass', question.id)"
+          >不通过</el-button
+        >
+        <el-button type="primary" @click="$emit('pass', question.id)"
+          >通过</el-button
+        >
+      </div>
+      <!-- <el-button @click="cancel">关闭</el-button> -->
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import QuestionAnswer from "./QuestionAnswer.vue";
+
+export default {
+  name: "QuestionPreviewLoopDialog",
+  components: { QuestionAnswer },
+  computed: {
+    prevDisabled() {
+      let id = this.propQuestion.id;
+      return this.tableData.findIndex((item) => item.id == id) == 0;
+    },
+    nextDisabled() {
+      let id = this.propQuestion.id;
+      return (
+        this.tableData.findIndex((item) => item.id == id) ==
+        this.tableData.length - 1
+      );
+    },
+  },
+  props: {
+    propQuestion: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    tableData: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      question: {},
+    };
+  },
+  watch: {
+    propQuestion(val) {
+      this.question = val;
+    },
+  },
+  methods: {
+    toPrev() {
+      let index = this.tableData.findIndex(
+        (item) => item.id == this.question.id
+      );
+      if (index != -1) {
+        this.question = this.tableData[index - 1];
+      }
+    },
+    toNext() {
+      let index = this.tableData.findIndex(
+        (item) => item.id == this.question.id
+      );
+      if (index != -1) {
+        this.question = this.tableData[index + 1];
+      }
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    isNested(questionType) {
+      const nestedQuestion = [
+        "PARAGRAPH_MATCHING",
+        "BANKED_CLOZE",
+        "CLOZE",
+        "READING_COMPREHENSION",
+        "LISTENING_QUESTION",
+      ];
+
+      return nestedQuestion.includes(questionType);
+    },
+    isMatchingQuestion(questionType) {
+      const typeQuestion = ["PARAGRAPH_MATCHING", "BANKED_CLOZE"];
+      return typeQuestion.includes(questionType);
+    },
+  },
+};
+</script>

+ 16 - 6
src/modules/questions/views/CheckDuplicateInfo.vue

@@ -1,6 +1,6 @@
 <template>
-  <div v-loading="loading" class="part-box">
-    <div class="part-box-header">
+  <div v-loading="loading">
+    <!-- <div class="part-box-header">
       <h1 class="part-box-title">试题详情</h1>
       <div>
         <el-button type="primary" icon="icon icon-save-white" @click="retain"
@@ -20,8 +20,8 @@
           >返回</el-button
         >
       </div>
-    </div>
-    <div class="part-page margin-tb-20">
+    </div> -->
+    <!-- <div class="part-page margin-tb-20">
       <el-button
         v-for="(city, index) in duplicateQuestions"
         :key="index"
@@ -31,7 +31,7 @@
         @click="selChange(index)"
         >{{ index + 1 }}</el-button
       >
-    </div>
+    </div> -->
     <el-row :gutter="20">
       <el-col :span="12">
         <QuestionInfo
@@ -44,7 +44,17 @@
           :question="duplicateQuestion"
           info-type="existed"
           style="height: 100%"
-        ></QuestionInfo>
+        >
+          <el-button
+            v-for="(city, index) in duplicateQuestions"
+            :key="index"
+            type="primary"
+            :plain="duplicateQuestionIndex !== index"
+            size="mini"
+            @click="selChange(index)"
+            >{{ index + 1 }}</el-button
+          >
+        </QuestionInfo>
       </el-col>
     </el-row>
   </div>

+ 188 - 123
src/modules/questions/views/QuestionInfo.vue

@@ -1,142 +1,158 @@
 <template>
-  <section class="question-info">
-    <el-form :model="quesModel" label-position="left" label-width="80px">
-      <el-form-item label="题目">
-        <rich-text
-          class="paper-question-body padding-top-6"
-          :text-json="quesModel.quesBody"
-        ></rich-text>
-      </el-form-item>
-      <el-form-item
-        v-for="(quesOption, optIndex) in quesModel.quesOptions"
-        :key="optIndex"
-      >
-        <div class="paper-question-option">
-          <span>{{ optIndex | optionOrderWordFilter }}. </span>
-          <rich-text :text-json="quesOption.optionBody"></rich-text>
+  <div class="question-info2" :class="{ new: infoType == 'new' }">
+    <div class="card-main">
+      <div class="title">{{ infoType === "new" ? "新导入" : "已入库" }}</div>
+      <div class="card-table">
+        <div class="tr">
+          <div class="td">题目</div>
+          <div class="td">
+            <rich-text
+              class="paper-question-body padding-top-6"
+              :text-json="quesModel.quesBody"
+            ></rich-text>
+          </div>
         </div>
-      </el-form-item>
-
-      <template v-if="quesModel.subQuestions && quesModel.subQuestions.length">
         <div
-          v-for="(subQuestionModel, qindex) in quesModel.subQuestions"
-          :key="`subq-${qindex}`"
-          class="sub-question"
+          class="tr"
+          v-for="(quesOption, optIndex) in quesModel.quesOptions"
+          :key="optIndex"
         >
-          <div class="sub-question-no">{{ qindex + 1 }}</div>
-          <el-form-item label="题目" label-width="50px">
-            <rich-text
-              class="paper-question-body"
-              :text-json="subQuestionModel.quesBody"
-            ></rich-text>
-          </el-form-item>
-          <template
-            v-if="
-              subQuestionModel.quesOptions &&
-              subQuestionModel.quesOptions.length
-            "
+          <div class="td">{{ optIndex | optionOrderWordFilter }}.</div>
+          <div class="td">
+            <rich-text :text-json="quesOption.optionBody"></rich-text>
+          </div>
+        </div>
+        <template
+          v-if="quesModel.subQuestions && quesModel.subQuestions.length"
+        >
+          <div
+            v-for="(subQuestionModel, qindex) in quesModel.subQuestions"
+            :key="`subq-${qindex}`"
           >
-            <el-form-item
-              v-for="(subQuesOption, subIndex) in subQuestionModel.quesOptions"
-              :key="subIndex"
-              label-width="50px"
+            <div class="tr" style="justify-content: flex-end">
+              <div class="td">{{ qindex + 1 }}.题目</div>
+              <div class="td">
+                <rich-text
+                  class="paper-question-body"
+                  :text-json="subQuestionModel.quesBody"
+                ></rich-text>
+              </div>
+            </div>
+            <template
+              v-if="
+                subQuestionModel.quesOptions &&
+                subQuestionModel.quesOptions.length
+              "
             >
-              <div class="paper-question-option">
-                <span>{{ subIndex | optionOrderWordFilter }}. </span>
-                <rich-text :text-json="subQuesOption.optionBody"></rich-text>
+              <div
+                class="tr"
+                v-for="(
+                  subQuesOption, subIndex
+                ) in subQuestionModel.quesOptions"
+                :key="subIndex"
+              >
+                <div class="td"></div>
+                <div class="td">
+                  <span>{{ subIndex | optionOrderWordFilter }}. </span>
+                  <rich-text :text-json="subQuesOption.optionBody"></rich-text>
+                </div>
               </div>
-            </el-form-item>
-          </template>
-          <el-form-item label="答案" label-width="50px">
+            </template>
+            <div class="tr" style="justify-content: flex-end">
+              <div class="td">答案</div>
+              <div class="td">
+                <question-answer
+                  class="paper-question-body"
+                  :data="subQuestionModel"
+                ></question-answer>
+              </div>
+            </div>
+          </div>
+        </template>
+        <div class="tr">
+          <div class="td">答案</div>
+          <div class="td">
             <question-answer
               class="paper-question-body"
               :data="subQuestionModel"
             ></question-answer>
-            <!-- <rich-text
-              class="paper-question-body"
-              :text-json="subQuestionModel.quesAnswer"
-            ></rich-text> -->
-          </el-form-item>
+          </div>
+        </div>
+        <div class="tr">
+          <div class="td">录入时间</div>
+          <div class="td">{{ quesModel.creationTime }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">题型</div>
+          <div class="td">{{ quesModel.questionType | questionType }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">预估难度</div>
+          <div class="td">{{ quesModel.difficulty || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">计算难度</div>
+          <div class="td">{{ quesModel.calculateDifficultyDegree || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">区分度</div>
+          <div class="td">{{ quesModel.discrimination || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">标准差</div>
+          <div class="td">{{ quesModel.std || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">信度</div>
+          <div class="td">{{ quesModel.reliability || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">差异系数</div>
+          <div class="td">{{ quesModel.cv || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">平均分值</div>
+          <div class="td">{{ quesModel.calculateAvgScore || "-" }}</div>
+        </div>
+        <div class="tr" v-if="infoType === 'existed'">
+          <div class="td">重复率</div>
+          <div class="td">{{ quesModel.duplicateRate || "-" }}</div>
+        </div>
+        <div class="tr">
+          <div class="td">试题关联知识点</div>
+          <div class="td">
+            <el-tag
+              v-for="(content, propIndex) in quesModel.quesProperties"
+              :key="propIndex"
+              type="primary"
+              effect="dark"
+              style="margin-right: 5px; margin-bottom: 5px"
+            >
+              {{ content.firstProperty && content.firstProperty.name }}
+              <span v-if="content.secondProperty" style="margin: 0 3px">/</span>
+              {{ content.secondProperty && content.secondProperty.name }}
+            </el-tag>
+          </div>
         </div>
-      </template>
-
-      <el-form-item
-        v-if="!quesModel.subQuestions || !quesModel.subQuestions.length"
-        label="答案"
-      >
-        <question-answer
-          class="paper-question-body padding-top-6"
-          :data="quesModel"
-        ></question-answer>
-      </el-form-item>
-
-      <div class="line-seperator"></div>
-
-      <el-form-item label="录入时间">
-        <span>{{ quesModel.creationTime }}</span>
-      </el-form-item>
-      <el-form-item label="题型">
-        <span>{{ quesModel.questionType | questionType }}</span>
-      </el-form-item>
-      <div class="box-justify">
-        <el-form-item label="预估难度">
-          <span>{{ quesModel.difficulty || "-" }}</span>
-        </el-form-item>
-        <el-form-item label="计算难度" style="width: 120px">
-          <span>{{ quesModel.calculateDifficultyDegree || "-" }}</span>
-        </el-form-item>
-      </div>
-      <div class="box-justify">
-        <el-form-item label="区分度">
-          <span>{{ quesModel.discrimination || "-" }}</span>
-        </el-form-item>
-        <el-form-item label="标准差" style="width: 120px">
-          <span>{{ quesModel.std || "-" }}</span>
-        </el-form-item>
       </div>
-      <div class="box-justify">
-        <el-form-item label="信度">
-          <span>{{ quesModel.reliability || "-" }}</span>
-        </el-form-item>
-        <el-form-item label="差异系数" style="width: 120px">
-          <span>{{ quesModel.cv || "-" }}</span>
-        </el-form-item>
+      <div
+        v-if="infoType === 'new'"
+        style="
+          padding: 10px 0;
+          display: flex;
+          align-items: center;
+          justify-content: flex-end;
+        "
+      >
+        <el-button type="danger" icon="el-icon-delete"></el-button>
+        <el-button type="primary" plain class="maintain">跳过</el-button>
+        <el-button type="primary">保留</el-button>
       </div>
-      <div class="box-justify">
-        <el-form-item label="平均分值">
-          <span>{{ quesModel.calculateAvgScore || "-" }}</span>
-        </el-form-item>
-        <el-form-item
-          v-if="infoType === 'existed'"
-          label="重复率"
-          style="width: 120px"
-        >
-          <span>{{ quesModel.duplicateRate || "-" }}</span>
-        </el-form-item>
+      <div v-else style="padding-top: 10px; text-align: right">
+        <slot />
       </div>
-
-      <div class="line-seperator"></div>
-
-      <el-form-item label="试题关联知识点" label-width="120px">
-        <el-tag
-          v-for="(content, propIndex) in quesModel.quesProperties"
-          :key="propIndex"
-          type="primary"
-          effect="dark"
-          style="margin-right: 5px; margin-bottom: 5px"
-        >
-          <!-- {{ content.courseProperty && content.courseProperty.name }}
-          <span style="margin: 0 3px">/</span> -->
-          {{ content.firstProperty && content.firstProperty.name }}
-          <span v-if="content.secondProperty" style="margin: 0 3px">/</span>
-          {{ content.secondProperty && content.secondProperty.name }}
-        </el-tag>
-      </el-form-item>
-    </el-form>
-    <div :class="['info-type', `info-type-${infoType}`]">
-      {{ infoType === "new" ? "新导入" : "已入库" }}
     </div>
-  </section>
+  </div>
 </template>
 <script>
 import { mapState } from "vuex";
@@ -197,3 +213,52 @@ export default {
   },
 };
 </script>
+<style lang="scss" scoped>
+.question-info2 {
+  background: #fff;
+  border-radius: 8px;
+  padding-top: 4px;
+  overflow: hidden;
+  &.new {
+    background: #6d5ff6;
+    .card-main {
+      .title {
+        color: #6d5ff6;
+      }
+    }
+  }
+  .card-main {
+    padding: 0 15px;
+    background: #fff;
+    padding-bottom: 15px;
+    .card-table {
+      border-top: 1px solid #e5e5e5;
+      border-left: 1px solid #e5e5e5;
+      .tr {
+        display: flex;
+
+        .td {
+          width: 122px;
+          padding: 10px;
+          border-bottom: 1px solid #e5e5e5;
+          border-right: 1px solid #e5e5e5;
+          &:first-child {
+            background: #f7f7f7;
+            display: flex;
+            align-items: center;
+          }
+          &:last-child {
+            flex: 1;
+          }
+        }
+      }
+    }
+    .title {
+      height: 52px;
+      line-height: 52px;
+      font-size: 16px;
+      color: #262626;
+    }
+  }
+}
+</style>

+ 199 - 0
src/modules/questions/views/QuestionInfoOld.vue

@@ -0,0 +1,199 @@
+<template>
+  <section class="question-info">
+    <el-form :model="quesModel" label-position="left" label-width="80px">
+      <el-form-item label="题目">
+        <rich-text
+          class="paper-question-body padding-top-6"
+          :text-json="quesModel.quesBody"
+        ></rich-text>
+      </el-form-item>
+      <el-form-item
+        v-for="(quesOption, optIndex) in quesModel.quesOptions"
+        :key="optIndex"
+      >
+        <div class="paper-question-option">
+          <span>{{ optIndex | optionOrderWordFilter }}. </span>
+          <rich-text :text-json="quesOption.optionBody"></rich-text>
+        </div>
+      </el-form-item>
+
+      <template v-if="quesModel.subQuestions && quesModel.subQuestions.length">
+        <div
+          v-for="(subQuestionModel, qindex) in quesModel.subQuestions"
+          :key="`subq-${qindex}`"
+          class="sub-question"
+        >
+          <div class="sub-question-no">{{ qindex + 1 }}</div>
+          <el-form-item label="题目" label-width="50px">
+            <rich-text
+              class="paper-question-body"
+              :text-json="subQuestionModel.quesBody"
+            ></rich-text>
+          </el-form-item>
+          <template
+            v-if="
+              subQuestionModel.quesOptions &&
+              subQuestionModel.quesOptions.length
+            "
+          >
+            <el-form-item
+              v-for="(subQuesOption, subIndex) in subQuestionModel.quesOptions"
+              :key="subIndex"
+              label-width="50px"
+            >
+              <div class="paper-question-option">
+                <span>{{ subIndex | optionOrderWordFilter }}. </span>
+                <rich-text :text-json="subQuesOption.optionBody"></rich-text>
+              </div>
+            </el-form-item>
+          </template>
+          <el-form-item label="答案" label-width="50px">
+            <question-answer
+              class="paper-question-body"
+              :data="subQuestionModel"
+            ></question-answer>
+            <!-- <rich-text
+              class="paper-question-body"
+              :text-json="subQuestionModel.quesAnswer"
+            ></rich-text> -->
+          </el-form-item>
+        </div>
+      </template>
+
+      <el-form-item
+        v-if="!quesModel.subQuestions || !quesModel.subQuestions.length"
+        label="答案"
+      >
+        <question-answer
+          class="paper-question-body padding-top-6"
+          :data="quesModel"
+        ></question-answer>
+      </el-form-item>
+
+      <div class="line-seperator"></div>
+
+      <el-form-item label="录入时间">
+        <span>{{ quesModel.creationTime }}</span>
+      </el-form-item>
+      <el-form-item label="题型">
+        <span>{{ quesModel.questionType | questionType }}</span>
+      </el-form-item>
+      <div class="box-justify">
+        <el-form-item label="预估难度">
+          <span>{{ quesModel.difficulty || "-" }}</span>
+        </el-form-item>
+        <el-form-item label="计算难度" style="width: 120px">
+          <span>{{ quesModel.calculateDifficultyDegree || "-" }}</span>
+        </el-form-item>
+      </div>
+      <div class="box-justify">
+        <el-form-item label="区分度">
+          <span>{{ quesModel.discrimination || "-" }}</span>
+        </el-form-item>
+        <el-form-item label="标准差" style="width: 120px">
+          <span>{{ quesModel.std || "-" }}</span>
+        </el-form-item>
+      </div>
+      <div class="box-justify">
+        <el-form-item label="信度">
+          <span>{{ quesModel.reliability || "-" }}</span>
+        </el-form-item>
+        <el-form-item label="差异系数" style="width: 120px">
+          <span>{{ quesModel.cv || "-" }}</span>
+        </el-form-item>
+      </div>
+      <div class="box-justify">
+        <el-form-item label="平均分值">
+          <span>{{ quesModel.calculateAvgScore || "-" }}</span>
+        </el-form-item>
+        <el-form-item
+          v-if="infoType === 'existed'"
+          label="重复率"
+          style="width: 120px"
+        >
+          <span>{{ quesModel.duplicateRate || "-" }}</span>
+        </el-form-item>
+      </div>
+
+      <div class="line-seperator"></div>
+
+      <el-form-item label="试题关联知识点" label-width="120px">
+        <el-tag
+          v-for="(content, propIndex) in quesModel.quesProperties"
+          :key="propIndex"
+          type="primary"
+          effect="dark"
+          style="margin-right: 5px; margin-bottom: 5px"
+        >
+          <!-- {{ content.courseProperty && content.courseProperty.name }}
+          <span style="margin: 0 3px">/</span> -->
+          {{ content.firstProperty && content.firstProperty.name }}
+          <span v-if="content.secondProperty" style="margin: 0 3px">/</span>
+          {{ content.secondProperty && content.secondProperty.name }}
+        </el-tag>
+      </el-form-item>
+    </el-form>
+    <div :class="['info-type', `info-type-${infoType}`]">
+      {{ infoType === "new" ? "新导入" : "已入库" }}
+    </div>
+  </section>
+</template>
+<script>
+import { mapState } from "vuex";
+import QuestionAnswer from "../../question/components/QuestionAnswer.vue";
+
+export default {
+  components: { QuestionAnswer },
+  props: {
+    question: {
+      type: Object,
+      default: () => {},
+    },
+    infoType: {
+      type: String,
+      default: "new",
+    },
+  },
+  data() {
+    return { quesModel: this.question };
+  },
+  computed: {
+    ...mapState({ user: (state) => state.user }),
+  },
+  watch: {
+    question: {
+      immediate: false,
+      handler(val) {
+        this.quesModel = val;
+      },
+    },
+  },
+  //初始化查询
+  created() {},
+  methods: {
+    isMatchingQuestion(questionType) {
+      if (
+        questionType == "PARAGRAPH_MATCHING" ||
+        questionType == "BANKED_CLOZE"
+      ) {
+        return true;
+      } else {
+        return false;
+      }
+    },
+    isNested(questionType) {
+      if (
+        questionType == "PARAGRAPH_MATCHING" ||
+        questionType == "BANKED_CLOZE" ||
+        questionType == "CLOZE" ||
+        questionType == "READING_COMPREHENSION" ||
+        questionType == "LISTENING_QUESTION"
+      ) {
+        return true;
+      } else {
+        return false;
+      }
+    },
+  },
+};
+</script>