123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509 |
- <template>
- <div class="edit-paper" ref="editPaper">
- <div class="edit-header">
- <div class="edit-header-top box-justify">
- <div class="header-info">
- <el-button
- class="is-back"
- icon="el-icon-arrow-left"
- @click="toBack"
- size="mini"
- style="margin-right: 0"
- ></el-button>
- <!-- <div class="header-info-item">
- <span>课程代码:</span>
- <span>{{ paper.course.code }}</span>
- </div> -->
- <div class="header-info-item">
- <!-- <span>课程名称:</span> -->
- <span style="color: #262626; font-size: 16px; font-weight: bold">{{
- 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-dropdown trigger="click" @command="importCommand">
- <div class="avatar-wrapper">
- <el-button>
- 导入
- <i class="el-icon-arrow-down" />
- </el-button>
- </div>
- <el-dropdown-menu slot="dropdown" class="user-dropdown">
- <el-dropdown-item command="answer">
- <span>导入答案</span>
- </el-dropdown-item>
- <el-dropdown-item command="property">
- <span>导入知识点</span>
- </el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- <el-button
- v-if="checkDuplicateBtnShow"
- type="primary"
- size="small"
- plain
- @click="toCheckDuplicate"
- >
- 进入查重
- </el-button>
- <el-button
- type="danger"
- size="small"
- plain
- class="maintain"
- @click="toDeletePaper(paper.id)"
- >
- 删除
- </el-button>
- <el-button type="primary" size="small" @click="toSavePaper">
- 保存
- </el-button>
- <!-- <el-button
- size="small"
- type="primary"
- plain
- @click="toImportPaperAnswer"
- >导入答案</el-button
- >
- <el-button
- size="small"
- type="primary"
- plain
- @click="toImportPaperProperty"
- >导入属性</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
- plain
- size="small"
- icon="el-icon-circle-plus"
- @click="addBigQuestion"
- >
- 新增大题
- </el-button>
- <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">
- 题型分布
- </el-button>
- <el-button plain size="small" @click="toViewBlueInfo">
- 蓝图分布
- </el-button> -->
- <!-- <el-button plain size="small" @click="toViewAuditInfo">
- 审核记录
- </el-button> -->
- <el-button
- v-if="
- enableCardEdit &&
- authButtons.includes('exam_paper_manager-edit_card')
- "
- plain
- size="small"
- @click="toEditCard"
- >
- 编辑题卡
- </el-button>
- <el-button
- v-if="
- enableCardEdit &&
- authButtons.includes('exam_paper_manager-edit_card')
- "
- type="danger"
- size="small"
- plain
- class="maintain"
- @click="toDeletCard"
- >
- 清除题卡
- </el-button>
- </div>
- <div>
- <el-button size="small" @click="toViewLog">试卷修改记录</el-button>
- <tool-tip-btn
- name="shenhejilu"
- content="审核记录"
- @click="toViewAuditInfo"
- ></tool-tip-btn>
- <tool-tip-btn
- name="yulan"
- content="生成试卷"
- @click="previewPDF2"
- ></tool-tip-btn>
- <tool-tip-btn
- name="shuxingyincangxianshi"
- :content="(quesTagShow ? '隐藏' : '显示') + '属性'"
- @click="toSwitchQuesTagShowHide"
- ></tool-tip-btn>
- <tool-tip-btn
- name="daochu"
- content="导出试卷蓝图"
- :disabled="downloading"
- @click="toExportPaperBlue"
- ></tool-tip-btn>
- <tool-tip-btn
- name="daanyincangxianshi"
- :content="(quesAnswerShow ? '隐藏' : '显示') + '答案'"
- @click="toSwitchQuesAnswerShowHide"
- ></tool-tip-btn>
- <!-- <el-button size="small" type="primary" plain @click="previewPDF2"
- >预览</el-button
- > -->
- <!-- <el-button
- type="primary"
- size="small"
- plain
- @click="toSwitchQuesTagShowHide"
- >
- {{ quesTagShow ? "隐藏" : "显示" }}属性
- </el-button> -->
- <!-- <el-button
- size="small"
- type="primary"
- plain
- :loading="downloading"
- @click="toExportPaperBlue"
- >导出试卷蓝图</el-button
- > -->
- <!-- <el-button
- type="primary"
- size="small"
- plain
- @click="toSwitchQuesAnswerShowHide"
- >
- {{ quesAnswerShow ? "隐藏" : "显示" }}答案
- </el-button> -->
- </div>
- </div>
- </div>
- <div
- class="edit-body"
- style="
- margin: 0 16px;
- padding-top: 0;
- display: flex;
- flex-direction: column;
- height: 100%;
- "
- >
- <div
- class="edit-warning-wrap"
- :class="{ hid: this.checkPaperQuestionAllHasScore() }"
- >
- <div class="edit-warning">
- <img src="../../../assets/images/paper_edit_warning.png" />
- <span>有小题未设置分值</span>
- </div>
- </div>
- <div style="flex: 1; overflow: auto" ref="editPaperBody">
- <!-- 考试说明 -->
- <div class="edit-part-list">
- <div class="edit-part">
- <div class="edit-cont">
- <div
- class="edit-cont-title"
- style="display: flex; align-items: center"
- >
- <h3>考试说明</h3>
- <svg-btn
- name="bianji"
- color="#6D5FF6"
- hoverBgColor="#F0EFFE"
- class="hover-show"
- @click="toEditExamRemark"
- style="margin-left: 10px"
- >编辑</svg-btn
- >
- </div>
- <!-- <div class="edit-cont-action">
- <el-button
- type="primary"
- plain
- size="small"
- @click="toEditExamRemark"
- >编辑</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"
- :key="paperDetail.id"
- class="edit-part-list"
- >
- <div class="edit-part level1">
- <div class="edit-cont">
- <div class="edit-cont-title">
- <h3>
- <span>{{ paperDetail.cnNum }}</span> <span>.</span>
- <span>{{ paperDetail.name }}</span>
- </h3>
- </div>
- <rich-text
- class="edit-cont-body"
- :text-json="paperDetail.description"
- ></rich-text>
- </div>
- <div class="level1-hover-show">
- <div style="color: #595959; margin-bottom: 5px">
- 共{{ paperDetail.unitCount }}小题,满分{{ paperDetail.score }}分
- </div>
- <div class="gray-btn-group">
- <span @click="toSelectPaperDetailQues(paperDetail)">选题</span>
- <span @click="toEditPaperDetail(paperDetail)">编辑</span>
- <span
- v-if="detailIndex"
- @click="toMovePaperDetail(paperDetail, 'up')"
- >上移</span
- >
- <span
- v-if="detailIndex < paper.paperDetails.length - 1"
- @click="toMovePaperDetail(paperDetail, 'down')"
- >下移</span
- >
- <span @click="toDeletePaperDetail(paperDetail)">删除</span>
- <span
- @click.stop="
- paperDetail.showQuestions = !paperDetail.showQuestions
- "
- >{{ paperDetail.showQuestions ? "收起" : "展开" }}</span
- >
- </div>
- <!--
- <div>
- <el-button
- size="small"
- type="primary"
- plain
- @click="toSelectPaperDetailQues(paperDetail)"
- >选题
- </el-button>
- <el-button
- size="small"
- type="primary"
- plain
- @click="toEditPaperDetail(paperDetail)"
- >编辑
- </el-button>
- <el-button
- v-if="detailIndex"
- size="small"
- type="primary"
- plain
- @click="toMovePaperDetail(paperDetail, 'up')"
- >上移
- </el-button>
- <el-button
- v-if="detailIndex < paper.paperDetails.length - 1"
- size="small"
- type="primary"
- plain
- @click="toMovePaperDetail(paperDetail, 'down')"
- >下移
- </el-button>
- <el-button
- size="small"
- type="danger"
- @click="toDeletePaperDetail(paperDetail)"
- >删除
- </el-button>
- <el-button
- size="small"
- type="primary"
- plain
- :icon="
- paperDetail.showQuestions
- ? 'el-icon-arrow-up'
- : 'el-icon-arrow-down'
- "
- @click.stop="
- paperDetail.showQuestions = !paperDetail.showQuestions
- "
- ></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 level1">
- <div class="edit-property-title">
- {{ paperDetailTag.tag }}
- </div>
- <div class="edit-property-content">
- {{ paperDetailTag.content }}
- </div>
- </div>
- </div>
- <template v-if="paperDetail.selective">
- <div class="edit-property-item">
- <div class="edit-property-body level1">
- <div class="edit-property-title">选做题数</div>
- <div class="edit-property-content">
- {{ paperDetail.selectiveCount }}
- </div>
- </div>
- </div>
- <div class="edit-property-item">
- <div class="edit-property-body level1">
- <div class="edit-property-title">取分规则</div>
- <div class="edit-property-content">
- {{
- paperDetail.selectiveRule | selectiveRuleTypeFilter
- }}
- </div>
- </div>
- </div>
- </template>
- </div>
- </div>
- </div>
- <!-- 循环小题 -->
- <div v-show="paperDetail.showQuestions" class="edit-paper-questions">
- <template
- v-for="(
- paperDetailUnit, unitIndex
- ) in paperDetail.paperDetailUnits"
- >
- <div
- :key="`question-${unitIndex}`"
- :class="[
- 'edit-part',
- 'level2',
- `small-${detailIndex}-${unitIndex}`,
- {
- 'question-duplicate':
- paperDetailUnit.question.checkDuplicateStatus ==
- 'TO_BE_DISPOSE',
- 'is-danger': !paperDetailUnit.score,
- },
- ]"
- >
- <div class="level2-hover-show">
- <div class="box-justify">
- <div class="gray-btn-group">
- <span
- v-if="
- paperDetailUnit.question.checkDuplicateStatus ===
- 'TO_BE_DISPOSE'
- "
- @click="
- toCheckDuplicateQuestion(paperDetailUnit.question.id)
- "
- >进入查重</span
- >
- <span @click="toChangeQues(paperDetailUnit)">换题</span>
- <span @click="toEditQues(paperDetailUnit)">编辑</span>
- <span
- v-if="unitIndex"
- @click="
- toMoveQues(paperDetail.id, paperDetailUnit.id, 'up')
- "
- >上移</span
- >
- <span
- v-if="
- unitIndex < paperDetail.paperDetailUnits.length - 1
- "
- @click="
- toMoveQues(paperDetail.id, paperDetailUnit.id, 'down')
- "
- >下移</span
- >
- <span @click="toDeleteQues(paperDetailUnit)">删除</span>
- <span
- v-if="isNested(paperDetailUnit.questionType)"
- @click="
- paperDetailUnit.showSubQuestions =
- !paperDetailUnit.showSubQuestions
- "
- >{{
- paperDetailUnit.showSubQuestions ? "收起" : "展开"
- }}</span
- >
- </div>
- <span class="tips-info">
- {{ paperDetailUnit.question.bodyLengthText }}
- </span>
- </div>
- <!-- <el-button
- v-if="
- paperDetailUnit.question.checkDuplicateStatus ===
- 'TO_BE_DISPOSE'
- "
- size="small"
- type="primary"
- plain
- @click="
- toCheckDuplicateQuestion(paperDetailUnit.question.id)
- "
- >进入查重
- </el-button>
- <el-button
- size="small"
- type="primary"
- plain
- @click="toChangeQues(paperDetailUnit)"
- >换题
- </el-button>
- <el-button
- size="small"
- type="primary"
- plain
- @click="toEditQues(paperDetailUnit)"
- >编辑
- </el-button>
- <el-button
- v-if="unitIndex"
- size="small"
- type="primary"
- plain
- @click="
- toMoveQues(paperDetail.id, paperDetailUnit.id, 'up')
- "
- >上移
- </el-button>
- <el-button
- v-if="unitIndex < paperDetail.paperDetailUnits.length - 1"
- size="small"
- type="primary"
- plain
- @click="
- toMoveQues(paperDetail.id, paperDetailUnit.id, 'down')
- "
- >下移
- </el-button>
- <el-button
- type="danger"
- size="small"
- @click="toDeleteQues(paperDetailUnit)"
- >删除
- </el-button>
- <el-button
- v-if="isNested(paperDetailUnit.questionType)"
- size="small"
- :icon="
- paperDetailUnit.showSubQuestions
- ? 'el-icon-arrow-up'
- : 'el-icon-arrow-down'
- "
- @click.stop="
- paperDetailUnit.showSubQuestions =
- !paperDetailUnit.showSubQuestions
- "
- ></el-button> -->
- </div>
- <div class="edit-cont">
- <div class="edit-cont-title">
- <span>{{ paperDetailUnit.number }}.</span>
- <rich-text
- :text-json="paperDetailUnit.question.quesBody"
- ></rich-text>
- <span :class="{ 'color-danger': !paperDetailUnit.score }">
- ({{ 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
- v-if="paperDetailUnit.question.quesProperties"
- class="edit-cont-props"
- style="margin-top: 10px"
- >
- <el-tag
- v-for="(content, propIndex) in paperDetailUnit.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" style="margin: 0 3px"
- >/</span
- >
- {{
- content.secondProperty && content.secondProperty.name
- }}
- </el-tag>
- </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 level2">
- <div class="edit-property-title">
- {{ questionTag.tag }}
- </div>
- <div class="edit-property-content">
- {{ questionTag.content }}
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div
- v-if="isNested(paperDetailUnit.questionType)"
- v-show="paperDetailUnit.showSubQuestions"
- :key="`question-sub-${unitIndex}`"
- class="edit-paper-question-subs"
- >
- <div
- v-for="(subQuestion, subIndex) in paperDetailUnit.question
- .subQuestions"
- :key="subIndex"
- :class="[
- 'edit-part',
- {
- 'is-danger': !paperDetailUnit.subScoreList[subIndex],
- },
- ]"
- >
- <div class="edit-cont">
- <div class="edit-cont-title">
- <span>{{ subIndex + 1 }}. </span>
- <rich-text :text-json="subQuestion.quesBody"></rich-text>
- <span
- :class="{
- 'color-danger':
- !paperDetailUnit.subScoreList[subIndex],
- }"
- >
- ({{ 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
- v-if="subQuestion.quesProperties"
- 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"
- style="margin: 0 3px"
- >/</span
- >
- {{
- content.secondProperty && content.secondProperty.name
- }}
- </el-tag>
- </div>
- </div>
- <!-- <div
- v-if="subQuestion.quesProperties"
- 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" style="margin: 0 3px"
- >/</span
- >
- {{ content.secondProperty && content.secondProperty.name }}
- </el-tag>
- </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 level2">
- <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>
- </div>
- <!-- 编辑考试说明 -->
- <modify-rich-text
- ref="ModifyRichText"
- :content="paper.examRemark"
- title="考试说明"
- @modified="examRemarkModified"
- ></modify-rich-text>
- <!-- 编辑大题弹框 -->
- <modify-detail-struct
- ref="ModifyDetailStruct"
- :detail="curDetail"
- only-name
- 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>
- <!-- 上传答案文件 -->
- <import-file-dialog
- ref="ImportAnswerDialog"
- dialog-title="上传答案文件"
- :template-url="answerTemplateUrl"
- :upload-url="uploadAnswerUrl"
- add-file-param="dataFile"
- @uploaded="initPaper"
- ></import-file-dialog>
- <!-- 上传属性文件 -->
- <import-file-dialog
- ref="ImportPorpertyDialog"
- dialog-title="上传知识点文件"
- :template-url="propertyTemplateUrl"
- :upload-url="uploadPropertyUrl"
- add-file-param="dataFile"
- @uploaded="initPaper"
- ></import-file-dialog>
- <!-- 题型分布 -->
- <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>
- <!-- 试题编辑 -->
- <question-edit-dialog
- ref="QuestionEditDialog"
- :question="curQuestion"
- edit-mode="paper"
- @modified="questionEdited"
- ></question-edit-dialog>
- <!-- SelectQuestionDialog -->
- <select-question-dialog
- ref="SelectQuestionDialog"
- :course-id="paper.course.id"
- :disabled-question-ids="paperQuestionIds"
- select-mode="paper"
- @confirm="questionSelected"
- ></select-question-dialog>
- <!-- PaperEditLogDialog -->
- <paper-edit-log-dialog
- ref="PaperEditLogDialog"
- :paper-id="paperId"
- ></paper-edit-log-dialog>
- </div>
- </template>
- <script>
- import {
- paperDetailApi,
- paperSaveApi,
- paperDeleteApi,
- paperDetailUpdateApi,
- paperDetailMoveApi,
- paperDetailDeleteApi,
- paperQuestionMoveApi,
- paperQuestionDeleteApi,
- paperQuestionSaveApi,
- paperDetailAddQuestionApi,
- paperQuestionChangeApi,
- paperCardDeleteApi,
- paperPropertyExportApi,
- paperDetailAddApi,
- } from "../api";
- 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";
- import PaperAuditInfo from "../components/PaperAuditInfo.vue";
- import ModifyDetailStruct from "../components/ModifyDetailStruct.vue";
- import PaperEditLogDialog from "../components/PaperEditLogDialog.vue";
- import ModifyRichText from "@/components/ModifyRichText.vue";
- import QuestionEditDialog from "../../question/components/QuestionEditDialog.vue";
- import SelectQuestionDialog from "../components/SelectQuestionDialog.vue";
- import QuestionAnswer from "../../question/components/QuestionAnswer.vue";
- import { calcSum } from "@/plugins/utils";
- import { downloadByApi } from "@/plugins/download";
- import { mapGetters } from "vuex";
- export default {
- name: "EditPaper",
- components: {
- PaperStructInfo,
- PaperBaseInfo,
- PaperQuestypeInfo,
- PaperAuditInfo,
- PaperBlueInfo,
- ModifyDetailStruct,
- ModifyRichText,
- QuestionEditDialog,
- ImportFileDialog,
- SelectQuestionDialog,
- QuestionAnswer,
- PaperEditLogDialog,
- },
- data() {
- return {
- paperId: "",
- parentView: "",
- paper: {
- name: "",
- title: "",
- totalScore: 0,
- course: {
- id: "",
- code: "",
- name: "",
- },
- examRemark: "",
- paperDetails: [],
- },
- checkDuplicateBtnShow: false,
- quesTagShow: true,
- quesAnswerShow: false,
- curDetail: {},
- curQuestion: {},
- paperQuestionIds: [],
- changeSelectQuestionMap: {},
- downloading: false,
- // upload answer
- uploadAnswerUrl: "",
- answerTemplateUrl: "",
- // upload property
- propertyTemplateUrl: "",
- uploadPropertyUrl: "",
- bigOpenStatusIds: [],
- smallOpenStatusIds: [],
- };
- },
- computed: {
- user() {
- return this.$store.state.user;
- },
- enableCardEdit() {
- return this.paper.auditStatus === "PASS";
- },
- ...mapGetters(["authButtons"]),
- },
- 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: {
- saveOpenStatus() {
- let bigOpenStatusIds = [];
- let smallOpenStatusIds = [];
- for (let i = 0; i < this.paper.paperDetails.length; i++) {
- let detail = this.paper.paperDetails[i];
- bigOpenStatusIds.push({
- id: detail.id,
- showQuestions: detail.showQuestions,
- });
- for (let j = 0; j < detail.paperDetailUnits.length; j++) {
- let question = detail.paperDetailUnits[j];
- smallOpenStatusIds.push({
- id: question.id,
- showSubQuestions: question.showSubQuestions,
- });
- }
- }
- this.bigOpenStatusIds = bigOpenStatusIds;
- this.smallOpenStatusIds = smallOpenStatusIds;
- },
- async initPaper(type) {
- this.saveOpenStatus();
- const res = await paperDetailApi(this.paperId);
- res.data.paperDetails.forEach((detail) => {
- detail.showQuestions =
- this.bigOpenStatusIds.find((item) => item.id == detail.id)
- ?.showQuestions ?? true;
- if (type == "addSmall" && detail.id == this.curDetail.id) {
- detail.showQuestions = true;
- }
- detail.paperDetailUnits.forEach((question) => {
- question.showSubQuestions =
- this.smallOpenStatusIds.find((item) => item.id == question.id)
- ?.showSubQuestions ?? true;
- });
- });
- this.paper = res.data;
- this.paper.title = this.paper.title || this.paper.name;
- this.showCheckDuplicate();
- if (type == "addBig") {
- setTimeout(() => {
- this.$refs.editPaperBody.scrollTo({
- left: 0,
- top: 100000,
- behavior: "smooth",
- });
- }, 20);
- } else if (type == "addSmall") {
- let bigIndex = this.paper.paperDetails.findIndex(
- (item) => item.id == this.curDetail.id
- );
- if (bigIndex > -1) {
- let cls = `small-${bigIndex}-${
- this.paper.paperDetails[bigIndex].paperDetailUnits.length - 1
- }`;
- setTimeout(() => {
- const el = document.querySelector("." + cls);
- // this.$refs.editPaperBody.scrollTo({
- // left: 0,
- // top: el.getBoundingClientRect().top - 210,
- // behavior: "smooth",
- // });
- el.scrollIntoView({ behavior: "smooth", block: "start" });
- }, 100);
- }
- }
- if (!this.checkPaperQuestionAllHasScore()) {
- this.$notify.error("有小题未设置分值!");
- }
- },
- previewPDF2() {
- window.open(
- this.getRouterPath({
- name: "PaperTemplateBuild",
- params: {
- paperId: this.paper.id,
- },
- })
- );
- },
- // 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",
- },
- });
- },
- checkPaperQuestionAllHasScore() {
- return !this.paper.paperDetails.some((detail) => {
- return detail.paperDetailUnits.some((qUnit) => !qUnit.score);
- });
- },
- // 保存试卷
- async toSavePaper() {
- const confirm = await this.$confirm(`确定保存吗?`, "系统通知", {
- type: "warning",
- }).catch(() => {});
- if (confirm !== "confirm") return;
- const res = await paperSaveApi(this.paper).catch(() => {});
- 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.id).catch(() => {});
- if (!res) return;
- this.$message.success("删除成功!");
- this.toBack();
- },
- importCommand(command) {
- if (command == "answer") {
- this.toImportPaperAnswer();
- } else {
- this.toImportPaperProperty();
- }
- },
- // 导入答案
- toImportPaperAnswer() {
- this.answerTemplateUrl = `${QUESTION_API}/paper/answer/export/${this.paperId}`;
- this.uploadAnswerUrl = `${QUESTION_API}/paper/answer/import/${this.paperId}`;
- this.$refs.ImportAnswerDialog.open();
- },
- // 导出试卷蓝图
- async toExportPaperBlue() {
- if (this.downloading) return;
- this.downloading = true;
- const res = await downloadByApi(() => {
- return paperPropertyExportApi(this.paperId);
- }).catch((e) => {
- this.$message.error(e || "下载失败,请重新尝试!");
- });
- this.downloading = false;
- if (!res) return;
- this.$message.success("下载成功!");
- },
- // 导入属性
- toImportPaperProperty() {
- this.propertyTemplateUrl = `${QUESTION_API}/paper/property/template?paperId=${this.paperId}`;
- this.uploadPropertyUrl = `${QUESTION_API}/paper/property/import?paperId=${this.paperId}`;
- this.$refs.ImportPorpertyDialog.open();
- },
- 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);
- },
- toViewStructInfo() {
- this.$refs.PaperStructInfo.open();
- },
- // 查看基础构成
- 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,
- },
- });
- },
- async toDeletCard() {
- const confirm = await this.$confirm(
- `确定要清除当前试卷的题卡吗?`,
- "提示",
- {
- type: "warning",
- }
- ).catch(() => {});
- if (confirm !== "confirm") return;
- await paperCardDeleteApi(this.paperId);
- this.$message.success("操作成功!");
- },
- toViewLog() {
- this.$refs.PaperEditLogDialog.open();
- },
- // header-action ----end
- // 考试说明
- toEditExamRemark() {
- this.$refs.ModifyRichText.open();
- },
- examRemarkModified(content) {
- this.paper.examRemark = content;
- this.toSavePaper();
- },
- getPaperQuestionIds() {
- let ids = [];
- this.paper.paperDetails.forEach((detail) => {
- let qids = detail.paperDetailUnits.map((q) => q.question.id);
- ids.push(...qids);
- });
- return ids;
- },
- // detail-action
- // 大题选题
- toSelectPaperDetailQues(detail) {
- this.curDetail = detail;
- this.paperQuestionIds = this.getPaperQuestionIds();
- this.$refs.SelectQuestionDialog.open();
- },
- async questionSelected(questions) {
- if (!questions.length) {
- this.$message.error("请选择试题!");
- return;
- }
- const res = await paperDetailAddQuestionApi(
- this.paperId,
- this.curDetail.id,
- questions
- ).catch(() => {});
- if (!res) return;
- this.$message.success("添加成功!");
- this.initPaper("addSmall");
- },
- addBigQuestion() {
- this.curDetail = {};
- this.$refs.ModifyDetailStruct.open();
- },
- // 大题编辑
- toEditPaperDetail(detail) {
- this.curDetail = { ...detail, detailName: detail.name };
- this.$refs.ModifyDetailStruct.open();
- },
- async detailModified(detail, isAdd) {
- if (isAdd) {
- const res = paperDetailAddApi({
- paperId: this.paperId,
- name: detail.detailName,
- description: detail.description,
- }).catch(() => {});
- if (!res) return;
- this.$message.success("新增成功!");
- setTimeout(() => {
- this.initPaper("addBig");
- }, 50);
- } else {
- detail.name = detail.detailName;
- const res = await paperDetailUpdateApi(this.paperId, detail).catch(
- () => {}
- );
- if (!res) return;
- this.$message.success("修改成功!");
- this.initPaper();
- }
- // const paperDetail = this.paper.paperDetails.find(
- // (item) => item.id === detail.id
- // );
- // if (!paperDetail) return;
- // paperDetail.name = detail.detailName;
- // paperDetail.description = detail.description;
- },
- // 移动大题
- async toMovePaperDetail(detail, vector) {
- const vectorStr = vector == "up" ? "上移" : "下移";
- const confirm = await this.$confirm(
- `确定要${vectorStr}该大题吗?`,
- "提示",
- {
- type: "warning",
- }
- ).catch(() => {});
- if (confirm !== "confirm") return;
- const res = await paperDetailMoveApi({
- paperId: this.paperId,
- detailId: detail.id,
- vector,
- }).catch(() => {});
- if (!res) return;
- this.$message.success("操作成功!");
- this.initPaper();
- },
- // 删除大题
- async toDeletePaperDetail(detail) {
- if (detail.paperDetailUnits.length) {
- this.$message.error("大题下还有小题,不可删除!");
- return;
- }
- const confirm = await this.$confirm(`确定要删除该大题吗?`, "提示", {
- type: "warning",
- }).catch(() => {});
- if (confirm !== "confirm") return;
- const res = await paperDetailDeleteApi({
- paperId: this.paperId,
- detailId: detail.id,
- }).catch(() => {});
- if (!res) return;
- this.$message.success("操作成功!");
- this.initPaper();
- },
- // detail-action ----end
- // question-action
- toCheckDuplicateQuestion(questionId) {
- this.$router.push({
- name: "check_duplicate_info",
- query: {
- quesId: questionId,
- basePaperId: this.paperId,
- from: "paper",
- },
- });
- },
- // 更换试题
- async toChangeQues(row) {
- let question = row.question;
- if (!this.changeSelectQuestionMap[question.sourceDetailId])
- this.changeSelectQuestionMap[question.sourceDetailId] = [];
- const res = await paperQuestionChangeApi(
- row.id,
- this.changeSelectQuestionMap[question.sourceDetailId].join()
- ).catch(() => {});
- if (!res) return;
- if (!this.changeSelectQuestionMap[question.sourceDetailId].length) {
- this.changeSelectQuestionMap[question.sourceDetailId].push(question.id);
- }
- this.changeSelectQuestionMap[question.sourceDetailId].push(res.data);
- this.initPaper();
- },
- // 编辑小题
- toEditQues(row) {
- this.curQuestion = row;
- this.$refs.QuestionEditDialog.open();
- },
- async questionEdited(question) {
- let subScoreList = [];
- if (question.subQuestions && question.subQuestions.length) {
- subScoreList = question.subQuestions.map((item) => item.score || 0);
- question.score = calcSum(subScoreList);
- }
- let questionUnit = {
- id: this.curQuestion.id,
- question,
- score: question.score,
- };
- if (subScoreList.length) questionUnit.subScoreList = subScoreList;
- const res = await paperQuestionSaveApi(questionUnit).catch(() => {});
- if (!res) return;
- this.$message.success("保存成功!");
- this.initPaper();
- },
- // 移动小题
- async toMoveQues(detailId, unitid, vector) {
- const vectorStr = vector == "up" ? "上移" : "下移";
- const confirm = await this.$confirm(
- `确定要${vectorStr}该小题吗?`,
- "提示",
- {
- type: "warning",
- }
- ).catch(() => {});
- if (confirm !== "confirm") return;
- const res = await paperQuestionMoveApi({
- detailId,
- unitid,
- vector,
- }).catch(() => {});
- if (!res) return;
- this.$message.success("操作成功!");
- this.initPaper();
- },
- // 删除小题
- async toDeleteQues(paperDetailUnit) {
- const confirm = await this.$confirm(`确定要删除该题吗?`, "提示", {
- type: "warning",
- }).catch(() => {});
- if (confirm !== "confirm") return;
- const res = await paperQuestionDeleteApi(paperDetailUnit.id).catch(
- () => {}
- );
- if (!res) return;
- this.$message.success("操作成功!");
- this.initPaper();
- },
- // other
- 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>
- <style lang="scss" scoped>
- .edit-paper {
- height: calc(100vh - 140px);
- margin-top: 140px;
- .edit-warning-wrap {
- height: 69px;
- &.hid {
- height: 0;
- overflow: hidden;
- .edit-warning {
- height: 0;
- overflow: hidden;
- }
- }
- transition: all 0.3s;
- }
- .edit-warning {
- height: 54px;
- background: #fdcdc5;
- border-radius: 8px;
- padding: 0 15px;
- display: flex;
- align-items: center;
- transition: all 0.3s;
- img {
- width: 20px;
- margin-right: 8px;
- }
- span {
- color: #262626;
- font-size: 14px;
- }
- }
- .edit-part {
- &.level2 {
- padding-bottom: 60px;
- & > .edit-cont {
- .edit-cont-title > .rich-text {
- vertical-align: top;
- }
- }
- .level2-hover-show {
- display: none;
- position: absolute;
- bottom: 15px;
- left: 20px;
- z-index: 1;
- width: calc(100% - 450px);
- }
- &:hover {
- .level2-hover-show {
- display: block;
- }
- }
- }
- &.level1 {
- padding-bottom: 80px;
- .level1-hover-show {
- display: none;
- position: absolute;
- bottom: 15px;
- left: 20px;
- z-index: 1;
- }
- &:hover {
- .level1-hover-show {
- display: block;
- }
- }
- }
- .hover-show {
- visibility: hidden;
- }
- &:hover {
- .hover-show {
- visibility: visible;
- }
- }
- .gray-btn-group {
- height: 32px;
- border-radius: 6px;
- background: #f2f3f5;
- display: flex;
- align-items: center;
- & > span {
- color: #8c8c8c;
- font-size: 14px;
- padding: 0 12px;
- cursor: pointer;
- transition: all 0.3s;
- &:not(:first-child) {
- border-left: 1px solid #e5e5e5;
- }
- &:hover {
- color: #262626;
- }
- }
- }
- }
- }
- </style>
|