InfoExamTask.vue 30 KB

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