InfoExamTask.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  1. <template>
  2. <div class="info-exam-task">
  3. <div class="part-box part-box-pad part-box-border part-box-gray">
  4. <el-form
  5. ref="examTaskComp"
  6. :model="examTask"
  7. :rules="rules"
  8. label-width="120px"
  9. >
  10. <el-row>
  11. <el-col :span="12">
  12. <el-form-item prop="semesterId" label="使用学期:">
  13. <semester-select
  14. v-model="examTask.semesterId"
  15. class="width-full"
  16. default-select-in-used
  17. @change="semesterChange"
  18. ></semester-select>
  19. </el-form-item>
  20. </el-col>
  21. <el-col :span="12">
  22. <el-form-item prop="examId" label="考试:">
  23. <exam-select
  24. v-model="examTask.examId"
  25. :semester-id="examTask.semesterId"
  26. :clearable="false"
  27. class="width-full"
  28. @change="examChange"
  29. ></exam-select>
  30. </el-form-item>
  31. </el-col>
  32. </el-row>
  33. <el-row>
  34. <el-col :span="12">
  35. <el-form-item label="部门:">
  36. {{ teachingRoomName }}
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="12">
  40. <el-form-item prop="courseCode" label="课程(代码):">
  41. <el-select
  42. v-model="examTask.courseCode"
  43. placeholder="请选择"
  44. filterable
  45. class="width-full"
  46. :disabled="!examTask.examId"
  47. @change="courseChange"
  48. >
  49. <el-option
  50. v-for="item in courses"
  51. :key="item.code"
  52. :value="item.code"
  53. :label="`${item.name}(${item.code})`"
  54. >
  55. </el-option>
  56. </el-select>
  57. </el-form-item>
  58. </el-col>
  59. </el-row>
  60. <el-row>
  61. <el-col :span="12">
  62. <el-form-item prop="paperNumber" label="试卷编号:">
  63. <el-input
  64. v-model.trim="examTask.paperNumber"
  65. placeholder="试卷编号不填写时会自动生成"
  66. :maxlength="50"
  67. clearable
  68. ></el-input>
  69. </el-form-item>
  70. </el-col>
  71. <el-col :span="12">
  72. <el-form-item prop="teacherName" label="拟卷教师:">
  73. <el-input
  74. v-model.trim="examTask.teacherName"
  75. placeholder="请输入拟卷教师"
  76. :maxlength="50"
  77. clearable
  78. ></el-input>
  79. </el-form-item>
  80. </el-col>
  81. </el-row>
  82. </el-form>
  83. </div>
  84. <div class="apply-content task-detail">
  85. <div class="task-body">
  86. <div class="mb-4 tab-btns">
  87. <el-button
  88. v-for="tab in tabs"
  89. :key="tab.val"
  90. size="medium"
  91. :type="curTab == tab.val ? 'primary' : 'default'"
  92. @click="selectMenu(tab.val)"
  93. >{{ tab.name }}
  94. </el-button>
  95. </div>
  96. <table class="table mb-2">
  97. <colgroup>
  98. <col width="90" />
  99. <col width="280" />
  100. <col />
  101. <col v-if="!IS_REBUILD" width="80" />
  102. </colgroup>
  103. <tr>
  104. <th>试卷类型</th>
  105. <th>试卷文件</th>
  106. <th>答题卡</th>
  107. <th v-if="!IS_REBUILD">操作</th>
  108. </tr>
  109. <tr v-for="(attachment, index) in paperAttachments" :key="index">
  110. <td>{{ attachment.name }}卷</td>
  111. <td v-if="IS_TIKU_TAB">
  112. <el-button
  113. type="text"
  114. class="btn-primary"
  115. @click="toSelect(attachment)"
  116. >
  117. <i
  118. :class="[
  119. 'icon',
  120. attachment.attachmentId ? 'icon-files-act' : 'icon-files',
  121. ]"
  122. ></i
  123. >{{ attachment.filename || "选择试卷" }}
  124. </el-button>
  125. </td>
  126. <td v-else>
  127. <el-button
  128. type="text"
  129. class="btn-primary"
  130. @click="toUpload(attachment)"
  131. >
  132. <i
  133. :class="[
  134. 'icon',
  135. attachment.attachmentId ? 'icon-files-act' : 'icon-files',
  136. ]"
  137. ></i
  138. >{{
  139. attachment.attachmentId
  140. ? attachment.filename
  141. : "点击上传试卷文件"
  142. }}
  143. </el-button>
  144. </td>
  145. <td v-if="IS_TIKU_TAB">
  146. <el-select
  147. v-model="attachment.cardId"
  148. placeholder="请选择"
  149. style="width: 260px; margin-right: 10px"
  150. >
  151. <el-option
  152. v-if="attachment.cardId"
  153. :value="attachment.cardId"
  154. :label="attachment.cardTitle"
  155. >
  156. </el-option>
  157. </el-select>
  158. <el-button
  159. class="btn-primary"
  160. type="text"
  161. :disabled="!attachment.cardId"
  162. @click="toViewCard(attachment)"
  163. >预览</el-button
  164. >
  165. <el-button
  166. v-if="!IS_REBUILD"
  167. class="btn-primary"
  168. type="text"
  169. :disabled="!attachment.cardId"
  170. @click="toEditCard(attachment)"
  171. >编辑</el-button
  172. >
  173. </td>
  174. <td v-else>
  175. <el-select
  176. class="mr-2"
  177. v-model="attachment.cardId"
  178. placeholder="请选择"
  179. style="width: 200px"
  180. filterable
  181. @visible-change="
  182. (visible) => cardOptionOpened(visible, attachment)
  183. "
  184. @change="cardChange(attachment)"
  185. >
  186. <el-option
  187. v-for="item in cards"
  188. :key="item.id"
  189. :value="item.id"
  190. :label="item.title"
  191. :disabled="item.disabled"
  192. >
  193. <span
  194. :class="[
  195. item.type === 'GENERIC'
  196. ? 'color-success'
  197. : 'color-primary',
  198. 'mr-1',
  199. {
  200. 'color-danger': item.used,
  201. },
  202. ]"
  203. >[{{ item.type === "GENERIC" ? "通" : "专" }}]</span
  204. >
  205. {{ item.title }}
  206. </el-option>
  207. </el-select>
  208. <span
  209. v-if="attachment.cardId"
  210. :class="[
  211. attachment.cardType === 'GENERIC'
  212. ? 'color-success'
  213. : 'color-primary',
  214. 'mr-1',
  215. {
  216. 'color-danger': attachment.used,
  217. },
  218. ]"
  219. >[{{ attachment.cardType === "GENERIC" ? "通" : "专" }}]</span
  220. >
  221. <el-button
  222. class="btn-primary"
  223. type="text"
  224. :disabled="!attachment.cardId"
  225. @click="toViewCard(attachment)"
  226. >预览</el-button
  227. >
  228. <template v-if="!IS_REBUILD">
  229. <el-button
  230. class="btn-primary"
  231. type="text"
  232. :disabled="
  233. !attachment.cardId ||
  234. (attachment.cardType === 'GENERIC' &&
  235. attachment.createMethod !== 'STANDARD')
  236. "
  237. @click="toCopyCard(attachment)"
  238. >复制</el-button
  239. >
  240. <el-button
  241. class="btn-primary"
  242. type="text"
  243. :disabled="
  244. !attachment.cardId ||
  245. attachment.cardType === 'GENERIC' ||
  246. !(!attachment.used && attachment.createId === user.id)
  247. "
  248. @click="toEditCard(attachment)"
  249. >编辑</el-button
  250. >
  251. <el-button
  252. class="btn-primary"
  253. type="text"
  254. :disabled="!canCreateCard"
  255. @click="toCreateCard(attachment)"
  256. >新建</el-button
  257. >
  258. </template>
  259. </td>
  260. <td v-if="!IS_REBUILD" class="text-right">
  261. <el-button
  262. v-if="index === paperAttachments.length - 1"
  263. class="btn-primary btn-icon"
  264. type="text"
  265. icon="el-icon-circle-plus"
  266. @click="addAtachment"
  267. ></el-button>
  268. <el-button
  269. class="btn-danger btn-icon"
  270. type="text"
  271. icon="el-icon-remove"
  272. @click="deleteAttachment(index)"
  273. ></el-button>
  274. </td>
  275. </tr>
  276. <tr v-if="!paperAttachments.length">
  277. <td colspan="5">
  278. <p class="tips-info text-center">暂无数据</p>
  279. </td>
  280. </tr>
  281. </table>
  282. <el-form v-if="!IS_REBUILD">
  283. <el-form-item label="单次抽卷卷型数量:" label-width="150">
  284. <el-input-number
  285. v-model="examTaskDetail.drawCount"
  286. :min="1"
  287. :max="1"
  288. :step="1"
  289. step-strictly
  290. :controls="false"
  291. ></el-input-number>
  292. </el-form-item>
  293. </el-form>
  294. <h4 class="mb-2">附件<span>(最多4张)</span>:</h4>
  295. <div class="image-list">
  296. <div
  297. class="image-item"
  298. v-for="(img, index) in paperConfirmAttachments"
  299. :key="index"
  300. >
  301. <img
  302. :src="img.url"
  303. :alt="img.filename"
  304. title="点击查看大图"
  305. @click="toPreview(index)"
  306. />
  307. <div class="image-delete">
  308. <i
  309. class="el-icon-delete-solid"
  310. @click="deletePaperConfirmAttachment(index)"
  311. ></i>
  312. </div>
  313. </div>
  314. <div
  315. v-if="paperConfirmAttachments.length < 4"
  316. class="image-item image-add"
  317. title="上传入库审核表"
  318. @click="toUploadPaperConfirm"
  319. >
  320. <i class="el-icon-plus"></i>
  321. </div>
  322. </div>
  323. <h4 class="mb-2">附件说明:</h4>
  324. <el-input
  325. class="mb-2"
  326. v-model="examTaskDetail.remark"
  327. type="textarea"
  328. resize="none"
  329. :rows="2"
  330. :maxlength="100"
  331. clearable
  332. show-word-limit
  333. placeholder="建议不超过100个字"
  334. ></el-input>
  335. </div>
  336. </div>
  337. <!-- upload-paper-dialog -->
  338. <upload-paper-dialog
  339. :paper-attachment="curAttachment"
  340. :upload-type="curUploadType"
  341. @confirm="uploadConfirm"
  342. ref="UploadPaperDialog"
  343. ></upload-paper-dialog>
  344. <!-- image-preview -->
  345. <simple-image-preview
  346. :cur-image="curImage"
  347. @on-prev="toPrevImage"
  348. @on-next="toNextImage"
  349. ref="SimpleImagePreview"
  350. ></simple-image-preview>
  351. <!-- ModifyCard -->
  352. <modify-card ref="ModifyCard" @modified="cardModified"></modify-card>
  353. <!-- SelectTikuPaperDialog -->
  354. <select-tiku-paper-dialog
  355. ref="SelectTikuPaperDialog"
  356. :row="curAttachment"
  357. @confirm="tikuPaperSelected"
  358. ></select-tiku-paper-dialog>
  359. <!-- CardBuildDialog -->
  360. <card-build-dialog
  361. ref="CardBuildDialog"
  362. :presetData="cardBuildPresetData"
  363. @confirm="cardBuildConfirm"
  364. ></card-build-dialog>
  365. </div>
  366. </template>
  367. <script>
  368. import { mapState, mapMutations } from "vuex";
  369. import UploadPaperDialog from "../UploadPaperDialog.vue";
  370. import SimpleImagePreview from "@/components/SimpleImagePreview";
  371. import ModifyCard from "../../../card/components/ModifyCard.vue";
  372. import SelectTikuPaperDialog from "./SelectTikuPaperDialog.vue";
  373. import { COMMON_CARD_RULE_ID } from "../../../../constants/enumerate";
  374. import { cardForSelectList } from "../../api";
  375. import { courseQuery, examConfigByExamIdOrgId } from "../../../base/api";
  376. import { copyCard } from "../../../card/api";
  377. import CardBuildDialog from "../../../card/components/CardBuildDialog.vue";
  378. // type=GENERIC时, 为通卡,不可复制,不可编辑,可预览。
  379. // type=CUSTOM时,可复制,不可编辑,如果是当前自己任务的题卡,才可编辑。
  380. export default {
  381. name: "info-exam-task",
  382. components: {
  383. UploadPaperDialog,
  384. SimpleImagePreview,
  385. ModifyCard,
  386. SelectTikuPaperDialog,
  387. CardBuildDialog,
  388. },
  389. data() {
  390. return {
  391. tabs: [
  392. {
  393. name: "上传本地试卷",
  394. val: "upload",
  395. },
  396. {
  397. name: "从题库选择试卷",
  398. val: "tiku",
  399. },
  400. ],
  401. curTab: "upload",
  402. user: {},
  403. task: {},
  404. rules: {
  405. semesterId: [
  406. {
  407. required: true,
  408. message: "请选择使用学期",
  409. trigger: "change",
  410. },
  411. ],
  412. examId: [
  413. {
  414. required: true,
  415. message: "请选择考试",
  416. trigger: "change",
  417. },
  418. ],
  419. teachingRoomId: [
  420. {
  421. required: true,
  422. message: "请选择机构",
  423. trigger: "change",
  424. },
  425. ],
  426. courseCode: [
  427. {
  428. required: true,
  429. message: "请选择课程",
  430. trigger: "change",
  431. },
  432. ],
  433. paperNumber: [
  434. {
  435. message: "试卷编号不能超过50个字符",
  436. max: 50,
  437. trigger: "change",
  438. },
  439. ],
  440. teacherName: [
  441. {
  442. message: "拟卷教师不能超过50个字符",
  443. max: 50,
  444. trigger: "change",
  445. },
  446. ],
  447. },
  448. examTask: {},
  449. cards: [],
  450. courses: [],
  451. semesters: [],
  452. teachingRoomName: "",
  453. cardRuleName: "全部通卡",
  454. // card-build
  455. cardBuildPresetData: {},
  456. // exam-task-detail
  457. examTaskDetail: { makeMethod: "" },
  458. paperConfirmAttachmentId: { attachmentId: "", filename: "", url: "" },
  459. paperAttachments: [],
  460. paperConfirmAttachments: [],
  461. curAttachment: {},
  462. curUploadType: "paper",
  463. attachmentLimitCount: 26,
  464. abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
  465. // image-preview
  466. curImage: {},
  467. curImageIndex: 0,
  468. };
  469. },
  470. computed: {
  471. ...mapState("exam", [
  472. "infoExamTask",
  473. "infoExamTaskDetail",
  474. "infoExamPrintPlan",
  475. ]),
  476. maxFetchCount() {
  477. return this.paperAttachments.length < 1
  478. ? 1
  479. : this.paperAttachments.length;
  480. },
  481. canCreateCard() {
  482. return (
  483. this.examTask.courseCode &&
  484. this.examTask.examId &&
  485. this.examTask.cardRuleId !== COMMON_CARD_RULE_ID
  486. );
  487. },
  488. IS_TIKU_TAB() {
  489. return this.curTab === "tiku";
  490. },
  491. IS_REBUILD() {
  492. return this.examTask.category === "REBUILD";
  493. },
  494. },
  495. watch: {
  496. "examTask.examId": function (val, oldval) {
  497. if (val !== oldval) this.examAndRoomChange();
  498. },
  499. "examTask.teachingRoomId": function (val, oldval) {
  500. if (val !== oldval) this.examAndRoomChange();
  501. },
  502. },
  503. mounted() {
  504. this.initData();
  505. },
  506. methods: {
  507. ...mapMutations("exam", ["updateTaskInfo"]),
  508. initData() {
  509. this.user = this.$ls.get("user", {});
  510. const userOrg = this.user.orgInfo;
  511. this.teachingRoomName = userOrg.name;
  512. this.examTask = { ...this.infoExamTask, teachingRoomId: userOrg.id };
  513. this.examTaskDetail = { ...this.infoExamTaskDetail };
  514. this.paperAttachments = this.examTaskDetail.paperAttachmentIds
  515. ? JSON.parse(this.examTaskDetail.paperAttachmentIds)
  516. : [];
  517. if (!this.paperAttachments.length) {
  518. this.addAtachment();
  519. }
  520. this.paperConfirmAttachments = this.examTaskDetail
  521. .paperConfirmAttachmentIds
  522. ? JSON.parse(this.examTaskDetail.paperConfirmAttachmentIds)
  523. : [];
  524. this.getCourses();
  525. this.getCardList();
  526. this.$nextTick(() => {
  527. this.$refs.examTaskComp.clearValidate();
  528. });
  529. },
  530. async selectMenu(tab) {
  531. const attachment = this.paperAttachments[0];
  532. if (attachment.cardId || attachment.attachmentId) {
  533. const result = await this.$confirm(
  534. "更改类型会清空已设置数据,确定要更改类型?",
  535. "提示",
  536. {
  537. type: "warning",
  538. }
  539. ).catch(() => {});
  540. if (result !== "confirm") return;
  541. this.paperAttachments = [];
  542. this.addAtachment();
  543. }
  544. this.curTab = tab;
  545. },
  546. async getCardList() {
  547. if (!this.examTask.courseCode || !this.examTask.examId) return;
  548. const data = await cardForSelectList({
  549. courseCode: this.examTask.courseCode,
  550. examId: this.examTask.examId,
  551. });
  552. this.cards = data || [];
  553. if (this.IS_REBUILD) {
  554. this.cards = this.cards.filter((item) => item.type === "GENERIC");
  555. }
  556. },
  557. async getCourses() {
  558. if (!this.examTask.teachingRoomId) return;
  559. const res = await courseQuery({
  560. teachingRoomId: this.examTask.teachingRoomId,
  561. });
  562. this.courses = res || [];
  563. },
  564. semesterChange(val) {
  565. this.examTask.paperName = val.name;
  566. },
  567. examChange(val) {
  568. if (!val.id) return;
  569. this.examTask.examModel = val.examModel;
  570. this.examTask.category = val.category;
  571. this.clearTaskData();
  572. },
  573. courseChange(val) {
  574. if (val) {
  575. const course = this.courses.find((item) => item.code === val);
  576. this.examTask.courseName = course.name;
  577. } else {
  578. this.examTask.courseName = "";
  579. }
  580. this.clearTaskData();
  581. this.updateTaskInfo({ infoExamTask: this.examTask });
  582. },
  583. clearTaskData() {
  584. this.paperAttachments = [];
  585. this.addAtachment();
  586. this.cards = [];
  587. this.getCardList();
  588. },
  589. async examAndRoomChange() {
  590. this.updateTaskInfo({ infoExamTask: this.examTask });
  591. const { examId, teachingRoomId } = this.examTask;
  592. if (examId && teachingRoomId) {
  593. const examPrintPlan = await examConfigByExamIdOrgId({
  594. examId,
  595. orgId: teachingRoomId,
  596. });
  597. this.examTask.cardRuleId = examPrintPlan.cardRuleId;
  598. this.examTaskDetail.review = examPrintPlan.review;
  599. this.examTaskDetail.includePaper =
  600. examPrintPlan.printContent.indexOf("PAPER") !== -1;
  601. this.updateTaskInfo({
  602. infoExamPrintPlan: Object.assign(
  603. {},
  604. this.infoExamPrintPlan,
  605. examPrintPlan
  606. ),
  607. infoExamTask: this.examTask,
  608. infoExamTaskDetail: this.examTaskDetail,
  609. });
  610. }
  611. },
  612. cardChange(attachment) {
  613. const card = this.cards.find((item) => item.id === attachment.cardId);
  614. if (card) {
  615. attachment.cardType = card.type;
  616. attachment.createMethod = card.createMethod;
  617. attachment.cardTitle = card.title;
  618. attachment.used = card.used;
  619. attachment.createId = card.createId;
  620. }
  621. },
  622. cardOptionOpened(visible, attachment) {
  623. if (!visible) return;
  624. // const selectedCardIds = this.paperAttachments.map((item) => item.cardId);
  625. // this.cards = this.cards.map((card) => {
  626. // card.disabled =
  627. // card.id !== attachment.cardId &&
  628. // selectedCardIds.includes(card.id) &&
  629. // card.type !== "GENERIC";
  630. // return card;
  631. // });
  632. },
  633. async toCreateCard(attachment) {
  634. if (!this.examTask.cardRuleId) {
  635. this.$message.error("题卡规则缺失!");
  636. return;
  637. }
  638. const res = await this.$prompt("请输入题卡名称?", "提示", {
  639. type: "warning",
  640. showInput: true,
  641. inputPlaceholder: "请输入题卡名称",
  642. inputValidator: (val) => {
  643. if (!val) return "请输入题卡名称!";
  644. if (val.length > 50) return "题卡名称不得超过50个字符!";
  645. return true;
  646. },
  647. }).catch(() => {});
  648. if (!res || res.action !== "confirm") return;
  649. this.curAttachment = { ...attachment };
  650. this.$ls.set("prepareTcPCard", {
  651. courseCode: this.examTask.courseCode,
  652. courseName: this.examTask.courseName,
  653. schoolName: this.$ls.get("schoolName"),
  654. makeMethod: "SELF",
  655. cardName: res.value,
  656. cardRuleId: this.examTask.cardRuleId,
  657. type: "CUSTOM",
  658. createMethod: "STANDARD",
  659. });
  660. this.$refs.ModifyCard.open();
  661. },
  662. toEditCard(attachment) {
  663. this.curAttachment = { ...attachment };
  664. // 这里只允许新建标准专卡
  665. this.$ls.set("prepareTcPCard", {
  666. id: attachment.cardId,
  667. courseCode: this.examTask.courseCode,
  668. courseName: this.examTask.courseName,
  669. schoolName: this.$ls.get("schoolName"),
  670. makeMethod: "SELF",
  671. cardRuleId: this.examTask.cardRuleId,
  672. type: "CUSTOM",
  673. createMethod: "STANDARD",
  674. });
  675. this.$refs.ModifyCard.open();
  676. },
  677. toViewCard(attachment) {
  678. window.open(
  679. this.getRouterPath({
  680. name: "CardPreview",
  681. params: {
  682. cardId: attachment.cardId,
  683. viewType: "view",
  684. },
  685. })
  686. );
  687. },
  688. async toCopyCard(attachment) {
  689. this.curAttachment = { ...attachment };
  690. const newCardId = await copyCard(
  691. attachment.cardId,
  692. this.examTask.courseCode
  693. );
  694. this.cardModified({ id: newCardId });
  695. },
  696. async cardModified(data) {
  697. // data: {id,title}
  698. if (!data.id) return;
  699. if (this.IS_TIKU_TAB) {
  700. const aind = this.paperAttachments.findIndex(
  701. (item) => item.name === this.curAttachment.name
  702. );
  703. this.paperAttachments[aind].cardTitle = data.title;
  704. return;
  705. }
  706. await this.getCardList();
  707. let card = this.cards.find((item) => item.id === data.id);
  708. const aind = this.paperAttachments.findIndex(
  709. (item) => item.name === this.curAttachment.name
  710. );
  711. if (aind !== -1 && card) {
  712. this.paperAttachments[aind].cardId = card.id;
  713. this.paperAttachments[aind].cardType = card.type;
  714. this.paperAttachments[aind].createMethod = card.createMethod;
  715. this.paperAttachments[aind].cardTitle = card.title;
  716. this.paperAttachments[aind].used = card.used;
  717. this.paperAttachments[aind].createId = card.createId;
  718. }
  719. },
  720. async checkData() {
  721. const valid = await this.$refs.examTaskComp.validate().catch(() => {});
  722. if (!valid) return Promise.reject();
  723. if (this.IS_TIKU_TAB) {
  724. const attachmentValid = !this.paperAttachments.some(
  725. (item) => !item.cardId
  726. );
  727. if (!attachmentValid) {
  728. this.$message.error("请完成试卷选择!");
  729. return Promise.reject();
  730. }
  731. return Promise.resolve(true);
  732. }
  733. // 设置了入库强制包含试卷时,校验试卷是否上传。
  734. // 未设置入库强制包含试卷时,若有试卷上传,则需要上传全部。若无试卷上传,则通过。
  735. if (this.examTaskDetail.includePaper) {
  736. const attachmentValid = !this.paperAttachments.some(
  737. (item) => !item.attachmentId
  738. );
  739. if (!attachmentValid) {
  740. this.$message.error("请完成试卷文件上传!");
  741. return Promise.reject();
  742. }
  743. } else {
  744. const hasUploadPaperAttachments = this.paperAttachments.filter(
  745. (item) => item.attachmentId
  746. );
  747. if (
  748. hasUploadPaperAttachments.length > 0 &&
  749. hasUploadPaperAttachments.length !== this.paperAttachments.length
  750. ) {
  751. this.$message.error("有试卷文件未完成上传!");
  752. return Promise.reject();
  753. }
  754. }
  755. // if (!this.paperConfirmAttachments.length) {
  756. // this.$message.error("请上传附件!");
  757. // return;
  758. // }
  759. let cardValid = !this.paperAttachments.some((item) => !item.cardId);
  760. if (!cardValid) {
  761. this.$message.error("有试卷类型未选择题卡!");
  762. return Promise.reject();
  763. }
  764. // const usedCards = this.paperAttachments
  765. // .filter((item) => item.cardId && item.used)
  766. // .map((item) => item.name);
  767. // if (usedCards.length) {
  768. // this.$message.error(`${usedCards.join()}卷选择的题卡已经被使用过!`);
  769. // return Promise.reject();
  770. // }
  771. return Promise.resolve(true);
  772. },
  773. updateData() {
  774. let data = {
  775. infoExamTask: this.examTask,
  776. infoExamTaskDetail: this.getTaskDetailData(),
  777. };
  778. this.updateTaskInfo(data);
  779. },
  780. emitRelateInfo(type) {
  781. this.$emit("relate-info-change", this.getData(), type);
  782. },
  783. // select-paper
  784. toSelect(attachment) {
  785. this.curAttachment = {
  786. ...attachment,
  787. courseCode: this.examTask.courseCode,
  788. };
  789. this.$refs.SelectTikuPaperDialog.open();
  790. // this.tikuPaperSelected({ id: "1", name: "paper-name" });
  791. },
  792. async tikuPaperSelected(data) {
  793. this.cardBuildPresetData = {
  794. examId: this.examTask.examId,
  795. courseCode: this.examTask.courseCode,
  796. courseName: this.examTask.courseName,
  797. schoolName: this.$ls.get("schoolName"),
  798. makeMethod: "SELF",
  799. cardName: "",
  800. cardRuleId: this.examTask.cardRuleId,
  801. type: "CUSTOM",
  802. createMethod: "STANDARD",
  803. paperId: data.id,
  804. paperName: data.name,
  805. uuid: this.examTask.uuid,
  806. };
  807. this.$refs.CardBuildDialog.open();
  808. },
  809. cardBuildConfirm(data) {
  810. if (!data.success) {
  811. this.$message.error(data.message);
  812. return;
  813. }
  814. const ind = this.paperAttachments.findIndex(
  815. (item) => item.name === this.curAttachment.name
  816. );
  817. if (ind === -1) return;
  818. const info = data.data;
  819. this.curAttachment = { ...this.paperAttachments[ind] };
  820. this.paperAttachments[ind] = Object.assign(this.paperAttachments[ind], {
  821. paperId: this.cardBuildPresetData.paperId,
  822. cardType: this.cardBuildPresetData.type,
  823. createMethod: this.cardBuildPresetData.createMethod,
  824. filename: this.cardBuildPresetData.paperName,
  825. cardId: info.id,
  826. cardTitle: info.title,
  827. uuid: info.uuid,
  828. attachmentId: info.attachmentId,
  829. });
  830. },
  831. // exam-task-detail edit
  832. addAtachment() {
  833. if (this.paperAttachments.length >= this.attachmentLimitCount) return;
  834. const newAttachment = {
  835. name: this.abc[this.paperAttachments.length],
  836. attachmentId: "",
  837. filename: "",
  838. paperId: null,
  839. uuid: null,
  840. cardId: "",
  841. cardType: "",
  842. createMethod: "",
  843. cardTitle: "",
  844. pages: 0,
  845. used: false,
  846. createId: null,
  847. };
  848. this.paperAttachments.push(newAttachment);
  849. },
  850. deleteAttachment(index) {
  851. if (this.paperAttachments.length <= 1) {
  852. this.$message.error("试卷类型数量不得少于1");
  853. return;
  854. }
  855. this.paperAttachments.splice(index, 1);
  856. this.paperAttachments.forEach((item, itemIndex) => {
  857. item.name = this.abc[itemIndex];
  858. });
  859. if (
  860. this.examTaskDetail.drawCount &&
  861. this.examTaskDetail.drawCount > this.paperAttachments.length
  862. ) {
  863. this.examTaskDetail.drawCount = this.paperAttachments.length;
  864. }
  865. },
  866. toUpload(attachment) {
  867. this.curUploadType = "paper";
  868. this.curAttachment = {
  869. ...attachment,
  870. };
  871. this.$refs.UploadPaperDialog.open();
  872. },
  873. toUploadPaperConfirm() {
  874. if (this.paperConfirmAttachments.length >= 4) return;
  875. this.curUploadType = "paperConfirm";
  876. this.curAttachment = {
  877. ...this.paperConfirmAttachmentId,
  878. };
  879. this.$refs.UploadPaperDialog.open();
  880. },
  881. uploadConfirm(attachment, uploadType) {
  882. if (uploadType === "paper") {
  883. const index = this.paperAttachments.findIndex(
  884. (item) => item.name === attachment.name
  885. );
  886. this.paperAttachments.splice(index, 1, { ...attachment });
  887. } else {
  888. this.paperConfirmAttachments.push(attachment);
  889. }
  890. },
  891. deletePaperConfirmAttachment(index) {
  892. this.paperConfirmAttachments.splice(index, 1);
  893. },
  894. // cardConfirm(data) {
  895. // this.examTaskDetail = this.$objAssign(this.examTaskDetail, data);
  896. // },
  897. getTaskDetailData() {
  898. let data = { ...this.examTaskDetail };
  899. data.paperType = this.paperAttachments.map((item) => item.name).join(",");
  900. data.paperAttachmentIds = JSON.stringify(this.paperAttachments, (k, v) =>
  901. k === "url" ? undefined : v
  902. );
  903. data.paperConfirmAttachmentIds = JSON.stringify(
  904. this.paperConfirmAttachments
  905. );
  906. return data;
  907. },
  908. // image-preview
  909. toPreview(index) {
  910. this.curImageIndex = index;
  911. this.selectImage(index);
  912. this.$refs.SimpleImagePreview.open();
  913. },
  914. selectImage(index) {
  915. this.curImage = this.paperConfirmAttachments[index];
  916. },
  917. toPrevImage() {
  918. if (this.curImageIndex === 0) {
  919. this.curImageIndex = this.paperConfirmAttachments.length - 1;
  920. } else {
  921. this.curImageIndex--;
  922. }
  923. this.selectImage(this.curImageIndex);
  924. },
  925. toNextImage() {
  926. if (this.curImageIndex === this.paperConfirmAttachments.length - 1) {
  927. this.curImageIndex = 0;
  928. } else {
  929. this.curImageIndex++;
  930. }
  931. this.selectImage(this.curImageIndex);
  932. },
  933. },
  934. };
  935. </script>