EditPaper.vue 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296
  1. <template>
  2. <div
  3. id="editPaperApp"
  4. v-loading="loading"
  5. class="paper"
  6. element-loading-text="拼命加载中。。。"
  7. >
  8. <!-- <ckeditor v-model="examRemark"></ckeditor> -->
  9. <div class="edit-paper-top">
  10. <div class="edit-paper-top-inline">
  11. <div class="paper-top-div">
  12. <span class="paper-top-title">课程代码:</span>
  13. <span class="paper-top-value">{{ paper.course.code }}</span>
  14. </div>
  15. <div class="paper-top-div">
  16. <span class="paper-top-title">课程名称:</span>
  17. <span class="paper-top-value">{{ paper.course.name }}</span>
  18. </div>
  19. <div class="paper-top-div">
  20. <span class="paper-top-title">试卷名称:</span>
  21. <el-tooltip class="item" effect="dark" placement="top-start">
  22. <div slot="content">{{ paper.name }}</div>
  23. <input
  24. v-model="paper.name"
  25. class="paperName-input font_length"
  26. placeholder="试卷名称"
  27. />
  28. </el-tooltip>
  29. </div>
  30. <div class="paper-top-div">
  31. <span class="paper-top-title">试卷总分:</span>
  32. <span class="paper-top-value">{{ paper.totalScore }}</span>
  33. </div>
  34. <div class="paper-top-right-div">
  35. <el-button
  36. size="small"
  37. type="primary"
  38. style="margin-left: 10px"
  39. @click="back"
  40. ><i class="el-icon-arrow-left"></i> 返回</el-button
  41. >
  42. </div>
  43. <div class="paper-top-right-div">
  44. <el-dropdown class="button_left">
  45. <el-button type="primary" size="small">
  46. 更多 <i class="el-icon-arrow-down el-icon--right"></i>
  47. </el-button>
  48. <el-dropdown-menu slot="dropdown">
  49. <el-dropdown-item>
  50. <el-button
  51. type="primary"
  52. :loading="duplicateLoading"
  53. size="small"
  54. @click="getreduplicateQuestions"
  55. ><i class="el-icon-zoom-in"></i>查重
  56. </el-button>
  57. </el-dropdown-item>
  58. <el-dropdown-item>
  59. <el-button type="primary" size="small" @click="openDialog"
  60. ><i class="el-icon-upload2"></i>上传音频
  61. </el-button>
  62. </el-dropdown-item>
  63. <el-dropdown-item>
  64. <el-button
  65. size="small"
  66. type="primary"
  67. @click="exportPaperAnswer()"
  68. ><i class="el-icon-download"></i>导出答案</el-button
  69. >
  70. </el-dropdown-item>
  71. <el-dropdown-item>
  72. <el-button type="primary" size="small" @click="openAnswerDialog"
  73. ><i class="el-icon-upload2"></i>导入答案
  74. </el-button>
  75. </el-dropdown-item>
  76. </el-dropdown-menu>
  77. </el-dropdown>
  78. </div>
  79. <div class="paper-top-right-div">
  80. <el-button
  81. style="margin-left: 10px"
  82. type="danger"
  83. size="small"
  84. @click="deletePaper(paper.id)"
  85. >
  86. <i class="el-icon-delete"></i> 删除
  87. </el-button>
  88. </div>
  89. <div class="paper-top-right-div">
  90. <el-button
  91. style="margin-left: 10px"
  92. type="primary"
  93. size="small"
  94. @click="savePaper"
  95. >
  96. 保存
  97. </el-button>
  98. </div>
  99. </div>
  100. </div>
  101. <div class="edit-paper-top2">
  102. <div class="edit-paper-top-inline">
  103. <div class="paper-top-left-div">
  104. <el-button type="primary" size="small" @click="savePaper">
  105. 保存
  106. </el-button>
  107. </div>
  108. <div class="paper-top-left-div">
  109. <el-button type="primary" size="small" @click="savePaper">
  110. 保存2
  111. </el-button>
  112. </div>
  113. <div class="paper-top-right-div" @click="quesTagShowHide">
  114. <span class="paper-top-text-btn"
  115. >{{ quesTagShow ? "隐藏" : "显示" }}属性</span
  116. >
  117. </div>
  118. <div class="paper-top-right-div" @click="quesAnswerShowHide">
  119. <span class="paper-top-text-btn"
  120. >{{ quesAnswerShow ? "隐藏" : "显示" }}答案</span
  121. >
  122. </div>
  123. </div>
  124. </div>
  125. <div class="paperName">
  126. <div class="text-left">
  127. <div class="mainQues" style="margin-top: 20px; margin-left: 0px">
  128. <div class="mainQuesTitle">
  129. <span>考试说明:</span>
  130. <span>
  131. <el-button size="small" @click="openEditExamPaperRemark"
  132. >编辑</el-button
  133. >
  134. </span>
  135. <div style="width: 550px; margin-left: 20px; margin-top: 20px">
  136. <span v-html="paper.examRemark"></span>
  137. </div>
  138. </div>
  139. </div>
  140. </div>
  141. </div>
  142. <div>
  143. <!-- 循环大题 -->
  144. <div
  145. v-for="(paperDetail, detailIndex) in paper.paperDetails"
  146. v-show="paperDetailShow(paperDetail)"
  147. :key="detailIndex"
  148. class="mainQues"
  149. >
  150. <div class="mainQuesTitleDiv">
  151. <div
  152. class="mainQuesTitle"
  153. @mouseover="quesMouseOver(paperDetail.id)"
  154. @mouseout="quesMouseOut(paperDetail.id)"
  155. >
  156. <span>{{ paperDetail.cnNum }}</span> <span>.</span>
  157. <span>{{ paperDetail.name }}</span>
  158. <span>
  159. ({{
  160. !paperDetail.title ? "本大题" : paperDetail.title + ","
  161. }}共{{ paperDetail.unitCount }}小题,满分{{
  162. paperDetail.score
  163. }}分)
  164. </span>
  165. <span :id="paperDetail.id" class="btnDiv">
  166. <el-button
  167. v-show="parentView == 'gen_paper'"
  168. size="small"
  169. @click="selectQues(paperDetail.id)"
  170. >选题
  171. </el-button>
  172. <el-button size="small" @click="openEditPaperDetail(paperDetail)"
  173. >编辑
  174. </el-button>
  175. <el-button
  176. v-if="showUp(paperDetail)"
  177. size="small"
  178. @click="movePaperDetail(paperDetail, 'up')"
  179. >上移
  180. </el-button>
  181. <el-button
  182. v-if="showDown(paperDetail)"
  183. size="small"
  184. @click="movePaperDetail(paperDetail, 'down')"
  185. >下移
  186. </el-button>
  187. <el-button
  188. size="small"
  189. type="danger"
  190. @click="deletePaperDetail(paperDetail.id)"
  191. >删除
  192. </el-button>
  193. <el-button
  194. v-show="showButtons[detailIndex].up"
  195. size="small"
  196. icon="el-icon-arrow-up"
  197. @click.stop="hideContent(detailIndex)"
  198. ></el-button>
  199. <el-button
  200. v-show="!showButtons[detailIndex].up"
  201. size="small"
  202. icon="el-icon-arrow-down"
  203. @click.stop="showContent(detailIndex)"
  204. ></el-button>
  205. </span>
  206. <span v-question-audio v-html="paperDetail.description"></span>
  207. </div>
  208. <div v-show="quesTagShow" class="ques-tag-main">
  209. <div
  210. v-for="(paperDetailTag, tagIndex) in paperDetail.tags"
  211. :key="tagIndex"
  212. class="ques-tag-container"
  213. >
  214. <div class="ques-tag">
  215. <div class="ques-tag-title">{{ paperDetailTag.tag }}</div>
  216. <div>{{ paperDetailTag.content }}</div>
  217. </div>
  218. </div>
  219. </div>
  220. </div>
  221. <!-- 循环小题 -->
  222. <div v-show="showQuestions[detailIndex].is_show">
  223. <div
  224. v-for="(paperDetailUnit, unitIndex) in paperDetail.paperDetailUnits"
  225. v-show="quesShow(paperDetailUnit.id)"
  226. :key="unitIndex"
  227. class="ques"
  228. >
  229. <reduplicate_mark
  230. :id="paperDetailUnit.id"
  231. :show="reduplicateMarkShow(paperDetailUnit.id)"
  232. :fill-color="reduplicateMarkColor(paperDetailUnit.id)"
  233. :checked="reduplicateMarkCheck(paperDetailUnit.id)"
  234. @reduplicate_mark_check="reduplicate_mark_check"
  235. >
  236. </reduplicate_mark>
  237. <div
  238. class="quesSelect"
  239. @mouseover="quesMouseOver(paperDetailUnit.id)"
  240. @mouseout="quesMouseOut(paperDetailUnit.id)"
  241. >
  242. <div :id="paperDetailUnit.id" class="btnDiv">
  243. <span>{{ paperDetailUnit.question.bodyLengthText }}</span>
  244. <el-button
  245. size="small"
  246. @click="editQues(paperDetailUnit, paperDetailUnit.question)"
  247. >编辑
  248. </el-button>
  249. <el-button
  250. type="danger"
  251. size="small"
  252. @click="deleteQues(paperDetailUnit)"
  253. >删除
  254. </el-button>
  255. </div>
  256. <div class="quesBody">
  257. <span class="ques-title">{{ paperDetailUnit.number }}.</span>
  258. <span
  259. v-question-audio
  260. class="ques-body"
  261. :hasAudio="paperDetailUnit.question.hasAudio"
  262. :questionId="paperDetailUnit.question.id"
  263. v-html="paperDetailUnit.question.quesBody"
  264. ></span>
  265. <span class="score-span">
  266. ({{ paperDetailUnit.score }}分)
  267. </span>
  268. </div>
  269. <div
  270. v-for="(quesOption, optionIndex) in paperDetailUnit.question
  271. .quesOptions"
  272. :key="optionIndex"
  273. class="quesOption"
  274. >
  275. <span class="ques-title"
  276. >{{ optionIndex | optionOrderWordFilter }}.
  277. </span>
  278. <span
  279. v-question-audio
  280. class="ques-body"
  281. :hasAudio="paperDetailUnit.question.hasAudio"
  282. :questionId="paperDetailUnit.question.id"
  283. v-html="quesOption.optionBody"
  284. ></span>
  285. </div>
  286. <div v-if="!isNested(paperDetailUnit.questionType)">
  287. <div v-show="quesAnswerShow">
  288. <span>答案:</span>
  289. <span v-html="paperDetailUnit.question.quesAnswer"></span>
  290. </div>
  291. </div>
  292. </div>
  293. <div v-show="quesTagShow" class="ques-tag-main">
  294. <div
  295. v-for="(questionTag, tagIndex) in paperDetailUnit.question.tags"
  296. :key="tagIndex"
  297. class="ques-tag-container"
  298. >
  299. <div class="ques-tag">
  300. <div class="ques-tag-title">{{ questionTag.tag }}</div>
  301. <div>{{ questionTag.content }}</div>
  302. </div>
  303. </div>
  304. </div>
  305. <div style="flex-basis: 100%"></div>
  306. <div class="sub-ques-main-div">
  307. <div
  308. v-for="(subQuestion, subIndex) in paperDetailUnit.question
  309. .subQuestions"
  310. v-show="quesShow(subQuestion.id)"
  311. :key="subIndex"
  312. class="subQues"
  313. >
  314. <reduplicate_mark
  315. :show="reduplicateMarkShow(subQuestion.id)"
  316. ></reduplicate_mark>
  317. <div
  318. class="quesSelect"
  319. @mouseover="
  320. quesMouseOver(
  321. getSubQuesEditId(paperDetailUnit, subQuestion)
  322. )
  323. "
  324. @mouseout="
  325. quesMouseOut(getSubQuesEditId(paperDetailUnit, subQuestion))
  326. "
  327. >
  328. <div
  329. :id="getSubQuesEditId(paperDetailUnit, subQuestion)"
  330. class="btnDiv"
  331. >
  332. <el-button
  333. size="small"
  334. @click="editQues(paperDetailUnit, subQuestion)"
  335. >编辑
  336. </el-button>
  337. </div>
  338. <div class="quesBody">
  339. <span class="ques-title"
  340. >{{ subQuestion.subNumber }}.
  341. </span>
  342. <span v-question-audio v-html="subQuestion.quesBody"></span>
  343. <span
  344. >({{ paperDetailUnit.subScoreList[subIndex] }}分)</span
  345. >
  346. </div>
  347. <div v-if="!isMatchingQuestion(paperDetailUnit.questionType)">
  348. <div
  349. v-for="(
  350. subQuesOption, subOptIndex
  351. ) in subQuestion.quesOptions"
  352. :key="subOptIndex"
  353. class="quesOption"
  354. >
  355. <span class="ques-title"
  356. >{{ subOptIndex | optionOrderWordFilter }}.
  357. </span>
  358. <span
  359. v-question-audio
  360. v-html="subQuesOption.optionBody"
  361. ></span>
  362. </div>
  363. </div>
  364. <div v-show="quesAnswerShow">
  365. <span>答案:</span>
  366. <span v-html="subQuestion.quesAnswer"></span>
  367. </div>
  368. </div>
  369. <div v-show="quesTagShow" class="ques-tag-main">
  370. <div
  371. v-for="(subQuestionTag, tagIndex) in subQuestion.tags"
  372. :key="tagIndex"
  373. class="ques-tag-container"
  374. >
  375. <div class="ques-tag">
  376. <div class="ques-tag-title">{{ subQuestionTag.tag }}</div>
  377. <div>{{ subQuestionTag.content }}</div>
  378. </div>
  379. </div>
  380. </div>
  381. </div>
  382. </div>
  383. </div>
  384. </div>
  385. </div>
  386. </div>
  387. <div class="text-left">
  388. <!-- 编辑大题弹框 -->
  389. <el-dialog
  390. v-loading.body="detailLoading"
  391. width="560px"
  392. title="大题名称编辑"
  393. element-loading-text="保存中。。。"
  394. :visible.sync="paperDatailDialog"
  395. @close="closeQuesDialog"
  396. >
  397. <el-form
  398. :model="editpaperDetail"
  399. label-position="right"
  400. label-width="80px"
  401. >
  402. <el-row :gutter="10">
  403. <el-col :xs="10" :sm="10" :md="10" :lg="10">
  404. <el-form-item label="大题名称" placeholder="大题名称">
  405. <el-input
  406. v-model="editpaperDetail.name"
  407. class="dialog_input_width"
  408. />
  409. </el-form-item>
  410. </el-col>
  411. </el-row>
  412. <el-row>
  413. <el-col>
  414. <el-form-item label="大题描述" placeholder="大题描述">
  415. <ckeditor v-model="editpaperDetail.description"></ckeditor>
  416. </el-form-item>
  417. </el-col>
  418. </el-row>
  419. <el-row>
  420. <el-form-item>
  421. <el-button
  422. type="primary"
  423. @click="savePaperDatail(editpaperDetail)"
  424. >保存</el-button
  425. >
  426. <el-button @click="closePaperDatailDialog()">取消</el-button>
  427. </el-form-item>
  428. </el-row>
  429. </el-form>
  430. </el-dialog>
  431. <!-- 编辑试题弹框 -->
  432. <el-dialog
  433. v-loading.body="dialogLoading"
  434. title="试题编辑"
  435. element-loading-text="保存中。。。"
  436. :visible.sync="quesDialog"
  437. @close="closeQuesDialog"
  438. >
  439. <el-form :model="quesModel" label-position="right" label-width="80px">
  440. <el-row :gutter="10">
  441. <el-col :xs="10" :sm="10" :md="10" :lg="10">
  442. <el-form-item label="题型">
  443. <el-select
  444. v-model="quesModel.questionType"
  445. :disabled="true"
  446. placeholder="请输入题型"
  447. >
  448. <el-option
  449. v-for="item in questionTypes"
  450. :key="item.value"
  451. :label="item.label"
  452. :value="item.value"
  453. >
  454. </el-option>
  455. </el-select>
  456. </el-form-item>
  457. </el-col>
  458. <el-col :xs="10" :sm="10" :md="10" :lg="10">
  459. <el-form-item label="分值">
  460. <el-input-number
  461. v-model="quesModel.score"
  462. placeholder="分值"
  463. :precision="1"
  464. :min="0"
  465. :disabled="isNested(quesModel.questionType)"
  466. ></el-input-number>
  467. </el-form-item>
  468. </el-col>
  469. </el-row>
  470. <!-- create by weiwenhai 添加难度,公开度,试题属性 -->
  471. <el-row :gutter="10">
  472. <el-col :xs="10" :sm="10" :md="10" :lg="10">
  473. <el-form-item label="难度">
  474. <el-select
  475. v-model="quesModel.difficultyDegree"
  476. placeholder="请输入难度"
  477. :disabled="
  478. isNested(quesModel.questionType) ? true : updatePorperty
  479. "
  480. >
  481. <el-option
  482. v-for="item in difficultyDegreeList"
  483. :key="item.value"
  484. :label="item.label"
  485. :value="item.value"
  486. >
  487. </el-option>
  488. </el-select>
  489. </el-form-item>
  490. </el-col>
  491. <el-col :xs="10" :sm="10" :md="10" :lg="10">
  492. <el-form-item label="公开度">
  493. <el-select
  494. v-model="quesModel.publicity"
  495. placeholder="请输入公开度"
  496. :disabled="updatePorperty"
  497. >
  498. <el-option
  499. v-for="item in publicityList"
  500. :key="item.value"
  501. :label="item.label"
  502. :value="item.value"
  503. >
  504. </el-option>
  505. </el-select>
  506. </el-form-item>
  507. </el-col>
  508. <el-col
  509. v-if="quesModel.questionType == 'TEXT_ANSWER_QUESTION'"
  510. :xs="10"
  511. :sm="10"
  512. :md="10"
  513. :lg="10"
  514. >
  515. <el-form-item label="作答类型">
  516. <el-select
  517. v-model="quesModel.answerType"
  518. :disabled="updatePorperty"
  519. >
  520. <el-option
  521. v-for="item in answerTypes"
  522. :key="item.value"
  523. :label="item.label"
  524. :value="item.value"
  525. >
  526. </el-option>
  527. </el-select>
  528. </el-form-item>
  529. </el-col>
  530. <el-col
  531. v-if="quesModel.questionType && !isNested(quesModel.questionType)"
  532. :xs="10"
  533. :sm="10"
  534. :md="10"
  535. :lg="10"
  536. >
  537. <el-form-item label="时长">
  538. <el-input-number
  539. v-model="quesModel.control.maxAnswerTime"
  540. size="small"
  541. :precision="0"
  542. :min="1"
  543. :disabled="updatePorperty"
  544. ></el-input-number>
  545. </el-form-item>
  546. </el-col>
  547. <el-col
  548. v-if="isMatchingQuestion(quesModel.questionType)"
  549. :xs="10"
  550. :sm="10"
  551. :md="10"
  552. :lg="10"
  553. >
  554. <el-form-item label="答题模式">
  555. <el-select
  556. v-model="quesModel.quesParam.matchingMode"
  557. :disabled="updatePorperty"
  558. >
  559. <el-option
  560. v-for="item in matchingModes"
  561. :key="item.value"
  562. :label="item.label"
  563. :value="item.value"
  564. >
  565. </el-option>
  566. </el-select>
  567. </el-form-item>
  568. </el-col>
  569. </el-row>
  570. <el-row :gutter="10">
  571. <el-col :xs="20" :sm="20" :md="20" :lg="20">
  572. <el-form-item label="属性列表">
  573. <el-tooltip
  574. v-for="(content, propIndex) in quesModel.quesProperties"
  575. :key="propIndex"
  576. placement="top"
  577. >
  578. <div slot="content">
  579. <span v-if="content.firstProperty != null"
  580. >一级属性:{{ content.firstProperty.name }}({{
  581. content.firstProperty.code
  582. }})</span
  583. ><br />
  584. <span v-if="content.secondProperty != null"
  585. >二级属性:{{ content.secondProperty.name }}({{
  586. content.secondProperty.code
  587. }})</span
  588. >
  589. </div>
  590. <span>
  591. <el-tag
  592. :key="content.id"
  593. style="margin-right: 5px"
  594. :closable="!updatePorperty"
  595. type="primary"
  596. @close="handleClose(content)"
  597. >
  598. {{ content.courseProperty.name }}
  599. </el-tag>
  600. </span>
  601. </el-tooltip>
  602. </el-form-item>
  603. </el-col>
  604. </el-row>
  605. <el-row>
  606. <el-col :span="6">
  607. <el-form-item label="属性名" label-width="60px">
  608. <el-select
  609. v-model="coursePropertyId"
  610. placeholder="属性名"
  611. class="property_with"
  612. :disabled="updatePorperty"
  613. @change="searchFirst"
  614. >
  615. <el-option label="请选择" value=""></el-option>
  616. <el-option
  617. v-for="item in coursePropertyList"
  618. :key="item.id"
  619. :label="item.name"
  620. :value="item.id"
  621. >
  622. </el-option>
  623. </el-select>
  624. </el-form-item>
  625. </el-col>
  626. <el-col :span="6">
  627. <el-form-item label="一级" label-width="48px">
  628. <el-select
  629. v-model="firstPropertyId"
  630. placeholder="一级"
  631. class="property_with"
  632. :disabled="updatePorperty"
  633. @change="searchSecond"
  634. >
  635. <el-option label="请选择" value=""></el-option>
  636. <el-option
  637. v-for="item in firstPropertyList"
  638. :key="item.id"
  639. :label="item.name + '(' + item.code + ')'"
  640. :value="item.id"
  641. >
  642. </el-option>
  643. </el-select>
  644. </el-form-item>
  645. </el-col>
  646. <el-col :span="6">
  647. <el-form-item label="二级" label-width="48px">
  648. <el-select
  649. v-model="secondPropertyId"
  650. placeholder="二级"
  651. class="property_with"
  652. :disabled="updatePorperty"
  653. >
  654. <el-option label="请选择" value=""></el-option>
  655. <el-option
  656. v-for="item in secondPropertyList"
  657. :key="item.id"
  658. :label="item.name + '(' + item.code + ')'"
  659. :value="item.id"
  660. >
  661. </el-option>
  662. </el-select>
  663. </el-form-item>
  664. </el-col>
  665. <el-col :span="6">
  666. <el-form-item>
  667. <el-button
  668. type="primary"
  669. style="margin-left: -50px"
  670. :disabled="updatePorperty"
  671. @click="insertProperty"
  672. ><i class="el-icon-plus"></i>新增属性
  673. </el-button>
  674. </el-form-item>
  675. </el-col>
  676. </el-row>
  677. <!-- end by weiwenhai -->
  678. <div>
  679. <el-row>
  680. <el-col>
  681. <el-form-item label="题目">
  682. <ckeditor v-model="quesModel.quesBody"></ckeditor>
  683. </el-form-item>
  684. </el-col>
  685. </el-row>
  686. <el-form-item
  687. v-for="(quesOption, optIndex) in quesModel.quesOptions"
  688. :key="optIndex"
  689. >
  690. <el-col :span="2">
  691. <div
  692. v-if="
  693. !quesModel.parentType ||
  694. !isMatchingQuestion(quesModel.parentType) ||
  695. !isInOtherSelect(optIndex, quesModel)
  696. "
  697. >
  698. <el-radio
  699. v-if="quesModel.questionType === 'SINGLE_ANSWER_QUESTION'"
  700. v-model="singleRightAnswer"
  701. :label="optIndex | optionOrderWordFilter"
  702. ></el-radio>
  703. <el-checkbox
  704. v-if="quesModel.questionType === 'MULTIPLE_ANSWER_QUESTION'"
  705. v-model="multipleRightAnswer"
  706. :label="optIndex | optionOrderWordFilter"
  707. ></el-checkbox>
  708. <span v-if="isMatchingQuestion(quesModel.questionType)">{{
  709. optIndex | optionOrderWordFilter
  710. }}</span>
  711. </div>
  712. <div
  713. v-if="
  714. quesModel.parentType &&
  715. isMatchingQuestion(quesModel.parentType) &&
  716. isInOtherSelect(optIndex, quesModel)
  717. "
  718. >
  719. <el-tooltip
  720. class="item"
  721. effect="dark"
  722. :content="otherSelect(optIndex, quesModel)"
  723. placement="top-start"
  724. >
  725. <el-radio
  726. v-if="quesModel.questionType === 'SINGLE_ANSWER_QUESTION'"
  727. v-model="singleRightAnswer"
  728. :disabled="true"
  729. :label="optIndex | optionOrderWordFilter"
  730. ></el-radio>
  731. <el-checkbox
  732. v-if="
  733. quesModel.questionType === 'MULTIPLE_ANSWER_QUESTION'
  734. "
  735. v-model="multipleRightAnswer"
  736. :disabled="true"
  737. :label="optIndex | optionOrderWordFilter"
  738. ></el-checkbox>
  739. <span v-if="isMatchingQuestion(quesModel.questionType)">{{
  740. optIndex | optionOrderWordFilter
  741. }}</span>
  742. </el-tooltip>
  743. </div>
  744. </el-col>
  745. <el-col
  746. v-if="
  747. !quesModel.parentType ||
  748. !isMatchingQuestion(quesModel.parentType)
  749. "
  750. :span="20"
  751. >
  752. <ckeditor v-model="quesOption.optionBody"></ckeditor>
  753. </el-col>
  754. <el-col
  755. v-if="
  756. quesModel.parentType &&
  757. isMatchingQuestion(quesModel.parentType)
  758. "
  759. :span="20"
  760. >
  761. <span v-html="quesOption.optionBody"></span>
  762. </el-col>
  763. <el-col
  764. v-if="
  765. !quesModel.parentType ||
  766. !isMatchingQuestion(quesModel.parentType)
  767. "
  768. :span="2"
  769. >
  770. <i
  771. class="el-icon-delete"
  772. title="删除"
  773. @click.prevent="removeQuesOption(quesOption)"
  774. ></i>
  775. </el-col>
  776. </el-form-item>
  777. <div
  778. v-if="
  779. quesModel.questionType == 'TEXT_ANSWER_QUESTION' ||
  780. quesModel.questionType == 'FILL_BLANK_QUESTION'
  781. "
  782. >
  783. <el-form-item label="答案">
  784. <ckeditor v-model="quesModel.quesAnswer"></ckeditor>
  785. </el-form-item>
  786. </div>
  787. <!-- 单选或多选 -->
  788. <div
  789. v-if="
  790. quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
  791. quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION'
  792. "
  793. >
  794. <el-form-item label="答案">
  795. <span v-html="answer"></span>
  796. </el-form-item>
  797. </div>
  798. <div v-if="quesModel.questionType == 'BOOL_ANSWER_QUESTION'">
  799. <el-row>
  800. <el-col>
  801. <el-form-item label="答案" prop="quesAnswer">
  802. <el-select
  803. v-model="quesModel.quesAnswer"
  804. placeholder="请选择"
  805. >
  806. <el-option
  807. v-for="op in options"
  808. :key="op"
  809. :label="op"
  810. :value="op"
  811. >
  812. </el-option>
  813. </el-select>
  814. </el-form-item>
  815. </el-col>
  816. </el-row>
  817. </div>
  818. </div>
  819. <div
  820. :class="{
  821. margin_left_30:
  822. quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
  823. quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION',
  824. margin_left_40: !(
  825. quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
  826. quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION'
  827. ),
  828. }"
  829. >
  830. <el-button
  831. v-if="
  832. (quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
  833. quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION' ||
  834. isMatchingQuestion(quesModel.questionType)) &&
  835. !isMatchingQuestion(quesModel.parentType)
  836. "
  837. type="primary"
  838. @click="addQuesOption"
  839. ><i class="el-icon-plus"></i> 新增选项
  840. </el-button>
  841. <el-button type="primary" @click="savePaperDetailUnit()"
  842. >保存</el-button
  843. >
  844. <el-button @click="closeQuesDialog">取消</el-button>
  845. </div>
  846. </el-form>
  847. </el-dialog>
  848. <!-- 考试说明弹框 -->
  849. <el-dialog title="考试说明编辑" :visible.sync="paperRemarkDialog">
  850. <el-form label-position="right" label-width="80px">
  851. <el-row :gutter="10">
  852. <el-col :xs="10" :sm="10" :md="10" :lg="10">
  853. <el-form-item label="考试说明">
  854. <div style="width: 550px">
  855. <ckeditor
  856. v-model="examRemark"
  857. :display="display"
  858. :width="wValue"
  859. :height="hValue"
  860. ></ckeditor>
  861. </div>
  862. </el-form-item>
  863. </el-col>
  864. </el-row>
  865. <div style="margin-top: 20px; margin-left: 40%">
  866. <el-button type="primary" @click="savePaperRemark">保存</el-button>
  867. <el-button @click="closPaperRemark">取消</el-button>
  868. </div>
  869. </el-form>
  870. </el-dialog>
  871. <!-- 上传音频弹框 -->
  872. <el-dialog
  873. title="上传音频文件"
  874. :visible.sync="dialogRadioFile"
  875. :before-close="closeAudioDialog"
  876. >
  877. <form
  878. id="radioForm"
  879. method="post"
  880. action=""
  881. enctype="multipart/form-data"
  882. >
  883. <input
  884. id="radioFile"
  885. name="files"
  886. type="file"
  887. value="上传音频文件"
  888. webkitdirectory
  889. />
  890. <el-button type="warning" @click="checkFile">检查文件名</el-button>
  891. <el-button
  892. type="info"
  893. :loading="uploadAudioLoading"
  894. :disabled="isUpload || uploadAudioLoading"
  895. @click="uploadAudioFile"
  896. >
  897. <span v-show="!uploadAudioLoading">开始上传</span>
  898. <span v-show="uploadAudioLoading">正在上传中...</span>
  899. </el-button>
  900. </form>
  901. <div v-if="checkResult" style="margin-top: 20px">
  902. <span>检查结果:</span><br /><br />
  903. <span v-show="message == 'OK!'" style="color: #13ce66">OK!</span>
  904. <span v-show="message != 'OK!'" style="color: #ff4949">{{
  905. message
  906. }}</span>
  907. </div>
  908. </el-dialog>
  909. <el-dialog
  910. title="上传答案文件"
  911. :visible.sync="dialogAnswerFile"
  912. :before-close="closeAnswerDialog"
  913. >
  914. <form
  915. id="answerForm"
  916. method="post"
  917. action=""
  918. enctype="multipart/form-data"
  919. >
  920. <input
  921. id="answerFile"
  922. name="answerFiles"
  923. type="file"
  924. value="上传答案文件"
  925. accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  926. />
  927. <el-button type="info" @click="downAnswerTemplate">
  928. <span>下载模板</span>
  929. </el-button>
  930. <el-button
  931. type="info"
  932. :loading="uploadAnswerLoading"
  933. :disabled="uploadAnswerLoading"
  934. @click="uploadAnswerFile"
  935. >
  936. <span v-show="!uploadAnswerLoading">开始上传</span>
  937. <span v-show="uploadAnswerLoading">正在上传中...</span>
  938. </el-button>
  939. </form>
  940. <div style="margin-top: 20px">
  941. <span v-show="answerMessage != ''" style="color: #ff4949">{{
  942. answerMessage
  943. }}</span>
  944. </div>
  945. </el-dialog>
  946. </div>
  947. </div>
  948. </template>
  949. <script>
  950. import { QUESTION_API } from "@/constants/constants";
  951. import { isEmptyStr, QUESTION_TYPES } from "../constants/constants";
  952. import { mapState } from "vuex";
  953. import reduplicate_mark from "../component/reduplicate_mark.vue";
  954. import randomColor from "randomcolor";
  955. import ckeditor from "../component/ckeditor.vue";
  956. export default {
  957. name: "EditPaperApp",
  958. components: {
  959. reduplicate_mark,
  960. ckeditor,
  961. },
  962. data() {
  963. return {
  964. quesAnswerShow: true,
  965. quesTagShow: true,
  966. hValue: "100px",
  967. wValue: "500px",
  968. display: "block",
  969. uploadAction: "",
  970. fileList: [],
  971. answerFileList: [],
  972. paperId: "",
  973. paperDetailId: "",
  974. editPaperDetailUnit: "",
  975. quesDialog: false,
  976. paperDatailDialog: false,
  977. paperRemarkDialog: false,
  978. parentView: "",
  979. paper: {
  980. course: {
  981. code: "",
  982. name: "",
  983. },
  984. examRemark: "",
  985. },
  986. loading: false,
  987. dialogLoading: false,
  988. detailLoading: false,
  989. uploadAudioLoading: false,
  990. uploadAnswerLoading: false,
  991. questionTypes: QUESTION_TYPES,
  992. questionType: "",
  993. quesModel: { quesProperties: [] },
  994. editpaperDetail: {},
  995. reduplicateQuestions: [],
  996. reduplicateGroup: [],
  997. reduplicateQuesColor: [],
  998. singleRightAnswer: "", //接收单选答案
  999. multipleRightAnswer: [], //接收多选答案
  1000. options: ["正确", "错误"],
  1001. duplicateLoading: false,
  1002. dialogRadioFile: false,
  1003. dialogAnswerFile: false,
  1004. isUpload: true,
  1005. isUploadAnswer: true,
  1006. message: "",
  1007. answerMessage: "",
  1008. checkResult: false,
  1009. checkResultAnswer: false,
  1010. fileNameList: [],
  1011. defaultColor: [
  1012. "Red",
  1013. "Blue",
  1014. "LimeGreen",
  1015. "GoldenRod",
  1016. "Black",
  1017. "BlueViolet",
  1018. "Chocolate",
  1019. "DarkCyan",
  1020. "HotPink",
  1021. "Orange",
  1022. "IndianRed",
  1023. "Indigo",
  1024. "Green",
  1025. "Aqua",
  1026. "CadetBlue",
  1027. "SkyBlue",
  1028. "SlateBlue",
  1029. "SlateGray",
  1030. "Tomato",
  1031. "VioletRed",
  1032. ],
  1033. difficultyDegreeList: [
  1034. { label: 0.1, value: 0.1 },
  1035. { label: 0.2, value: 0.2 },
  1036. { label: 0.3, value: 0.3 },
  1037. { label: 0.4, value: 0.4 },
  1038. { label: 0.5, value: 0.5 },
  1039. { label: 0.6, value: 0.6 },
  1040. { label: 0.7, value: 0.7 },
  1041. { label: 0.8, value: 0.8 },
  1042. { label: 0.9, value: 0.9 },
  1043. { label: 1.0, value: 1.0 },
  1044. ],
  1045. publicityList: [
  1046. { label: "公开", value: true },
  1047. { label: "非公开", value: false },
  1048. ],
  1049. answerTypes: [
  1050. { label: "文本", value: "DIVERSIFIED_TEXT" },
  1051. { label: "音频", value: "SINGLE_AUDIO" },
  1052. ],
  1053. matchingTypes: [
  1054. { label: "填词", value: 1 },
  1055. { label: "段落", value: 2 },
  1056. ],
  1057. matchingModes: [
  1058. { label: "单用", value: 1 },
  1059. { label: "复用", value: 2 },
  1060. ],
  1061. coursePropertyList: [],
  1062. coursePropertyId: "", //课程属性名
  1063. firstPropertyList: [], //一级属性集合
  1064. firstPropertyId: "", //一级属性id
  1065. secondPropertyList: [], //二级属性集合
  1066. secondPropertyId: "", //二级属性id
  1067. examRemark: "",
  1068. showQuestions: [],
  1069. showButtons: [],
  1070. };
  1071. },
  1072. computed: {
  1073. ...mapState({
  1074. user: (state) => state.user,
  1075. }),
  1076. updatePorperty() {
  1077. return false;
  1078. },
  1079. answer() {
  1080. if (this.quesModel.questionType == "SINGLE_ANSWER_QUESTION") {
  1081. return this.singleRightAnswer;
  1082. } else if (this.quesModel.questionType == "MULTIPLE_ANSWER_QUESTION") {
  1083. var obj = this.multipleRightAnswer;
  1084. return obj.sort().toString();
  1085. }
  1086. return this.quesModel.quesAnswer;
  1087. },
  1088. },
  1089. created() {
  1090. let qt = sessionStorage.getItem("quesTagShow");
  1091. if (qt) {
  1092. this.quesTagShow = qt == "true";
  1093. }
  1094. let qa = sessionStorage.getItem("quesAnswerShow");
  1095. if (qa) {
  1096. this.quesAnswerShow = qa == "true";
  1097. }
  1098. document.getElementsByTagName("body")[0].style = "";
  1099. this.paperId = this.$route.params.id;
  1100. this.parentView = this.$route.params.parentView;
  1101. this.initPaper();
  1102. this.getreduplicateQuestions();
  1103. this.uploadAction = QUESTION_API + "/uploadRadio/" + this.paperId;
  1104. this.uploadHeaders = {
  1105. key: this.user.key,
  1106. token: this.user.token,
  1107. };
  1108. },
  1109. methods: {
  1110. quesAnswerShowHide() {
  1111. this.quesAnswerShow = !this.quesAnswerShow;
  1112. sessionStorage.setItem("quesAnswerShow", this.quesAnswerShow);
  1113. },
  1114. quesTagShowHide() {
  1115. this.quesTagShow = !this.quesTagShow;
  1116. sessionStorage.setItem("quesTagShow", this.quesTagShow);
  1117. },
  1118. isMatchingQuestion(questionType) {
  1119. if (
  1120. questionType == "PARAGRAPH_MATCHING" ||
  1121. questionType == "BANKED_CLOZE"
  1122. ) {
  1123. return true;
  1124. } else {
  1125. return false;
  1126. }
  1127. },
  1128. isNested(questionType) {
  1129. if (
  1130. questionType == "PARAGRAPH_MATCHING" ||
  1131. questionType == "BANKED_CLOZE" ||
  1132. questionType == "CLOZE" ||
  1133. questionType == "READING_COMPREHENSION" ||
  1134. questionType == "LISTENING_QUESTION"
  1135. ) {
  1136. return true;
  1137. } else {
  1138. return false;
  1139. }
  1140. },
  1141. otherSelect(optIndex, quesModel) {
  1142. return "该选项被第" + quesModel.optionsSelected[optIndex + 1] + "题选用";
  1143. },
  1144. isInOtherSelect(optIndex, quesModel) {
  1145. if (quesModel.parentQuesParam.matchingMode != 1) {
  1146. return false;
  1147. }
  1148. if (!quesModel.optionsSelected) {
  1149. return false;
  1150. }
  1151. if (!quesModel.optionsSelected[optIndex + 1]) {
  1152. return false;
  1153. }
  1154. if (
  1155. quesModel.optionsSelected[optIndex + 1].includes(quesModel.subNumber)
  1156. ) {
  1157. return false;
  1158. }
  1159. return true;
  1160. },
  1161. movePaperDetail(detail, vector) {
  1162. let vectorStr = vector == "up" ? "上移" : "下移";
  1163. this.$alert("您确定" + vectorStr + "吗?", "提示", {
  1164. confirmButtonText: "确定",
  1165. callback: (action) => {
  1166. if (action == "confirm") {
  1167. this.loading = true;
  1168. this.$http
  1169. .put(
  1170. QUESTION_API +
  1171. "/paperDetail/" +
  1172. this.paperId +
  1173. "/" +
  1174. detail.id +
  1175. "/" +
  1176. vector
  1177. )
  1178. .then(() => {
  1179. this.initPaper();
  1180. this.loading = true;
  1181. this.$notify({
  1182. message: vectorStr + "成功",
  1183. type: "success",
  1184. });
  1185. this.loading = false;
  1186. });
  1187. }
  1188. },
  1189. });
  1190. },
  1191. showUp(detail) {
  1192. if (this.paper.paperDetails.length <= 1) {
  1193. return false;
  1194. }
  1195. if (detail.id != this.paper.paperDetails[0].id) {
  1196. return true;
  1197. } else {
  1198. return false;
  1199. }
  1200. },
  1201. showDown(detail) {
  1202. if (this.paper.paperDetails.length <= 1) {
  1203. return false;
  1204. }
  1205. if (
  1206. detail.id !=
  1207. this.paper.paperDetails[this.paper.paperDetails.length - 1].id
  1208. ) {
  1209. return true;
  1210. } else {
  1211. return false;
  1212. }
  1213. },
  1214. downAnswerTemplate() {
  1215. var key = this.user.key;
  1216. var token = this.user.token;
  1217. window.open(
  1218. QUESTION_API + "/paper/answer/template?$key=" + key + "&$token=" + token
  1219. );
  1220. },
  1221. openAnswerDialog() {
  1222. this.checkResultAnswer = false;
  1223. this.isUploadAnswer = true;
  1224. if (document.getElementById("answerFile")) {
  1225. document.getElementById("answerFile").value = "";
  1226. }
  1227. this.dialogAnswerFile = true;
  1228. this.answerFileList = [];
  1229. },
  1230. closeAnswerDialog() {
  1231. this.answerMessage = "";
  1232. this.dialogAnswerFile = this.uploadAnswerLoading;
  1233. },
  1234. uploadAnswerFile() {
  1235. this.answerMessage = "";
  1236. var fileList = document.getElementById("answerFile").files;
  1237. if (fileList.length == 0) {
  1238. this.answerMessage = "请选择文件!";
  1239. return;
  1240. }
  1241. let param = new FormData();
  1242. //循环添加到formData中
  1243. for (var i = 0; i < fileList.length; i++) {
  1244. var file = fileList[i];
  1245. param.append("dataFile", file, file.name);
  1246. }
  1247. let config = {
  1248. headers: { "Content-Type": "multipart/form-data" },
  1249. };
  1250. this.uploadAnswerLoading = true;
  1251. this.$http
  1252. .post(
  1253. QUESTION_API + "/paper/answer/import/" + this.paperId,
  1254. param,
  1255. config
  1256. )
  1257. .then(() => {
  1258. this.dialogAnswerFile = false;
  1259. this.uploadAnswerLoading = false;
  1260. this.checkResultAnswer = false;
  1261. this.isUploadAnswer = true;
  1262. document.getElementById("answerFile").value = "";
  1263. this.initPaper();
  1264. })
  1265. .catch((error) => {
  1266. this.answerMessage = error.response.data.desc;
  1267. document.getElementById("answerFile").value = "";
  1268. this.uploadAnswerLoading = false;
  1269. });
  1270. },
  1271. //隐藏大题下的所有小题
  1272. hideContent(index) {
  1273. console.log("up");
  1274. this.showQuestions[index].is_show = false;
  1275. this.showButtons[index].up = false;
  1276. },
  1277. //展开大题下所有小题
  1278. showContent(index) {
  1279. console.log("down");
  1280. this.showQuestions[index].is_show = true;
  1281. this.showButtons[index].up = true;
  1282. },
  1283. quesMouseOver(index) {
  1284. document.getElementById(index).style.visibility = "visible";
  1285. },
  1286. quesMouseOut(index) {
  1287. document.getElementById(index).style.visibility = "hidden";
  1288. },
  1289. selectQues(id) {
  1290. this.paperDetailId = id;
  1291. var courseCode = this.paper.course.code;
  1292. var courseName = this.paper.course.name;
  1293. this.$router.push({
  1294. path:
  1295. "/select_question/" +
  1296. this.paper.id +
  1297. "/" +
  1298. courseCode +
  1299. "/" +
  1300. encodeURIComponent(courseName) +
  1301. "/" +
  1302. this.paperDetailId +
  1303. "/" +
  1304. this.parentView,
  1305. });
  1306. },
  1307. //打开编辑大题题目弹窗
  1308. openEditPaperDetail(paperDetail) {
  1309. this.paperDatailDialog = true;
  1310. this.editpaperDetail = Object.assign({}, paperDetail); //浅拷贝
  1311. },
  1312. //关闭编辑大题题目弹窗
  1313. closePaperDatailDialog() {
  1314. this.paperDatailDialog = false;
  1315. this.editpaperDetail = {};
  1316. },
  1317. //保存大题题目信息
  1318. savePaperDatail(editpaperDetail) {
  1319. this.detailLoading = true;
  1320. var paperId = this.paper.id;
  1321. this.$http
  1322. .post(QUESTION_API + "/updatePaperDetail/" + paperId, editpaperDetail)
  1323. .then(() => {
  1324. this.$notify({
  1325. message: "保存成功",
  1326. type: "success",
  1327. });
  1328. this.detailLoading = false;
  1329. this.closePaperDatailDialog();
  1330. this.initPaper();
  1331. });
  1332. },
  1333. //初始化试卷
  1334. initPaper() {
  1335. const scrollPosition =
  1336. document.documentElement.scrollTop || document.body.scrollTop;
  1337. this.loading = true;
  1338. this.paper = {
  1339. course: {
  1340. code: "",
  1341. name: "",
  1342. },
  1343. };
  1344. this.$http
  1345. .get(QUESTION_API + "/paper/" + this.paperId)
  1346. .then((response) => {
  1347. this.paper = response.data;
  1348. //查询所有课程属性名
  1349. this.initCourseProperty(this.paper.course.code);
  1350. //将所有小题分为公开和非公开
  1351. if (this.paper.paperDetails && this.paper.paperDetails.length > 0) {
  1352. for (let paperDetil of this.paper.paperDetails) {
  1353. this.showQuestions.push({ is_show: true });
  1354. this.showButtons.push({ up: true });
  1355. paperDetil.pubCount = 0;
  1356. paperDetil.noPubCount = 0;
  1357. if (
  1358. paperDetil.paperDetailUnits &&
  1359. paperDetil.paperDetailUnits.length > 0
  1360. ) {
  1361. for (let paperDetilUt of paperDetil.paperDetailUnits) {
  1362. if (!this.isNested(paperDetilUt.question.questionType)) {
  1363. //非套题
  1364. if (paperDetilUt.question.publicity) {
  1365. paperDetil.pubCount = paperDetil.pubCount + 1;
  1366. } else {
  1367. paperDetil.noPubCount = paperDetil.noPubCount + 1;
  1368. }
  1369. } else {
  1370. //循环所有子题
  1371. for (let ques of paperDetilUt.question.subQuestions) {
  1372. if (ques.publicity) {
  1373. paperDetil.pubCount = paperDetil.pubCount + 1;
  1374. } else {
  1375. paperDetil.noPubCount = paperDetil.noPubCount + 1;
  1376. }
  1377. }
  1378. }
  1379. }
  1380. }
  1381. }
  1382. }
  1383. setTimeout(() => {
  1384. document.documentElement.scrollTop = document.body.scrollTop =
  1385. scrollPosition;
  1386. console.log(scrollPosition);
  1387. }, 1000);
  1388. this.loading = false;
  1389. });
  1390. },
  1391. //查询所有课程属性名
  1392. initCourseProperty(courseCode) {
  1393. this.$http
  1394. .get(QUESTION_API + "/courseProperty/enable/" + courseCode)
  1395. .then((response) => {
  1396. this.coursePropertyList = response.data;
  1397. });
  1398. },
  1399. //删除大题
  1400. deletePaperDetail(paperDetailsId) {
  1401. //先判断大题下面是否还有小题
  1402. var count = 0;
  1403. for (var i = 0, imax = this.paper.paperDetails.length; i < imax; i++) {
  1404. if (paperDetailsId == this.paper.paperDetails[i].id) {
  1405. if (this.paper.paperDetails[i].paperDetailUnits) {
  1406. count += this.paper.paperDetails[i].paperDetailUnits.length;
  1407. break;
  1408. }
  1409. }
  1410. }
  1411. if (count == 0) {
  1412. this.$alert("您确定删除吗?", "提示", {
  1413. confirmButtonText: "确定",
  1414. callback: (action) => {
  1415. if (action == "confirm") {
  1416. this.loading = true;
  1417. this.$http
  1418. .delete(
  1419. QUESTION_API +
  1420. "/paperDetail/" +
  1421. this.paperId +
  1422. "/" +
  1423. paperDetailsId
  1424. )
  1425. .then(() => {
  1426. this.initPaper();
  1427. this.loading = true;
  1428. this.$notify({
  1429. message: "删除成功",
  1430. type: "success",
  1431. });
  1432. this.loading = false;
  1433. });
  1434. }
  1435. },
  1436. });
  1437. } else {
  1438. this.$alert("大题下还有小题,不可删除!", "提示", {
  1439. confirmButtonText: "确定",
  1440. callback: () => {},
  1441. });
  1442. }
  1443. },
  1444. quesShow(id) {
  1445. if (this.reduplicateGroup.length < 1) {
  1446. return true;
  1447. }
  1448. for (var i = 0, imax = this.reduplicateGroup.length; i < imax; i++) {
  1449. if (id == this.reduplicateGroup[i]) {
  1450. return true;
  1451. }
  1452. }
  1453. return false;
  1454. },
  1455. reduplicateMarkShow(id) {
  1456. var found = false;
  1457. for (var i = 0, imax = this.reduplicateQuestions.length; i < imax; i++) {
  1458. for (
  1459. var j = 0, jmax = this.reduplicateQuestions[i].length;
  1460. j < jmax;
  1461. j++
  1462. ) {
  1463. if (this.reduplicateQuestions[i][j] == id) {
  1464. found = true;
  1465. break;
  1466. }
  1467. }
  1468. if (found) {
  1469. break;
  1470. }
  1471. }
  1472. return found;
  1473. },
  1474. reduplicateMarkColor(id) {
  1475. for (var i = 0, imax = this.reduplicateQuestions.length; i < imax; i++) {
  1476. for (
  1477. var j = 0, jmax = this.reduplicateQuestions[i].length;
  1478. j < jmax;
  1479. j++
  1480. ) {
  1481. if (this.reduplicateQuestions[i][j] == id) {
  1482. return this.reduplicateQuesColor[i];
  1483. }
  1484. }
  1485. }
  1486. },
  1487. reduplicateMarkCheck(id) {
  1488. for (var i = 0, imax = this.reduplicateGroup.length; i < imax; i++) {
  1489. if (id == this.reduplicateGroup[i]) {
  1490. return true;
  1491. }
  1492. }
  1493. return false;
  1494. },
  1495. reduplicate_mark_check(id, checked) {
  1496. console.log(checked);
  1497. console.log(this.reduplicateQuestions);
  1498. console.log(id);
  1499. if (!checked) {
  1500. for (
  1501. var i = 0, imax = this.reduplicateQuestions.length;
  1502. i < imax;
  1503. i++
  1504. ) {
  1505. for (
  1506. var j = 0, jmax = this.reduplicateQuestions[i].length;
  1507. j < jmax;
  1508. j++
  1509. ) {
  1510. if (this.reduplicateQuestions[i][j] == id) {
  1511. this.reduplicateGroup = [];
  1512. for (
  1513. var k = 0, kmax = this.reduplicateQuestions[i].length;
  1514. k < kmax;
  1515. k++
  1516. ) {
  1517. this.reduplicateGroup.push(this.reduplicateQuestions[i][k]);
  1518. }
  1519. return;
  1520. }
  1521. }
  1522. }
  1523. } else {
  1524. this.reduplicateGroup = [];
  1525. }
  1526. },
  1527. //编辑题目
  1528. editQues(paperDetailUnit, question) {
  1529. console.log("question:", question);
  1530. this.coursePropertyId = "";
  1531. this.firstPropertyId = "";
  1532. this.secondPropertyId = "";
  1533. this.editPaperDetailUnit = paperDetailUnit;
  1534. this.quesModel = JSON.parse(JSON.stringify(question)); //深拷贝
  1535. if (!this.quesModel.control) {
  1536. this.quesModel.control = {};
  1537. }
  1538. this.quesModel.score = paperDetailUnit.score;
  1539. //如果是套题下面的小题编辑 ( paperDetailUnit的类型是套题,question的类型不是套题)
  1540. if (
  1541. this.isNested(paperDetailUnit.questionType) &&
  1542. question.questionType != paperDetailUnit.questionType
  1543. ) {
  1544. for (var i = 0; i < paperDetailUnit.question.subQuestions.length; i++) {
  1545. if (
  1546. paperDetailUnit.question.subQuestions[i].id == this.quesModel.id
  1547. ) {
  1548. this.quesModel.score = paperDetailUnit.subScoreList[i];
  1549. this.quesModel.parentType = paperDetailUnit.questionType;
  1550. this.quesModel.optionsSelected = paperDetailUnit.optionsSelected;
  1551. this.quesModel.parentQuesParam = paperDetailUnit.question.quesParam;
  1552. break;
  1553. }
  1554. }
  1555. }
  1556. if (isEmptyStr(this.quesModel.answerType)) {
  1557. this.quesModel.answerType = "DIVERSIFIED_TEXT";
  1558. }
  1559. if (this.quesModel.questionType == "FILL_BLANK_QUESTION") {
  1560. this.quesModel.quesBody = this.quesModel.quesBody.replace(
  1561. /______/g,
  1562. "###"
  1563. );
  1564. }
  1565. if (this.isNested(this.quesModel.questionType)) {
  1566. this.quesModel.quesBody = this.quesModel.quesBody.replace(
  1567. /___([1-9][0-9]*)___/g,
  1568. "##$1##"
  1569. );
  1570. }
  1571. this.assignAnswers(); //给singleRightAnswer或multipleRightAnswer赋值
  1572. this.openQuesDialog();
  1573. },
  1574. //给singleRightAnswer和multipleRightAnswer赋值
  1575. assignAnswers() {
  1576. if (this.quesModel.quesOptions && this.quesModel.quesOptions.length > 0) {
  1577. this.singleRightAnswer = "";
  1578. this.multipleRightAnswer = [];
  1579. for (let i = 0; i < this.quesModel.quesOptions.length; i++) {
  1580. let option = this.quesModel.quesOptions[i];
  1581. if (
  1582. this.quesModel.questionType == "SINGLE_ANSWER_QUESTION" &&
  1583. option.isCorrect == 1
  1584. ) {
  1585. this.singleRightAnswer = String.fromCharCode(65 + i);
  1586. }
  1587. if (
  1588. this.quesModel.questionType == "MULTIPLE_ANSWER_QUESTION" &&
  1589. option.isCorrect == 1
  1590. ) {
  1591. this.multipleRightAnswer.push(String.fromCharCode(65 + i));
  1592. }
  1593. }
  1594. }
  1595. },
  1596. //打开修改试题编辑框
  1597. openQuesDialog() {
  1598. this.quesDialog = true;
  1599. },
  1600. //关闭试题编辑框
  1601. closeQuesDialog() {
  1602. this.quesDialog = false;
  1603. this.quesModel = {};
  1604. },
  1605. //删除属性
  1606. handleClose(tag) {
  1607. this.quesModel.quesProperties.splice(
  1608. this.quesModel.quesProperties.indexOf(tag),
  1609. 1
  1610. );
  1611. },
  1612. //查询一级属性
  1613. searchFirst() {
  1614. this.firstPropertyId = "";
  1615. this.secondPropertyId = "";
  1616. this.secondPropertyList = [];
  1617. if (this.coursePropertyId) {
  1618. for (let courseProperty of this.coursePropertyList) {
  1619. if (courseProperty.id == this.coursePropertyId) {
  1620. this.$http
  1621. .get(QUESTION_API + "/property/first/" + courseProperty.id)
  1622. .then((response) => {
  1623. this.firstPropertyList = response.data;
  1624. });
  1625. }
  1626. }
  1627. }
  1628. },
  1629. //查询二级属性
  1630. searchSecond() {
  1631. this.secondPropertyId = "";
  1632. if (this.firstPropertyId) {
  1633. this.$http
  1634. .get(QUESTION_API + "/property/second/" + this.firstPropertyId)
  1635. .then((response) => {
  1636. this.secondPropertyList = response.data;
  1637. });
  1638. }
  1639. },
  1640. //新增属性
  1641. insertProperty() {
  1642. if (!this.checkInsertPro()) {
  1643. return false;
  1644. }
  1645. var quesProperty = {
  1646. id: "",
  1647. courseProperty: {},
  1648. firstProperty: {},
  1649. secondProperty: {},
  1650. };
  1651. if (
  1652. this.quesModel.quesProperties == null ||
  1653. this.quesModel.quesProperties.length == 0
  1654. ) {
  1655. this.quesModel.quesProperties = [];
  1656. }
  1657. if (this.secondPropertyId) {
  1658. quesProperty.id =
  1659. this.coursePropertyId +
  1660. "-" +
  1661. this.firstPropertyId +
  1662. "-" +
  1663. this.secondPropertyId;
  1664. } else {
  1665. quesProperty.id = this.coursePropertyId + "-" + this.firstPropertyId;
  1666. }
  1667. for (let quesPro of this.quesModel.quesProperties) {
  1668. if (quesPro.id == quesProperty.id) {
  1669. this.$notify({
  1670. message: "该属性已存在,请重新选择",
  1671. type: "error",
  1672. });
  1673. return false;
  1674. }
  1675. }
  1676. for (let courseProperty of this.coursePropertyList) {
  1677. if (courseProperty.id == this.coursePropertyId) {
  1678. quesProperty.courseProperty = courseProperty;
  1679. }
  1680. }
  1681. //取到一级属性对象
  1682. for (let property of this.firstPropertyList) {
  1683. if (property.id == this.firstPropertyId) {
  1684. quesProperty.firstProperty = property;
  1685. }
  1686. }
  1687. //判断是否有二级属性
  1688. if (
  1689. this.secondPropertyList != undefined &&
  1690. this.secondPropertyList.length > 0
  1691. ) {
  1692. if (!this.secondPropertyId) {
  1693. this.$notify({
  1694. message: "请选择二级属性",
  1695. type: "error",
  1696. });
  1697. return false;
  1698. }
  1699. }
  1700. //取到二级属性对象
  1701. for (let property of this.secondPropertyList) {
  1702. if (property.id == this.secondPropertyId) {
  1703. quesProperty.secondProperty = property;
  1704. }
  1705. }
  1706. this.quesModel.quesProperties.push(quesProperty);
  1707. this.quesModel = Object.assign({}, this.quesModel);
  1708. //清空下拉框
  1709. this.coursePropertyId = "";
  1710. this.firstPropertyId = "";
  1711. this.secondPropertyId = "";
  1712. this.firstPropertyList = [];
  1713. this.secondPropertyList = [];
  1714. },
  1715. //新增属性验证
  1716. checkInsertPro() {
  1717. if (!this.coursePropertyId) {
  1718. this.$notify({
  1719. message: "请选择属性",
  1720. type: "error",
  1721. });
  1722. return false;
  1723. }
  1724. if (!this.firstPropertyId) {
  1725. this.$notify({
  1726. message: "请选择一级属性",
  1727. type: "error",
  1728. });
  1729. return false;
  1730. }
  1731. return true;
  1732. },
  1733. //删除选项
  1734. removeQuesOption(option) {
  1735. if (this.quesModel.quesOptions.length == 1) {
  1736. this.$notify({
  1737. message: "不能删除最后一个选项",
  1738. type: "error",
  1739. });
  1740. return;
  1741. }
  1742. this.singleRightAnswer = "";
  1743. this.multipleRightAnswer = [];
  1744. let index = this.quesModel.quesOptions.indexOf(option);
  1745. if (index !== -1) {
  1746. this.quesModel.quesOptions.splice(index, 1);
  1747. }
  1748. if (this.quesModel.quesOptions.length > 0) {
  1749. for (var i = 0; i < this.quesModel.quesOptions.length; i++) {
  1750. var quesOption = this.quesModel.quesOptions[i];
  1751. quesOption["number"] = i + 1;
  1752. if (quesOption.isCorrect == 1) {
  1753. var answerOrderNum = String.fromCharCode(65 + i);
  1754. if (this.quesModel.questionType == "SINGLE_ANSWER_QUESTION") {
  1755. this.singleRightAnswer = answerOrderNum;
  1756. }
  1757. if (this.quesModel.questionType == "MULTIPLE_ANSWER_QUESTION") {
  1758. this.multipleRightAnswer.push(answerOrderNum);
  1759. }
  1760. }
  1761. }
  1762. }
  1763. },
  1764. //新增选项
  1765. addQuesOption() {
  1766. this.quesModel.quesOptions.push({
  1767. number: "",
  1768. optionBody: "",
  1769. isCorrect: "",
  1770. });
  1771. for (var i = 0; i < this.quesModel.quesOptions.length; i++) {
  1772. this.quesModel.quesOptions[i]["number"] = i + 1;
  1773. }
  1774. },
  1775. savePaperDetailUnit() {
  1776. //跟新难度值
  1777. if (this.quesModel.difficultyDegree < 0.4) {
  1778. this.quesModel.difficulty = "难";
  1779. } else if (
  1780. this.quesModel.difficultyDegree > 0.3 &&
  1781. this.quesModel.difficultyDegree < 0.8
  1782. ) {
  1783. this.quesModel.difficulty = "中";
  1784. } else {
  1785. this.quesModel.difficulty = "易";
  1786. }
  1787. this.setRightAnswer();
  1788. if (/^\d+(?=\.{0,1}\d+$|$)/.test(this.quesModel.score)) {
  1789. console.log("正确");
  1790. } else {
  1791. this.$notify({
  1792. message: "分数只能为正数",
  1793. type: "error",
  1794. });
  1795. return;
  1796. }
  1797. if (this.paper.paperType == "GENERATE") {
  1798. this.$confirm(
  1799. "试题内容修改,会影响所有关联试卷,是否确定进行?",
  1800. "提示",
  1801. {
  1802. confirmButtonText: "确定",
  1803. cancelButtonText: "取消",
  1804. type: "warning",
  1805. }
  1806. ).then(() => {
  1807. this.submitPaperDetailUnit();
  1808. });
  1809. } else {
  1810. this.submitPaperDetailUnit();
  1811. }
  1812. },
  1813. submitPaperDetailUnit() {
  1814. let paperDetailUnitExp = {
  1815. id: this.editPaperDetailUnit.id,
  1816. question: this.quesModel,
  1817. score: this.quesModel.score,
  1818. };
  1819. if (
  1820. this.quesModel.quesOptions &&
  1821. this.quesModel.quesOptions.length == 0
  1822. ) {
  1823. this.$confirm("无选项将删除该试题, 是否继续?", "提示", {
  1824. confirmButtonText: "确定",
  1825. cancelButtonText: "取消",
  1826. type: "warning",
  1827. }).then(() => {
  1828. this.dialogLoading = true;
  1829. this.$http
  1830. .delete(
  1831. QUESTION_API +
  1832. "/paper/deleteQuestion/" +
  1833. this.editPaperDetailUnit.id +
  1834. "/" +
  1835. this.quesModel.id
  1836. )
  1837. .then((response) => {
  1838. if (response.data.length > 0) {
  1839. var deleteInfo =
  1840. "该试题被试卷:" +
  1841. response.data.join(" , ") +
  1842. "使用,不能删除";
  1843. this.$notify({
  1844. message: deleteInfo,
  1845. type: "error",
  1846. });
  1847. } else {
  1848. this.$notify({
  1849. message: "保存成功",
  1850. type: "success",
  1851. });
  1852. }
  1853. this.dialogLoading = false;
  1854. });
  1855. });
  1856. } else {
  1857. this.dialogLoading = true;
  1858. //校验音频重复
  1859. let audiomap = new Map();
  1860. let regex = new RegExp(
  1861. '<a id="[^<>]+" name="([^<>]+\\.mp3)"></a>',
  1862. "ig"
  1863. );
  1864. let ret = "";
  1865. let quesBodyStr = paperDetailUnitExp.question.quesBody;
  1866. if (quesBodyStr) {
  1867. while ((ret = regex.exec(quesBodyStr))) {
  1868. if (audiomap.get(ret[1])) {
  1869. this.dialogLoading = false;
  1870. this.$notify({
  1871. type: "error",
  1872. message: "题干中存在相同的音频文件",
  1873. });
  1874. return;
  1875. } else {
  1876. audiomap.set(ret[1], ret[1]);
  1877. }
  1878. }
  1879. }
  1880. let quesAnswerStr = paperDetailUnitExp.question.quesAnswer;
  1881. if (quesAnswerStr) {
  1882. while ((ret = regex.exec(quesAnswerStr))) {
  1883. if (audiomap.get(ret[1])) {
  1884. this.dialogLoading = false;
  1885. this.$notify({
  1886. type: "error",
  1887. message: "答案中存在相同的音频文件",
  1888. });
  1889. return;
  1890. } else {
  1891. audiomap.set(ret[1], ret[1]);
  1892. }
  1893. }
  1894. }
  1895. let quesOptions = paperDetailUnitExp.question.quesOptions;
  1896. if (quesOptions) {
  1897. for (let i = 0; i < quesOptions.length; i++) {
  1898. let quesOptionStr = quesOptions[i].optionBody;
  1899. while ((ret = regex.exec(quesOptionStr))) {
  1900. if (audiomap.get(ret[1])) {
  1901. this.dialogLoading = false;
  1902. this.$notify({
  1903. type: "error",
  1904. message: "选项中存在相同的音频文件",
  1905. });
  1906. return;
  1907. } else {
  1908. audiomap.set(ret[1], ret[1]);
  1909. }
  1910. }
  1911. }
  1912. }
  1913. paperDetailUnitExp.question.quesAnswer = this.answer;
  1914. this.$http
  1915. .put(QUESTION_API + "/paperDetailUnit", paperDetailUnitExp)
  1916. .then(() => {
  1917. this.$notify({
  1918. message: "保存成功",
  1919. type: "success",
  1920. });
  1921. this.dialogLoading = false;
  1922. this.closeQuesDialog();
  1923. this.initPaper();
  1924. })
  1925. .catch((err) => {
  1926. this.dialogLoading = false;
  1927. this.$notify({
  1928. type: "error",
  1929. message: err.response.data.desc,
  1930. });
  1931. });
  1932. }
  1933. },
  1934. //在正确的option上设置isCorrect=1
  1935. setRightAnswer() {
  1936. if (
  1937. !this.quesModel.quesOptions ||
  1938. this.quesModel.quesOptions.length == 0
  1939. ) {
  1940. return false;
  1941. }
  1942. for (var i = 0; i < this.quesModel.quesOptions.length; i++) {
  1943. var option = this.quesModel.quesOptions[i];
  1944. var answerOrderNum = String.fromCharCode(65 + i);
  1945. if (this.quesModel.questionType == "SINGLE_ANSWER_QUESTION") {
  1946. option["isCorrect"] =
  1947. answerOrderNum == this.singleRightAnswer ? 1 : 0;
  1948. }
  1949. if (this.quesModel.questionType == "MULTIPLE_ANSWER_QUESTION") {
  1950. option["isCorrect"] =
  1951. this.multipleRightAnswer.indexOf(answerOrderNum) > -1 ? 1 : 0;
  1952. }
  1953. }
  1954. },
  1955. //删除试题
  1956. deleteQues(paperDetailUnit) {
  1957. let paperDetailUnitId = paperDetailUnit.id;
  1958. if (this.paper.paperType == "GENERATE") {
  1959. this.deleteQues01(paperDetailUnitId);
  1960. } else {
  1961. let questionId = paperDetailUnit.question.id;
  1962. this.deleteQues02(questionId, paperDetailUnitId);
  1963. }
  1964. },
  1965. deleteQues01(paperDetailUnitId) {
  1966. this.$alert("您确定删除吗?", "提示", {
  1967. confirmButtonText: "确定",
  1968. callback: (action) => {
  1969. if (action == "confirm") {
  1970. this.loading = true;
  1971. this.$http
  1972. .delete(QUESTION_API + "/paperDetailUnit/" + paperDetailUnitId)
  1973. .then(() => {
  1974. this.initPaper();
  1975. this.getreduplicateQuestions();
  1976. this.reduplicateGroup = [];
  1977. this.loading = true;
  1978. this.$notify({
  1979. message: "删除成功",
  1980. type: "success",
  1981. });
  1982. this.loading = false;
  1983. });
  1984. }
  1985. },
  1986. });
  1987. },
  1988. deleteQues02(questionId, paperDetailUnitId) {
  1989. this.$alert("您确定删除吗?", "提示", {
  1990. confirmButtonText: "确定",
  1991. callback: (action) => {
  1992. if (action == "confirm") {
  1993. this.loading = true;
  1994. this.$http
  1995. .delete(
  1996. QUESTION_API +
  1997. "/paper/deleteQuestion/" +
  1998. paperDetailUnitId +
  1999. "/" +
  2000. questionId
  2001. )
  2002. .then((response) => {
  2003. if (response.data.length > 0) {
  2004. var deleteInfo =
  2005. "该试题被试卷:" +
  2006. response.data.join(" , ") +
  2007. "使用,不能删除";
  2008. this.$notify({
  2009. message: deleteInfo,
  2010. type: "error",
  2011. });
  2012. } else {
  2013. this.initPaper();
  2014. this.getreduplicateQuestions();
  2015. this.reduplicateGroup = [];
  2016. this.loading = true;
  2017. this.$notify({
  2018. message: "保存成功",
  2019. type: "success",
  2020. });
  2021. }
  2022. this.loading = false;
  2023. });
  2024. }
  2025. },
  2026. });
  2027. },
  2028. //获取重复试题
  2029. getreduplicateQuestions() {
  2030. this.duplicateLoading = true;
  2031. this.$http
  2032. .get(QUESTION_API + "/paper/" + this.paperId + "/reduplicate-questions")
  2033. .then((response) => {
  2034. this.reduplicateQuestions = response.data;
  2035. this.duplicateLoading = false;
  2036. this.initReduplicateQuesColor();
  2037. // var ques = document.getElementsByClassName("ques")[0];
  2038. // ques.style.display = "inline";
  2039. });
  2040. },
  2041. exportPaperAnswer() {
  2042. var key = this.user.key;
  2043. var token = this.user.token;
  2044. window.open(
  2045. QUESTION_API +
  2046. "/paper/answer/export/" +
  2047. this.paperId +
  2048. "?$key=" +
  2049. key +
  2050. "&$token=" +
  2051. token
  2052. );
  2053. },
  2054. initReduplicateQuesColor() {
  2055. var colorCount = this.reduplicateQuestions.length;
  2056. if (colorCount > 20) {
  2057. this.reduplicateQuesColor = randomColor({
  2058. luminosity: "bright",
  2059. count: colorCount,
  2060. });
  2061. } else {
  2062. this.reduplicateQuesColor = this.defaultColor;
  2063. }
  2064. },
  2065. getSubQuesEditId(paperDetailUnit, subQuestion) {
  2066. return paperDetailUnit.question.id + "_" + subQuestion.subNumber;
  2067. },
  2068. //打开考试说明编辑框
  2069. openEditExamPaperRemark() {
  2070. if (this.paper.examRemark) {
  2071. this.examRemark = this.paper.examRemark;
  2072. } else {
  2073. this.examRemark = "";
  2074. }
  2075. this.paperRemarkDialog = true;
  2076. },
  2077. //保存考试说明
  2078. savePaperRemark() {
  2079. this.paper.examRemark = this.examRemark;
  2080. this.savePaper();
  2081. this.paperRemarkDialog = false;
  2082. },
  2083. //关闭考试说明编辑框
  2084. closPaperRemark() {
  2085. this.examRemark = "";
  2086. this.paperRemarkDialog = false;
  2087. },
  2088. //保存试卷
  2089. savePaper() {
  2090. this.loading = true;
  2091. this.$http
  2092. .put(QUESTION_API + "/paper", this.paper)
  2093. .then(() => {
  2094. this.$notify({
  2095. message: "保存成功",
  2096. type: "success",
  2097. });
  2098. this.loading = false;
  2099. this.initPaper();
  2100. })
  2101. .catch((error) => {
  2102. this.loading = false;
  2103. this.$notify({
  2104. type: "error",
  2105. message: error.response.data.desc,
  2106. });
  2107. });
  2108. },
  2109. //删除试卷
  2110. deletePaper(id) {
  2111. this.$confirm("确认删除试卷吗?", "提示", {
  2112. type: "warning",
  2113. }).then(() => {
  2114. this.loading = true;
  2115. this.$http.delete(QUESTION_API + "/paper/" + id).then(
  2116. () => {
  2117. this.$notify({
  2118. message: "删除成功",
  2119. type: "success",
  2120. });
  2121. this.back();
  2122. },
  2123. (error) => {
  2124. this.$notify({
  2125. message: error.response.data.desc,
  2126. type: "error",
  2127. title: "错误",
  2128. });
  2129. this.loading = false;
  2130. }
  2131. );
  2132. });
  2133. },
  2134. //打开上传音频弹框
  2135. openDialog() {
  2136. this.checkResult = false;
  2137. this.isUpload = true;
  2138. if (document.getElementById("radioFile")) {
  2139. document.getElementById("radioFile").value = "";
  2140. }
  2141. this.dialogRadioFile = true;
  2142. this.fileList = [];
  2143. },
  2144. //关闭音频弹框
  2145. closeAudioDialog() {
  2146. this.dialogRadioFile = this.uploadAudioLoading;
  2147. },
  2148. //返回
  2149. back() {
  2150. if (sessionStorage.getItem("question_back") == "true") {
  2151. this.$router.push({
  2152. path: "/questions/" + this.parentView + "/0",
  2153. });
  2154. } else {
  2155. this.$router.push({
  2156. path: "/questions/" + this.parentView + "/1",
  2157. });
  2158. }
  2159. },
  2160. paperDetailShow(paperDetail) {
  2161. if (this.reduplicateGroup.length == 0) {
  2162. return true;
  2163. }
  2164. let paperDetailUnits = paperDetail.paperDetailUnits;
  2165. for (let i = 0, imax = paperDetailUnits.length; i < imax; i++) {
  2166. for (var j = 0, jmax = this.reduplicateGroup.length; j < jmax; j++) {
  2167. if (paperDetailUnits[i].id == this.reduplicateGroup[j]) {
  2168. return true;
  2169. }
  2170. }
  2171. }
  2172. return false;
  2173. },
  2174. //上传文件检查
  2175. checkFile() {
  2176. this.fileNameList = [];
  2177. //读取选取的文件夹里面的文件
  2178. this.checkResult = true;
  2179. var files = document.getElementById("radioFile").files;
  2180. if (files.length == 0) {
  2181. this.message = "请选择音频文件夹!";
  2182. return;
  2183. }
  2184. var size = 0;
  2185. var isGo = false;
  2186. //取到所有文件的文件名
  2187. for (var i = 0; i < files.length; i++) {
  2188. this.fileNameList.push(files[i].name);
  2189. if (files[i].size > 5 * 1024 * 1024) {
  2190. isGo = true;
  2191. break;
  2192. }
  2193. size = files[i].size + size;
  2194. }
  2195. if (isGo) {
  2196. this.message = "上传单个文件不能超过5M";
  2197. this.isUpload = true;
  2198. }
  2199. if (size > 50 * 1024 * 1024) {
  2200. this.message = "上传文件总和不能超过50M";
  2201. this.isUpload = true;
  2202. return;
  2203. }
  2204. this.$http
  2205. .post(
  2206. QUESTION_API + "/checkRadioFile/" + this.paperId,
  2207. this.fileNameList
  2208. )
  2209. .then((response) => {
  2210. console.log("response:", response);
  2211. this.message = response.data.errorMsg;
  2212. if (this.message == "OK") {
  2213. this.message = "OK!";
  2214. this.isUpload = false;
  2215. } else {
  2216. this.isUpload = true;
  2217. }
  2218. })
  2219. .catch((error) => {
  2220. console.log(error);
  2221. });
  2222. },
  2223. //读取文件
  2224. uploadAudioFile() {
  2225. let param = new FormData();
  2226. var fileList = document.getElementById("radioFile").files;
  2227. //循环添加到formData中
  2228. for (var i = 0; i < fileList.length; i++) {
  2229. var file = fileList[i];
  2230. param.append("files", file, file.name);
  2231. }
  2232. let config = {
  2233. headers: { "Content-Type": "multipart/form-data" },
  2234. };
  2235. this.$http
  2236. .post(QUESTION_API + "/uploadRadio/" + this.paperId, param, config)
  2237. .then(() => {
  2238. this.dialogRadioFile = false;
  2239. this.uploadAudioLoading = false;
  2240. this.checkResult = false;
  2241. this.isUpload = true;
  2242. document.getElementById("radioFile").value = "";
  2243. this.initPaper();
  2244. })
  2245. .catch((error) => {
  2246. this.message = error.response.data.desc;
  2247. this.uploadAudioLoading = false;
  2248. });
  2249. },
  2250. },
  2251. };
  2252. </script>
  2253. <style scoped src="../styles/EditPaper.css">
  2254. .property_with {
  2255. width: 100px;
  2256. }
  2257. .ck-toolbar {
  2258. z-index: 9999;
  2259. }
  2260. #app {
  2261. background-color: white !important;
  2262. }
  2263. </style>
  2264. <style scoped src="../styles/Common.css"></style>