Selaa lähdekoodia

试卷编辑页

zhangjie 2 vuotta sitten
vanhempi
commit
5d7c821ec6

+ 17 - 8
src/assets/styles/pages.scss

@@ -296,6 +296,12 @@
     flex-grow: 2;
     overflow: hidden;
 
+    &:hover {
+      > .edit-cont-action {
+        display: block;
+      }
+    }
+
     &-title {
       min-height: 42px;
       line-height: 20px;
@@ -325,6 +331,7 @@
       z-index: 8;
       padding: 0 30px;
       text-align: right;
+      display: none;
     }
 
     &-body {
@@ -918,14 +925,16 @@
 // build-paper
 .build-paper {
   .part-box-header {
-    h1.part-box-title {
-      display: inline-block;
-      vertical-align: middle;
-    }
-    span {
-      display: inline-block;
-      vertical-align: middle;
-      margin-left: 15px;
+    .part-box-header-left {
+      h1 {
+        display: inline-block;
+        vertical-align: middle;
+      }
+      span {
+        display: inline-block;
+        vertical-align: middle;
+        margin-left: 15px;
+      }
     }
   }
 

+ 47 - 0
src/modules/paper/api.js

@@ -23,3 +23,50 @@ import folderPropStruct from "./datas/folderPropStruct.json";
 export const questionGroupStructListApi = (datas) => {
   return Promise.resolve({ data: folderPropStruct, filter: datas });
 };
+
+// edit paper
+export const paperDetailInfoApi = (paperId) => {
+  return $httpWithMsg.post(`${QUESTION_API}/paper/${paperId}`, {});
+};
+export const paperSaveApi = (paper) => {
+  return $httpWithMsg.post(`${QUESTION_API}/paper`, paper);
+};
+export const paperDeleteApi = (paperId) => {
+  return $httpWithMsg.delete(`${QUESTION_API}/paper/${paperId}`, {});
+};
+
+// paper-info
+export const paperAuditInfoApi = ({ paperId, curPage, pageSize }) => {
+  return $httpWithMsg.get(
+    `${QUESTION_API}/paper/audit/page/${curPage}/${pageSize}`,
+    {
+      params: {
+        paperId,
+      },
+    }
+  );
+};
+export const paperBlueInfoApi = ({ paperId, coursePropertyId, rootOrgId }) => {
+  return $httpWithMsg.get(`${QUESTION_API}/paper/blue`, {
+    params: {
+      id: paperId,
+      coursePropertyId,
+      rootOrgId,
+    },
+  });
+};
+export const paperQtypeInfoApi = ({ paperId, type }) => {
+  return $httpWithMsg.get(`${QUESTION_API}/paper/question/type`, {
+    params: {
+      id: paperId,
+      type,
+    },
+  });
+};
+export const paperBaseInfoApi = ({ paperId }) => {
+  return $httpWithMsg.get(`${QUESTION_API}/paper/basic/composition`, {
+    params: {
+      id: paperId,
+    },
+  });
+};

+ 83 - 0
src/modules/paper/components/PaperAuditInfo.vue

@@ -0,0 +1,83 @@
+<template>
+  <el-dialog
+    title="审核记录"
+    width="700px"
+    :visible.sync="modalIsShow"
+    :modal="false"
+    append-to-body
+    custom-class="side-dialog"
+    @open="toPage(1)"
+  >
+    <div class="part-box-border">
+      <el-table :data="tableData">
+        <el-table-column
+          prop="operateUserName"
+          label="执行人"
+        ></el-table-column>
+        <el-table-column prop="operateTime" label="执行时间"></el-table-column>
+        <el-table-column prop="operate" label="执行事项"></el-table-column>
+        <el-table-column prop="auditRemark" label="审核意见"></el-table-column>
+      </el-table>
+    </div>
+    <div class="part-page">
+      <el-pagination
+        :current-page="currentPage"
+        :page-size="pageSize"
+        :page-sizes="[10, 20, 50, 100, 200, 300]"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        @current-change="toPage"
+        @size-change="handleSizeChange"
+      ></el-pagination>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { paperAuditInfoApi } from "../api";
+
+export default {
+  name: "PaperAuditInfo",
+  props: {
+    paperId: {
+      type: [String, Number],
+      default: "",
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      tableData: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 0,
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getList() {
+      const res = await paperAuditInfoApi({
+        paperId: this.paperId,
+        curPage: this.currentPage,
+        pageSize: this.pageSize,
+      }).catch(() => {});
+      if (!res) return;
+      this.tableData = res.data.content;
+      this.total = res.data.totalElements;
+    },
+    toPage(page) {
+      this.currentPage = page;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.toPage(1);
+    },
+  },
+};
+</script>

+ 78 - 0
src/modules/paper/components/PaperBaseInfo.vue

@@ -0,0 +1,78 @@
+<template>
+  <el-dialog
+    title="基础构成"
+    width="100%"
+    :visible.sync="modalIsShow"
+    :modal="false"
+    append-to-body
+    custom-class="side-dialog"
+    @open="getData"
+  >
+    <el-form>
+      <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-dialog>
+</template>
+
+<script>
+import { paperBaseInfoApi } from "../api";
+
+export default {
+  name: "PaperBaseInfo",
+  props: {
+    paperId: {
+      type: String,
+      default: "",
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      paperData: {
+        tags: [],
+        head: [],
+      },
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getData() {
+      const res = await paperBaseInfoApi(this.paperId);
+      this.paperData = res.data;
+    },
+  },
+};
+</script>

+ 121 - 0
src/modules/paper/components/PaperBlueInfo.vue

@@ -0,0 +1,121 @@
+<template>
+  <el-dialog
+    title="蓝图分布"
+    width="100%"
+    :visible.sync="modalIsShow"
+    :modal="false"
+    append-to-body
+    custom-class="side-dialog"
+    @open="visibleChange"
+  >
+    <el-form>
+      <el-form-item label="可选属性">
+        <property-select
+          v-model="coursePropertyId"
+          :course-id="courseId"
+          @change="getPaperData"
+        >
+        </property-select>
+      </el-form-item>
+    </el-form>
+    <el-table
+      :data="paperData.data"
+      style="width: 100%"
+      border
+      :span-method="objectSpanMethod"
+    >
+      <el-table-column label="蓝图属性" align="center">
+        <el-table-column
+          v-for="(colval, colIndex) in headFirst"
+          :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 headSecond"
+          :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-dialog>
+</template>
+
+<script>
+import { paperBlueInfoApi } from "../api";
+
+export default {
+  name: "PaperBlueInfo",
+  props: {
+    paperId: {
+      type: [String, Number],
+      default: "",
+    },
+    courseId: {
+      type: [String, Number],
+      default: null,
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      coursePropertyId: "",
+      paperData: { head: [] },
+      headFirst: [],
+      headSecond: [],
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.getPaperData();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getPaperData() {
+      if (!this.coursePropertyId) return;
+      const res = await paperBlueInfoApi({
+        paperId: this.paperId,
+        courseId: this.courseId,
+        coursePropertyId: this.coursePropertyId,
+      });
+      this.paperData = res.data;
+      this.headFirst = this.paperData.head.slice(0, 2);
+      this.headSecond = this.paperData.head.slice(2);
+    },
+    objectSpanMethod({ 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>

+ 119 - 0
src/modules/paper/components/PaperQuestypeInfo.vue

@@ -0,0 +1,119 @@
+<template>
+  <el-dialog
+    title="题型分布"
+    width="100%"
+    :visible.sync="modalIsShow"
+    :modal="false"
+    append-to-body
+    custom-class="side-dialog"
+    @open="visibleChange"
+  >
+    <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-table :data="paperData.data" border :span-method="objectSpanMethod">
+      <el-table-column label="题型" align="center">
+        <el-table-column
+          v-for="(colval, colIndex) in headFirst"
+          :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 headSecond"
+          :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-dialog>
+</template>
+
+<script>
+import { paperQtypeInfoApi } from "../api";
+
+export default {
+  name: "PaperQuestypeInfo",
+  props: {
+    paperId: {
+      type: String,
+      default: "",
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      type: "count",
+      paperData: { head: [] },
+      headFirst: [],
+      headSecond: [],
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.getPaperData();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getPaperData() {
+      const res = await paperQtypeInfoApi({
+        paperId: this.paperId,
+        type: this.type,
+      });
+      this.paperData = res.data;
+      this.headFirst = this.paperData.head.slice(0, 2);
+      this.headSecond = this.paperData.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,
+        };
+      }
+    },
+  },
+};
+</script>

+ 1 - 1
src/modules/paper/views/BuildPaper.vue

@@ -2,7 +2,7 @@
   <div class="build-paper">
     <div class="part-box">
       <div class="part-box-header">
-        <div>
+        <div class="part-box-header-left">
           <h1 class="part-box-title">组卷</h1>
           <span>课程代码:{{ modalForm.courseCode }}</span>
           <span>课程名称:{{ modalForm.courseName }}</span>

+ 698 - 0
src/modules/paper/views/EditPaper.vue

@@ -0,0 +1,698 @@
+<template>
+  <div class="edit-paper">
+    <div class="edit-header">
+      <div class="edit-header-top box-justify">
+        <div class="header-info">
+          <div class="header-info-item">
+            <span>课程代码:</span>
+            <span>{{ paper.course.code }}</span>
+          </div>
+          <div class="header-info-item">
+            <span>课程名称:</span>
+            <span>{{ paper.course.name }}</span>
+          </div>
+          <div class="header-info-item">
+            <span>试卷名称:</span>
+            <span>
+              <el-tooltip class="item" effect="dark" placement="top-start">
+                <div slot="content">{{ paper.name }}</div>
+                <el-input
+                  v-model="paper.name"
+                  size="mini"
+                  class="header-info-input"
+                  placeholder="试卷名称"
+                ></el-input>
+              </el-tooltip>
+            </span>
+          </div>
+          <div class="header-info-item">
+            <span>试卷标题:</span>
+            <span>
+              <el-tooltip class="item" effect="dark" placement="top-start">
+                <div slot="content">{{ paper.title }}</div>
+                <el-input
+                  v-model="paper.title"
+                  size="mini"
+                  class="header-info-input"
+                  placeholder="试卷标题"
+                ></el-input>
+              </el-tooltip>
+            </span>
+          </div>
+          <div class="header-info-item">
+            <span>试卷总分:</span>
+            <span>{{ paper.totalScore }}</span>
+          </div>
+        </div>
+        <div class="header-btns">
+          <el-button type="primary" size="small" @click="toSavePaper">
+            保存
+          </el-button>
+          <el-button
+            type="danger"
+            plain
+            size="small"
+            @click="toDeletePaper(paper.id)"
+          >
+            删除
+          </el-button>
+          <el-button
+            v-if="checkDuplicateBtnShow"
+            type="primary"
+            size="small"
+            plain
+            @click="toCheckDuplicate"
+          >
+            进入查重
+          </el-button>
+          <el-button
+            size="small"
+            type="primary"
+            plain
+            @click="toExportPaperAnswer"
+            >导出答案</el-button
+          >
+          <el-button
+            size="small"
+            type="danger"
+            plain
+            icon="icon icon-back"
+            @click="toBack"
+            >返回</el-button
+          >
+        </div>
+      </div>
+      <div class="edit-header-bottom box-justify">
+        <div>
+          <el-button type="info" size="small" @click="toViewBaseInfo">
+            基础构成
+          </el-button>
+          <el-button type="info" size="small" @click="toViewQuestypeInfo">
+            题型分布
+          </el-button>
+          <el-button type="info" size="small" @click="toViewBlueInfo">
+            蓝图分布
+          </el-button>
+          <el-button type="info" size="small" @click="toViewAuditInfo">
+            审核记录
+          </el-button>
+          <el-button
+            v-if="enableCardEdit"
+            type="info"
+            size="small"
+            @click="toEditCard"
+          >
+            编辑题卡
+          </el-button>
+        </div>
+        <div>
+          <el-button
+            type="primary"
+            size="small"
+            plain
+            @click="toSwitchQuesTagShowHide"
+          >
+            {{ quesTagShow ? "隐藏" : "显示" }}属性
+          </el-button>
+          <el-button
+            type="primary"
+            size="small"
+            plain
+            @click="toSwitchQuesAnswerShowHide"
+          >
+            {{ quesAnswerShow ? "隐藏" : "显示" }}答案
+          </el-button>
+        </div>
+      </div>
+    </div>
+
+    <div class="edit-body">
+      <!-- 考试说明 -->
+      <div class="edit-part-list">
+        <div class="edit-part">
+          <div class="edit-cont">
+            <div class="edit-cont-title">
+              <h3>考试说明</h3>
+            </div>
+            <div class="edit-cont-action">
+              <el-button
+                type="primary"
+                plain
+                size="small"
+                @click="openEditExamPaperRemark"
+                >编辑</el-button
+              >
+            </div>
+            <div class="edit-cont-body">
+              <rich-text :text-json="paper.examRemark"></rich-text>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 循环大题 -->
+      <div
+        v-for="(paperDetail, detailIndex) in paper.paperDetails"
+        v-show="paperDetailShow(paperDetail)"
+        :key="detailIndex"
+        class="edit-part-list"
+      >
+        <div class="edit-part">
+          <div class="edit-cont">
+            <div class="edit-cont-title">
+              <h3>
+                <span>{{ paperDetail.cnNum }}</span> <span>.</span>
+                <span>{{ paperDetail.name }}</span>
+                <span>
+                  ({{
+                    !paperDetail.title ? "本大题" : paperDetail.title + ","
+                  }}共{{ paperDetail.unitCount }}小题,满分{{
+                    paperDetail.score
+                  }}分)
+                </span>
+              </h3>
+            </div>
+            <rich-text
+              class="edit-cont-body"
+              :text-json="paperDetail.description"
+            ></rich-text>
+            <div class="edit-cont-action">
+              <el-button
+                v-show="parentView == 'gen_paper'"
+                size="small"
+                type="primary"
+                plain
+                @click="selectQues(paperDetail.id)"
+                >选题
+              </el-button>
+              <el-button
+                size="small"
+                type="primary"
+                plain
+                @click="openEditPaperDetail(paperDetail)"
+                >编辑
+              </el-button>
+              <el-button
+                v-if="showUp(paperDetail)"
+                size="small"
+                type="primary"
+                plain
+                @click="movePaperDetail(paperDetail, 'up')"
+                >上移
+              </el-button>
+              <el-button
+                v-if="showDown(paperDetail)"
+                size="small"
+                type="primary"
+                plain
+                @click="movePaperDetail(paperDetail, 'down')"
+                >下移
+              </el-button>
+              <el-button
+                size="small"
+                type="danger"
+                @click="deletePaperDetail(paperDetail.id)"
+                >删除
+              </el-button>
+              <el-button
+                v-show="showButtons[detailIndex].up"
+                size="small"
+                type="primary"
+                plain
+                icon="el-icon-arrow-up"
+                @click.stop="hideContent(detailIndex)"
+              ></el-button>
+              <el-button
+                v-show="!showButtons[detailIndex].up"
+                size="small"
+                icon="el-icon-arrow-down"
+                type="primary"
+                plain
+                @click.stop="showContent(detailIndex)"
+              ></el-button>
+            </div>
+          </div>
+          <div v-show="quesTagShow" class="edit-property">
+            <div class="edit-property-box">
+              <div
+                v-for="(paperDetailTag, tagIndex) in paperDetail.tags"
+                :key="tagIndex"
+                class="edit-property-item"
+              >
+                <div class="edit-property-body edit-property-danger">
+                  <div class="edit-property-title">
+                    {{ paperDetailTag.tag }}
+                  </div>
+                  <div class="edit-property-content">
+                    {{ paperDetailTag.content }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <!-- 循环小题 -->
+        <div
+          v-show="showQuestions[detailIndex].is_show"
+          class="edit-paper-questions"
+        >
+          <template
+            v-for="(paperDetailUnit, unitIndex) in paperDetail.paperDetailUnits"
+          >
+            <div
+              v-show="quesShow(paperDetailUnit.id)"
+              :key="`question-${unitIndex}`"
+              :class="[
+                'edit-part',
+                {
+                  'question-duplicate':
+                    paperDetailUnit.question.checkDuplicateStatus ==
+                    'TO_BE_DISPOSE',
+                },
+              ]"
+            >
+              <div class="edit-cont">
+                <div class="edit-cont-title">
+                  <span>{{ paperDetailUnit.number }}.</span>
+                  <rich-text
+                    :text-json="paperDetailUnit.question.quesBody"
+                  ></rich-text>
+                  <span> ({{ paperDetailUnit.score }}分) </span>
+                </div>
+                <div class="edit-cont-body">
+                  <div
+                    v-for="(quesOption, optionIndex) in paperDetailUnit.question
+                      .quesOptions"
+                    :key="optionIndex"
+                    class="paper-option"
+                  >
+                    <span>{{ optionIndex | optionOrderWordFilter }}. </span>
+                    <rich-text :text-json="quesOption.optionBody"></rich-text>
+                  </div>
+                  <div v-if="!isNested(paperDetailUnit.questionType)">
+                    <div v-show="quesAnswerShow" class="paper-answer">
+                      <span>答案:</span>
+                      <question-answer
+                        :data="paperDetailUnit.question"
+                      ></question-answer>
+                    </div>
+                  </div>
+                </div>
+                <div class="edit-cont-action">
+                  <span class="tips-info">
+                    {{ paperDetailUnit.question.bodyLengthText }}
+                  </span>
+                  <el-button
+                    v-if="
+                      paperDetailUnit.question.checkDuplicateStatus ===
+                      'TO_BE_DISPOSE'
+                    "
+                    size="small"
+                    type="primary"
+                    plain
+                    @click="checkDuplicateQuestion(paperDetailUnit.question.id)"
+                    >进入查重
+                  </el-button>
+                  <el-button
+                    size="small"
+                    type="primary"
+                    plain
+                    @click="editQues(paperDetailUnit, paperDetailUnit.question)"
+                    >编辑
+                  </el-button>
+                  <el-button
+                    v-if="showUnitUp(paperDetail, paperDetailUnit.id)"
+                    size="small"
+                    type="primary"
+                    plain
+                    @click="
+                      movePaperDetailUnit(
+                        paperDetail.id,
+                        paperDetailUnit.id,
+                        'up'
+                      )
+                    "
+                    >上移
+                  </el-button>
+                  <el-button
+                    v-if="showUnitDown(paperDetail, paperDetailUnit.id)"
+                    size="small"
+                    type="primary"
+                    plain
+                    @click="
+                      movePaperDetailUnit(
+                        paperDetail.id,
+                        paperDetailUnit.id,
+                        'down'
+                      )
+                    "
+                    >下移
+                  </el-button>
+                  <el-button
+                    type="danger"
+                    size="small"
+                    @click="deleteQues(paperDetailUnit)"
+                    >删除
+                  </el-button>
+                  <el-button
+                    v-show="
+                      isNested(paperDetailUnit.questionType) &&
+                      showSubButtons[detailIndex + '-' + unitIndex]
+                    "
+                    size="small"
+                    icon="el-icon-arrow-up"
+                    @click.stop="hideSubContent(detailIndex + '-' + unitIndex)"
+                  ></el-button>
+                  <el-button
+                    v-show="
+                      isNested(paperDetailUnit.questionType) &&
+                      !showSubButtons[detailIndex + '-' + unitIndex]
+                    "
+                    size="small"
+                    type="primary"
+                    plain
+                    icon="el-icon-arrow-down"
+                    @click.stop="showSubContent(detailIndex + '-' + unitIndex)"
+                  ></el-button>
+                </div>
+              </div>
+              <div v-show="quesTagShow" class="edit-property">
+                <div class="edit-property-box">
+                  <div
+                    v-for="(questionTag, tagIndex) in paperDetailUnit.question
+                      .tags"
+                    :key="tagIndex"
+                    class="edit-property-item"
+                  >
+                    <div class="edit-property-body">
+                      <div class="edit-property-title">
+                        {{ questionTag.tag }}
+                      </div>
+                      <div class="edit-property-content">
+                        {{ questionTag.content }}
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div
+              v-show="showSubQuestions[detailIndex + '-' + unitIndex]"
+              :key="`question-sub-${unitIndex}`"
+              class="edit-paper-question-subs"
+            >
+              <div
+                v-for="(subQuestion, subIndex) in paperDetailUnit.question
+                  .subQuestions"
+                v-show="quesShow(subQuestion.id)"
+                :key="subIndex"
+                class="edit-part"
+              >
+                <div class="edit-cont">
+                  <div class="edit-cont-title">
+                    <span>{{ subQuestion.subNumber }}. </span>
+                    <rich-text :text-json="subQuestion.quesBody"></rich-text>
+                    <span
+                      >({{ paperDetailUnit.subScoreList[subIndex] }}分)</span
+                    >
+                  </div>
+                  <div
+                    v-if="!isMatchingQuestion(paperDetailUnit.questionType)"
+                    class="edit-cont-body"
+                  >
+                    <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>
+                  </div>
+                  <div v-show="quesAnswerShow" class="paper-answer">
+                    <span>答案:</span>
+                    <question-answer :data="subQuestion"></question-answer>
+                    <!-- <rich-text :text-json="subQuestion.quesAnswer"></rich-text> -->
+                  </div>
+                  <div class="edit-cont-action">
+                    <el-button
+                      size="small"
+                      type="primary"
+                      plain
+                      @click="editQues(paperDetailUnit, subQuestion)"
+                      >编辑
+                    </el-button>
+                    <el-button
+                      v-if="showUnitSubUp(paperDetailUnit, subQuestion.id)"
+                      size="small"
+                      type="primary"
+                      plain
+                      @click="
+                        movePaperDetailUnitSub(
+                          paperDetailUnit.id,
+                          subQuestion.id,
+                          'up'
+                        )
+                      "
+                      >上移
+                    </el-button>
+                    <el-button
+                      v-if="showUnitSubDown(paperDetailUnit, subQuestion.id)"
+                      size="small"
+                      type="primary"
+                      plain
+                      @click="
+                        movePaperDetailUnitSub(
+                          paperDetailUnit.id,
+                          subQuestion.id,
+                          'down'
+                        )
+                      "
+                      >下移
+                    </el-button>
+                  </div>
+                </div>
+                <div v-show="quesTagShow" class="edit-property">
+                  <div class="edit-property-box">
+                    <div
+                      v-for="(subQuestionTag, tagIndex) in subQuestion.tags"
+                      :key="tagIndex"
+                      class="edit-property-item"
+                    >
+                      <div class="edit-property-body">
+                        <div class="edit-property-title">
+                          {{ subQuestionTag.tag }}
+                        </div>
+                        <div class="edit-property-content">
+                          {{ subQuestionTag.content }}
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </template>
+        </div>
+      </div>
+    </div>
+
+    <!-- 基础构成 -->
+    <paper-base-info ref="PaperBaseInfo" :paper-id="paperId"></paper-base-info>
+    <!-- 题型分布 -->
+    <paper-questype-info
+      ref="PaperQuestypeInfo"
+      :paper-id="paperId"
+    ></paper-questype-info>
+    <!-- 蓝图分布 -->
+    <paper-blue-info
+      ref="PaperBlueInfo"
+      :paper-id="paperId"
+      :course-id="paper.course.id"
+    ></paper-blue-info>
+    <!-- 审核记录 -->
+    <paper-audit-info
+      ref="PaperAuditInfo"
+      :paper-id="paperId"
+    ></paper-audit-info>
+  </div>
+</template>
+
+<script>
+import { paperDetailInfoApi, paperSaveApi, paperDeleteApi } from "../api";
+import { QUESTION_API } from "@/constants/constants";
+
+import PaperBaseInfo from "../components/PaperBaseInfo.vue";
+import PaperQuestypeInfo from "../components/PaperQuestypeInfo.vue";
+import PaperBlueInfo from "../components/PaperBlueInfo.vue";
+import PaperAuditInfo from "../components/PaperAuditInfo.vue";
+
+export default {
+  name: "EditPaper",
+  components: {
+    PaperBaseInfo,
+    PaperQuestypeInfo,
+    PaperAuditInfo,
+    PaperBlueInfo,
+  },
+  data() {
+    return {
+      paperId: "",
+      parentView: "",
+      paper: {
+        name: "",
+        title: "",
+        totalScore: 0,
+        course: {
+          code: "",
+          name: "",
+        },
+        examRemark: "",
+        paperDetails: [],
+      },
+      checkDuplicateBtnShow: false,
+      quesTagShow: false,
+      quesAnswerShow: false,
+    };
+  },
+  computed: {
+    user() {
+      return this.$store.state.user;
+    },
+    enableCardEdit() {
+      return (
+        this.paper.auditStatus === "PASS" && this.paper.paperType === "GENERATE"
+      );
+    },
+  },
+  created() {
+    let qt = sessionStorage.getItem("quesTagShow");
+    if (qt) {
+      this.quesTagShow = qt === "true";
+    }
+    let qa = sessionStorage.getItem("quesAnswerShow");
+    if (qa) {
+      this.quesAnswerShow = qa === "true";
+    }
+    this.paperId = Number(this.$route.params.id);
+    this.parentView = this.$route.params.parentView;
+    this.initPaper();
+  },
+  methods: {
+    async initPaper() {
+      const res = await paperDetailInfoApi(this.paperId);
+      res.data.paperDetails.forEach((detail) => {
+        detail.showQuestions = true;
+        detail.paperDetailUnits.forEach((question) => {
+          question.showSubQuestions = true;
+        });
+      });
+      this.paper = res.data;
+      this.showCheckDuplicate();
+    },
+    // header-actions
+    showCheckDuplicate() {
+      if (this.paper.checkDuplicateStatus === "DISPOSED") {
+        this.checkDuplicateBtnShow = false;
+        return;
+      }
+
+      this.checkDuplicateBtnShow = this.paper.paperDetails.some((detail) =>
+        detail.paperDetailUnits.some(
+          (question) =>
+            question.question.checkDuplicateStatus === "TO_BE_DISPOSE"
+        )
+      );
+    },
+    toCheckDuplicate() {
+      this.$router.push({
+        name: "check_duplicate_info",
+        query: {
+          basePaperId: this.paper.id,
+          from: "paper",
+        },
+      });
+    },
+    // 保存试卷
+    async toSavePaper() {
+      const res = await paperSaveApi(this.paper).catch((error) => {
+        this.$notify({
+          type: "error",
+          message: error.response.data.desc,
+        });
+      });
+
+      if (!res) return;
+      this.$message.success("保存成功!");
+    },
+    // 删除试卷
+    async toDeletePaper() {
+      const confirm = await this.$confirm(`确定要删除该试卷吗?`, "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      const res = await paperDeleteApi(this.paper).catch((error) => {
+        this.$notify({
+          type: "error",
+          message: error.response.data.desc,
+        });
+      });
+
+      if (!res) return;
+      this.$message.success("删除成功!");
+      window.history.go(-1);
+      this.toBack();
+    },
+    // 导出答案
+    toExportPaperAnswer() {
+      const { key, token } = this.user;
+      const url = `${QUESTION_API}/paper/answer/export/${this.paperId}?$key=${key}&$token=${token}`;
+      window.open(url);
+    },
+    toBack() {
+      window.history.go(-1);
+    },
+    // 显示/隐藏答案
+    toSwitchQuesAnswerShowHide() {
+      this.quesAnswerShow = !this.quesAnswerShow;
+      sessionStorage.setItem("quesAnswerShow", this.quesAnswerShow);
+    },
+    // 显示/隐藏属性
+    toSwitchQuesTagShowHide() {
+      this.quesTagShow = !this.quesTagShow;
+      sessionStorage.setItem("quesTagShow", this.quesTagShow);
+    },
+    // 查看基础构成
+    toViewBaseInfo() {
+      this.$refs.PaperBaseInfo.open();
+    },
+    // 查看题型分布
+    toViewQuestypeInfo() {
+      this.$refs.PaperQuestypeInfo.open();
+    },
+    // 查看蓝图分布
+    toViewBlueInfo() {
+      this.$refs.PaperBlueInfo.open();
+    },
+    // 查看审核信息
+    toViewAuditInfo() {
+      this.$refs.PaperAuditInfo.open();
+    },
+    // 编辑题卡
+    toEditCard() {
+      this.$router.push({
+        name: "CardEdit",
+        params: {
+          idType: "paper",
+          paperOrCardId: this.paperId,
+        },
+      });
+    },
+  },
+};
+</script>