ApplyContent.vue 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. <template>
  2. <div class="apply-content task-detail">
  3. <div class="task-body">
  4. <div v-if="IS_APPLY" class="mb-2 text-right">
  5. <el-button
  6. type="info"
  7. icon="el-icon-circle-plus-outline"
  8. @click="addAtachment"
  9. >增加卷型</el-button
  10. >
  11. </div>
  12. <table class="table mb-2">
  13. <tr>
  14. <th>试卷类型</th>
  15. <th>试卷文件</th>
  16. <th>答题卡创建方式</th>
  17. <th>答题卡</th>
  18. <th v-if="IS_APPLY">操作</th>
  19. </tr>
  20. <tr v-for="(attachment, index) in paperAttachments" :key="index">
  21. <td>
  22. <span>{{ attachment.name }}卷</span>
  23. <span class="color-gray-2" v-if="attachment.isExposed"
  24. >(已曝光)</span
  25. >
  26. </td>
  27. <td>
  28. <el-button
  29. v-if="!attachment.isExposed && (IS_APPLY || IS_AUDIT_APPLY)"
  30. type="text"
  31. class="btn-primary"
  32. @click="toUpload(attachment)"
  33. >
  34. <i
  35. :class="[
  36. 'icon',
  37. attachment.attachmentId ? 'icon-files-act' : 'icon-files'
  38. ]"
  39. ></i
  40. >{{
  41. attachment.attachmentId
  42. ? attachment.filename
  43. : "点击上传试卷文件"
  44. }}
  45. </el-button>
  46. <el-button
  47. v-else
  48. type="text"
  49. class="btn-primary"
  50. @click="downloadPaper(attachment)"
  51. >
  52. <i
  53. class="icon icon-download mr-1"
  54. v-if="attachment.attachmentId"
  55. ></i>
  56. <i>{{ attachment.filename }}</i>
  57. </el-button>
  58. </td>
  59. <td :rowspan="paperAttachments.length" v-if="index === 0">
  60. {{ createCardTypeName }}
  61. </td>
  62. <td :rowspan="paperAttachments.length" v-if="index === 0">
  63. <el-button
  64. type="text"
  65. class="btn-primary"
  66. v-if="!exposedMode && IS_APPLY"
  67. @click="toCreateOrViewCard"
  68. >{{ cardTodoName }}</el-button
  69. >
  70. <el-button
  71. v-else
  72. type="text"
  73. class="btn-primary"
  74. @click="toViewCard"
  75. >
  76. 查看题卡
  77. </el-button>
  78. <el-button
  79. v-if="
  80. curTaskApply.makeMethod &&
  81. curTaskApply.makeMethod !== 'CUST' &&
  82. !exposedMode &&
  83. IS_APPLY
  84. "
  85. type="text"
  86. class="btn-danger"
  87. @click="changeCreateCardType"
  88. >切换题卡创建方式</el-button
  89. >
  90. </td>
  91. <td v-if="IS_APPLY">
  92. <el-button
  93. v-if="attachment.canDelete"
  94. class="btn-danger"
  95. type="text"
  96. @click="deleteAttachment(index)"
  97. >删除</el-button
  98. >
  99. </td>
  100. </tr>
  101. <tr v-if="!paperAttachments.length">
  102. <td colspan="5">
  103. <p class="tips-info text-center">暂无数据</p>
  104. </td>
  105. </tr>
  106. </table>
  107. <p class="tips-info tips-dark mb-2">
  108. 提示:多卷型试卷由于会绑定一个答题卡模板,因此试卷结构必须相同。多卷型试卷之间客观题要求试题内容相同,可允许大题内的小题题序不同。
  109. </p>
  110. <el-form>
  111. <el-form-item label="单次抽卷卷型数量:" label-width="150">
  112. <el-input-number
  113. v-model="curTaskApply.drawCount"
  114. :min="1"
  115. :max="maxFetchCount"
  116. :step="1"
  117. step-strictly
  118. :controls="false"
  119. :disabled="!IS_APPLY || exposedMode"
  120. ></el-input-number>
  121. </el-form-item>
  122. </el-form>
  123. <h4 class="mb-2">附件<span v-if="IS_APPLY">(最多4张)</span>:</h4>
  124. <div class="image-list">
  125. <div
  126. class="image-item"
  127. v-for="(img, index) in paperConfirmAttachments"
  128. :key="index"
  129. >
  130. <img
  131. :src="img.url"
  132. :alt="img.filename"
  133. title="点击查看大图"
  134. @click="toPreview(index)"
  135. />
  136. <div v-if="IS_APPLY" class="image-delete">
  137. <i
  138. class="el-icon-delete-solid"
  139. @click="deletePaperConfirmAttachment(index)"
  140. ></i>
  141. </div>
  142. </div>
  143. <div
  144. v-if="paperConfirmAttachments.length < 4 && IS_APPLY"
  145. class="image-item image-add"
  146. title="上传附件"
  147. @click="toUploadPaperConfirm"
  148. >
  149. <i class="el-icon-plus"></i>
  150. </div>
  151. </div>
  152. <div
  153. v-if="!IS_APPLY && !paperConfirmAttachments.length"
  154. class="image-list-none"
  155. >
  156. 暂无数据
  157. </div>
  158. <h4 class="mb-2">附件说明:</h4>
  159. <el-input
  160. v-if="IS_APPLY"
  161. class="mb-2"
  162. v-model="curTaskApply.remark"
  163. type="textarea"
  164. resize="none"
  165. :rows="2"
  166. :maxlength="100"
  167. clearable
  168. show-word-limit
  169. placeholder="建议不超过100个字"
  170. ></el-input>
  171. <div class="color-gray-2" v-else>
  172. <p v-if="curTaskApply.remark">{{ curTaskApply.remark }}</p>
  173. <p v-else>暂无</p>
  174. </div>
  175. <!-- -->
  176. <div v-if="IS_APPLY && needSetApproveUser" class="task-audit">
  177. <el-form>
  178. <el-form-item label="指定审批人:">
  179. <el-select
  180. v-model="approveUserIds"
  181. placeholder="请选择"
  182. multiple
  183. filterable
  184. clearable
  185. style="width: 700px"
  186. >
  187. <el-option
  188. v-for="user in approveUserList"
  189. :key="user.id"
  190. :value="user.id"
  191. :label="`${user.realName}(${user.orgName})`"
  192. >
  193. {{ user.realName }}({{ user.orgName }})
  194. </el-option>
  195. </el-select>
  196. </el-form-item>
  197. </el-form>
  198. </div>
  199. <!-- audit -->
  200. <div v-if="IS_AUDIT" class="task-audit">
  201. <el-form
  202. ref="auditModalComp"
  203. :model="auditModal"
  204. :rules="auditRules"
  205. label-width="90px"
  206. >
  207. <el-form-item prop="approvePass" label="审批操作:">
  208. <el-radio-group
  209. v-model="auditModal.approvePass"
  210. @change="approvePassChange"
  211. >
  212. <el-radio
  213. v-for="(val, key) in TASK_AUDIT_RESULT"
  214. :key="key"
  215. :label="key"
  216. >{{ val }}</el-radio
  217. >
  218. </el-radio-group>
  219. </el-form-item>
  220. <el-form-item
  221. v-if="auditModal.approvePass === 'REJECT'"
  222. prop="setup"
  223. label="驳回节点:"
  224. >
  225. <el-select
  226. v-model="auditModal.setup"
  227. placeholder="请选择"
  228. style="width: 100%"
  229. >
  230. <el-option
  231. v-for="item in setups"
  232. :key="item.taskKey"
  233. :value="item.setup"
  234. :label="item.taskName"
  235. >
  236. </el-option>
  237. </el-select>
  238. </el-form-item>
  239. <el-form-item
  240. v-if="auditModal.approvePass !== 'EXCHANGE'"
  241. :key="auditModal.approvePass"
  242. prop="remark"
  243. label="审批意见:"
  244. >
  245. <el-input
  246. class="mb-2"
  247. v-model="auditModal.remark"
  248. type="textarea"
  249. resize="none"
  250. :rows="5"
  251. :maxlength="1000"
  252. clearable
  253. show-word-limit
  254. placeholder="建议不超过1000个字"
  255. ref="ReasonInput"
  256. ></el-input>
  257. </el-form-item>
  258. <el-form-item
  259. v-if="auditModal.approvePass === 'EXCHANGE'"
  260. prop="userId"
  261. label="审批人:"
  262. >
  263. <el-select
  264. v-model="auditModal.userId"
  265. filterable
  266. placeholder="请选择"
  267. >
  268. <el-option
  269. v-for="user in approveExchangePeople"
  270. :key="user.id"
  271. :value="user.id"
  272. :label="user.realName"
  273. ></el-option>
  274. </el-select>
  275. </el-form-item>
  276. <el-form-item
  277. v-if="needSetApproveUser && auditModal.approvePass === 'PASS'"
  278. key="approveUserIds"
  279. label="指定审批人:"
  280. >
  281. <el-select
  282. v-model="approveUserIds"
  283. placeholder="请选择"
  284. multiple
  285. filterable
  286. clearable
  287. style="width: 700px"
  288. >
  289. <el-option
  290. v-for="user in approveUserList"
  291. :key="user.id"
  292. :value="user.id"
  293. :label="`${user.realName}(${user.orgName})`"
  294. >
  295. {{ user.realName }}({{ user.orgName }})
  296. </el-option>
  297. </el-select>
  298. </el-form-item>
  299. </el-form>
  300. </div>
  301. </div>
  302. <div class="task-action">
  303. <el-button
  304. v-if="IS_APPLY"
  305. type="primary"
  306. :disabled="isSubmit"
  307. @click="submit"
  308. >确认提交</el-button
  309. >
  310. <el-button
  311. v-if="IS_APPLY"
  312. type="primary"
  313. :disabled="isSubmit"
  314. @click="toSave"
  315. >暂存</el-button
  316. >
  317. <el-button
  318. v-if="IS_AUDIT"
  319. type="primary"
  320. :disabled="isSubmit"
  321. @click="toAuditSubmit"
  322. >确定</el-button
  323. >
  324. <el-button
  325. v-if="IS_AUDIT_APPLY"
  326. type="primary"
  327. :disabled="isSubmit"
  328. @click="toAuditApply"
  329. >提交</el-button
  330. >
  331. <el-button @click="cancel">取消</el-button>
  332. </div>
  333. <!-- upload-paper-dialog -->
  334. <upload-paper-dialog
  335. :paper-attachment="curAttachment"
  336. :upload-type="curUploadType"
  337. @confirm="uploadConfirm"
  338. ref="UploadPaperDialog"
  339. ></upload-paper-dialog>
  340. <!-- card-option-dialog -->
  341. <card-option-dialog
  342. ref="CardOptionDialog"
  343. :data="task"
  344. @upload-sample-over="initData"
  345. @draft-task="silentSave"
  346. @confirm="cardConfirm"
  347. ></card-option-dialog>
  348. <!-- image-preview -->
  349. <simple-image-preview
  350. :cur-image="curImage"
  351. @on-prev="toPrevImage"
  352. @on-next="toNextImage"
  353. ref="SimpleImagePreview"
  354. ></simple-image-preview>
  355. </div>
  356. </template>
  357. <script>
  358. import UploadPaperDialog from "./UploadPaperDialog";
  359. import CardOptionDialog from "./CardOptionDialog";
  360. import {
  361. taskApplyDetail,
  362. updateTaskApply,
  363. updateTaskReview,
  364. taskAuditApply,
  365. switchCardCreateMethod,
  366. taskAllFlowSetups,
  367. taskAllApproverPeople,
  368. taskAllApproverExchangePeople,
  369. taskApproverExchange,
  370. taskApproverNextPeople
  371. } from "../api";
  372. import { attachmentPreview } from "../../login/api";
  373. import SimpleImagePreview from "@/components/SimpleImagePreview";
  374. import { CARD_SOURCE_TYPE, TASK_AUDIT_RESULT } from "@/constants/enumerate";
  375. const initTaskApply = {
  376. examTaskId: "",
  377. paperType: "A",
  378. paperAttachmentIds: "",
  379. paperConfirmAttachmentIds: "",
  380. cardId: "",
  381. cardRuleId: "",
  382. makeMethod: "",
  383. remark: "",
  384. courseCode: "",
  385. courseName: "",
  386. drawCount: 1,
  387. exposedPaperType: "",
  388. // 流程
  389. flowId: "",
  390. setup: 0,
  391. // 工作台任务id
  392. flowTaskId: "",
  393. // 题卡状态
  394. status: "",
  395. // 考务规则
  396. review: false,
  397. includePaper: false,
  398. customCard: false,
  399. // 是否有子流程
  400. subFlowReject: false
  401. };
  402. export default {
  403. name: "apply-content",
  404. components: { UploadPaperDialog, CardOptionDialog, SimpleImagePreview },
  405. props: {
  406. examTask: {
  407. type: Object,
  408. default() {
  409. return {};
  410. }
  411. },
  412. editType: {
  413. type: String,
  414. default: ""
  415. }
  416. },
  417. data() {
  418. return {
  419. isSubmit: false,
  420. curTaskApply: { ...initTaskApply },
  421. paperConfirmAttachmentId: { attachmentId: "", filename: "", url: "" },
  422. paperAttachments: [],
  423. paperConfirmAttachments: [],
  424. curAttachment: {},
  425. curUploadType: "paper",
  426. attachmentLimitCount: 26,
  427. abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
  428. task: {},
  429. reason: "",
  430. TASK_AUDIT_RESULT: { ...TASK_AUDIT_RESULT, EXCHANGE: "转他人审批" },
  431. // audit
  432. flows: [],
  433. setups: [],
  434. auditModal: {
  435. approvePass: "PASS",
  436. setup: "",
  437. remark: ""
  438. },
  439. auditRules: {
  440. approvePass: [
  441. {
  442. required: true
  443. }
  444. ],
  445. setup: [
  446. {
  447. required: true,
  448. validator: (rule, value, callback) => {
  449. if (this.auditModal.approvePass === "REJECT" && !value) {
  450. callback(new Error(`请选择要驳回到的节点`));
  451. } else {
  452. callback();
  453. }
  454. },
  455. trigger: "change"
  456. }
  457. ],
  458. remark: [
  459. {
  460. required: false,
  461. validator: (rule, value, callback) => {
  462. if (this.auditModal.approvePass === "REJECT" && !value) {
  463. callback(new Error(`请输入审批意见`));
  464. } else {
  465. callback();
  466. }
  467. },
  468. trigger: "change"
  469. }
  470. ],
  471. userId: [
  472. {
  473. required: true,
  474. message: "请选择审批人",
  475. trigger: "change"
  476. }
  477. ]
  478. },
  479. approveExchangePeople: [],
  480. needSetApproveUser: false,
  481. approveUserIds: [],
  482. approveUserList: [], //审批人
  483. // image-preview
  484. curImage: {},
  485. curImageIndex: 0
  486. };
  487. },
  488. computed: {
  489. IS_APPLY() {
  490. return this.editType
  491. ? this.editType === "APPLY"
  492. : this.curTaskApply.setup === 1 || this.curTaskApply.setup === null;
  493. },
  494. IS_PREVIEW() {
  495. return this.editType
  496. ? this.editType === "PREVIEW"
  497. : this.curTaskApply.setup !== null && this.curTaskApply.setup <= 0;
  498. },
  499. IS_AUDIT() {
  500. const IS_COMMON_AUDIT = this.editType
  501. ? this.editType === "AUDIT"
  502. : this.curTaskApply.setup > 1;
  503. return IS_COMMON_AUDIT && !this.IS_AUDIT_APPLY;
  504. },
  505. IS_AUDIT_APPLY() {
  506. // IS_PRELAST_STEP
  507. return (
  508. this.curTaskApply.subFlowReject &&
  509. this.curTaskApply.setup === this.flows.length - 1
  510. );
  511. },
  512. cardTodoName() {
  513. let name = "创建答题卡";
  514. if (this.curTaskApply.cardId) {
  515. if (this.curTaskApply.makeMethod === "SELECT") {
  516. name = "选择题卡";
  517. } else if (this.curTaskApply.makeMethod === "SELF") {
  518. name = "编辑题卡";
  519. } else {
  520. // 已经审核的题卡可以自行编辑,未审核的题卡只能查看
  521. name =
  522. this.curTaskApply.status === "SUBMIT" ? "编辑题卡" : "查看题卡";
  523. }
  524. }
  525. return name;
  526. },
  527. createCardTypeName() {
  528. return CARD_SOURCE_TYPE[this.curTaskApply.makeMethod] || "";
  529. },
  530. maxFetchCount() {
  531. return this.paperAttachments.length < 1
  532. ? 1
  533. : this.paperAttachments.length;
  534. },
  535. exposedMode() {
  536. return !!this.curTaskApply.exposedPaperType;
  537. }
  538. },
  539. mounted() {
  540. this.initData();
  541. },
  542. methods: {
  543. async initData() {
  544. const data = await taskApplyDetail(
  545. this.examTask.id,
  546. this.examTask.source
  547. );
  548. this.curTaskApply = this.$objAssign(initTaskApply, data || {});
  549. this.curTaskApply.examTaskId = this.examTask.id;
  550. this.curTaskApply.courseCode = this.examTask.courseCode;
  551. this.curTaskApply.courseName = this.examTask.courseName;
  552. this.curTaskApply.cardRuleId = this.examTask.cardRuleId;
  553. this.curTaskApply.customCard = this.examTask.customCard;
  554. this.curTaskApply.setup = this.examTask.setup;
  555. this.paperAttachments = this.curTaskApply.paperAttachmentIds
  556. ? JSON.parse(this.curTaskApply.paperAttachmentIds)
  557. : [];
  558. const exposedPaperType = data.exposedPaperType || "";
  559. let exposedPaperTypes = exposedPaperType.split(",");
  560. exposedPaperTypes.sort((a, b) => (a > b ? -1 : 1));
  561. const maxExposedPaperType = exposedPaperTypes[0];
  562. this.paperAttachments.forEach(paper => {
  563. paper.canDelete = maxExposedPaperType
  564. ? paper.name > maxExposedPaperType
  565. : true;
  566. paper.isExposed = exposedPaperTypes.includes(paper.name);
  567. });
  568. this.paperConfirmAttachments = this.curTaskApply.paperConfirmAttachmentIds
  569. ? JSON.parse(this.curTaskApply.paperConfirmAttachmentIds)
  570. : [];
  571. this.buildSteps();
  572. if (this.IS_AUDIT) this.getExchangeApproverPeople();
  573. },
  574. async buildSteps() {
  575. if (
  576. !this.curTaskApply.flowId ||
  577. (this.curTaskApply.setup !== null && this.curTaskApply.setup <= 0)
  578. ) {
  579. this.$emit("step-change", []);
  580. return;
  581. }
  582. const flowStatus = {
  583. wait: "待进行",
  584. process: "进行中",
  585. success: "已完成"
  586. };
  587. const approveData = await taskAllApproverPeople({
  588. taskId: this.curTaskApply.flowTaskId
  589. });
  590. let approvePeople = {};
  591. approveData.approveUserList.forEach(item => {
  592. item.users = item.approveUser.map(
  593. user => `${user.realName}(${user.orgName})`
  594. );
  595. item.firstUser = item.users[0];
  596. item.moreUser = item.users.length > 1 ? item.users.join(",") : null;
  597. approvePeople[item.setup] = item;
  598. });
  599. const flowData = await taskAllFlowSetups(this.curTaskApply.flowId);
  600. const curSetup = this.curTaskApply.setup;
  601. const curStepIsLast = curSetup === flowData.length;
  602. this.flows = flowData.map(item => {
  603. item.status =
  604. curSetup > item.setup
  605. ? "success"
  606. : curSetup === item.setup
  607. ? "process"
  608. : "wait";
  609. item.desc = flowStatus[item.status];
  610. item.isCurrent = curSetup === item.setup;
  611. item = { ...item, ...approvePeople[item.setup] };
  612. return item;
  613. });
  614. if (!this.flows.length) {
  615. this.$emit("step-change", this.flows);
  616. return;
  617. }
  618. const curFlow = this.flows.find(item => item.isCurrent);
  619. if (curFlow) {
  620. const flows = curStepIsLast
  621. ? this.flows.slice(-2, -1)
  622. : this.flows.filter(item => item.setup < curFlow.setup);
  623. this.setups = flows.map(item => {
  624. return {
  625. taskKey: item.taskKey,
  626. setup: item.setup,
  627. taskName: `【${item.taskName}】${item.firstUser}`
  628. };
  629. });
  630. }
  631. // 下一节点审批人
  632. const nextFlow = this.flows.find(
  633. item => item.setup > this.curTaskApply.setup
  634. );
  635. if (
  636. (this.IS_APPLY || this.IS_AUDIT) &&
  637. nextFlow &&
  638. !nextFlow.approveUser.length
  639. ) {
  640. // 获取审批人
  641. this.needSetApproveUser = true;
  642. let datas = {};
  643. if (this.IS_APPLY) {
  644. datas.courseCode = this.curTaskApply.courseCode;
  645. }
  646. if (this.IS_AUDIT) {
  647. datas.taskId = this.curTaskApply.flowTaskId;
  648. }
  649. const data = await taskApproverNextPeople(datas);
  650. this.approveUserList =
  651. data && data.approveUserList && data.approveUserList[0].approveUser;
  652. }
  653. this.$emit("step-change", this.flows);
  654. },
  655. async getExchangeApproverPeople() {
  656. const data = await taskAllApproverExchangePeople({
  657. taskId: this.curTaskApply.flowTaskId
  658. });
  659. this.approveExchangePeople =
  660. (data &&
  661. data.approveUserList &&
  662. data.approveUserList[0] &&
  663. data.approveUserList[0].approveUser) ||
  664. [];
  665. const userId = this.$ls.get("user", { id: "" }).id;
  666. this.approveExchangePeople = this.approveExchangePeople.filter(
  667. user => user.id !== userId
  668. );
  669. },
  670. approvePassChange() {
  671. this.auditRules.remark[0].required =
  672. this.auditModal.approvePass === "REJECT";
  673. },
  674. addAtachment() {
  675. if (this.paperAttachments.length >= this.attachmentLimitCount) return;
  676. const name = this.abc[this.paperAttachments.length];
  677. const newAttachment = {
  678. name,
  679. attachmentId: "",
  680. filename: "",
  681. pages: 0,
  682. canDelete: true,
  683. isExposed: false
  684. };
  685. this.paperAttachments.push(newAttachment);
  686. },
  687. deleteAttachment(index) {
  688. if (this.paperAttachments.length <= 1) {
  689. this.$message.error("试卷类型数量不得少于1");
  690. return;
  691. }
  692. this.paperAttachments.splice(index, 1);
  693. this.paperAttachments.forEach((item, itemIndex) => {
  694. item.name = this.abc[itemIndex];
  695. });
  696. if (
  697. this.curTaskApply.drawCount &&
  698. this.curTaskApply.drawCount > this.paperAttachments.length
  699. ) {
  700. this.curTaskApply.drawCount = this.paperAttachments.length;
  701. }
  702. },
  703. toUpload(attachment) {
  704. this.curUploadType = "paper";
  705. this.curAttachment = {
  706. ...attachment
  707. };
  708. this.$refs.UploadPaperDialog.open();
  709. },
  710. toUploadPaperConfirm() {
  711. if (this.paperConfirmAttachments.length >= 4) return;
  712. this.curUploadType = "paperConfirm";
  713. this.curAttachment = {
  714. ...this.paperConfirmAttachmentId
  715. };
  716. this.$refs.UploadPaperDialog.open();
  717. },
  718. uploadConfirm(attachment, uploadType) {
  719. if (uploadType === "paper") {
  720. const index = this.paperAttachments.findIndex(
  721. item => item.name === attachment.name
  722. );
  723. this.paperAttachments.splice(index, 1, { ...attachment });
  724. } else {
  725. this.paperConfirmAttachments.push(attachment);
  726. }
  727. },
  728. deletePaperConfirmAttachment(index) {
  729. this.paperConfirmAttachments.splice(index, 1);
  730. },
  731. toViewCard() {
  732. window.open(
  733. this.getRouterPath({
  734. name: "CardPreview",
  735. params: {
  736. cardId: this.curTaskApply.cardId,
  737. viewType: "view"
  738. }
  739. })
  740. );
  741. },
  742. toEditCard() {
  743. this.cachePrepareTcpCard();
  744. this.$router.push({
  745. name: "CardDesign",
  746. params: {
  747. cardId: this.curTaskApply.cardId
  748. }
  749. });
  750. },
  751. cachePrepareTcpCard() {
  752. this.$ls.set("prepareTcPCard", {
  753. examTaskId: this.task.examTaskId,
  754. courseCode: this.task.courseCode,
  755. courseName: this.task.courseName,
  756. makeMethod: this.task.makeMethod,
  757. cardRuleId: this.task.cardRuleId
  758. });
  759. },
  760. async toCreateOrViewCard() {
  761. await this.silentSave();
  762. this.task = this.getTaskData();
  763. if (!this.curTaskApply.cardId) {
  764. this.$refs.CardOptionDialog.open();
  765. return;
  766. }
  767. if (this.curTaskApply.makeMethod === "SELECT") {
  768. this.$refs.CardOptionDialog.open();
  769. } else if (this.curTaskApply.makeMethod === "SELF") {
  770. this.toEditCard();
  771. } else {
  772. // 客服制卡:制作完毕则可以编辑,未制作完毕则可以查看
  773. if (this.curTaskApply.status === "SUBMIT") {
  774. this.toEditCard();
  775. } else {
  776. this.toViewCard();
  777. }
  778. }
  779. },
  780. cancel() {
  781. this.$emit("cancel");
  782. },
  783. async downloadPaper(attachment) {
  784. if (!attachment.attachmentId) return;
  785. const data = await attachmentPreview(attachment.attachmentId);
  786. window.open(data.url);
  787. },
  788. cardConfirm(data) {
  789. this.curTaskApply = this.$objAssign(this.curTaskApply, data);
  790. },
  791. async changeCreateCardType() {
  792. const h = this.$createElement;
  793. const result = await this.$msgbox({
  794. title: "切换题卡操作说明",
  795. message: h("div", null, [
  796. h("p", null, "1、切换题卡会将之前选择题卡数据删除。"),
  797. h(
  798. "p",
  799. null,
  800. "2、之前选择专卡进行绘制,切换题卡后再次选择专卡,需要重新开始绘制。"
  801. )
  802. ]),
  803. showCancelButton: true,
  804. type: "warning"
  805. }).catch(() => {});
  806. if (result !== "confirm") return;
  807. await this.clearMakeMethod();
  808. this.toCreateOrViewCard();
  809. },
  810. async clearMakeMethod() {
  811. // 清除后台记录的题卡
  812. if (this.curTaskApply.cardId && this.curTaskApply.makeMethod !== "CUST") {
  813. await switchCardCreateMethod(this.examTask.id);
  814. }
  815. this.curTaskApply.makeMethod = "";
  816. this.curTaskApply.cardId = "";
  817. },
  818. getTaskData() {
  819. let data = { ...this.curTaskApply };
  820. data.paperType = this.paperAttachments.map(item => item.name).join(",");
  821. data.paperAttachmentIds = JSON.stringify(this.paperAttachments, (k, v) =>
  822. k === "url" ? undefined : v
  823. );
  824. data.paperConfirmAttachmentIds = JSON.stringify(
  825. this.paperConfirmAttachments
  826. );
  827. if (this.needSetApproveUser) data.approveUserIds = this.approveUserIds;
  828. return data;
  829. },
  830. checkDataValid() {
  831. const attachmentValid = !this.paperAttachments.some(
  832. item => !item.attachmentId
  833. );
  834. // 设置了入库强制包含试卷时,校验试卷是否上传。
  835. if (this.curTaskApply.includePaper && !attachmentValid) {
  836. this.$message.error("请完成试卷文件上传!");
  837. return;
  838. }
  839. // if (!this.paperConfirmAttachments.length) {
  840. // this.$message.error("请上传附件!");
  841. // return;
  842. // }
  843. if (!this.curTaskApply.cardId) {
  844. this.$message.error("请选择题卡创建方式!");
  845. return;
  846. }
  847. if (
  848. this.curTaskApply.makeMethod !== "SELECT" &&
  849. this.curTaskApply.status !== "SUBMIT"
  850. ) {
  851. this.$message.error("请先提交题卡!");
  852. return;
  853. }
  854. if (this.needSetApproveUser && !this.approveUserIds.length) {
  855. this.$message.error("请指定审批人!");
  856. return;
  857. }
  858. return true;
  859. },
  860. async toSave() {
  861. if (this.isSubmit) return;
  862. this.isSubmit = true;
  863. const datas = this.getTaskData();
  864. datas.operateType = "STAGE";
  865. const data = await updateTaskApply(datas).catch(() => {});
  866. this.isSubmit = false;
  867. if (!data) return;
  868. this.$message.success("保存成功!");
  869. },
  870. async silentSave() {
  871. const datas = this.getTaskData();
  872. datas.operateType = "STAGE";
  873. await updateTaskApply(datas).catch(() => {});
  874. },
  875. async submit() {
  876. if (!this.checkDataValid()) return;
  877. const result = await this.$confirm(
  878. "任务确定提交后,则不可更改试卷及答题卡内容,确定提交该任务?",
  879. "提示",
  880. {
  881. type: "warning"
  882. }
  883. ).catch(() => {});
  884. if (result !== "confirm") return;
  885. const datas = this.getTaskData();
  886. datas.operateType = "SUBMIT";
  887. const data = await updateTaskApply(datas).catch(() => {});
  888. if (!data) return;
  889. this.$message.success("提交成功!");
  890. this.$emit("modified");
  891. },
  892. async toAuditSubmit() {
  893. const valid = await this.$refs.auditModalComp.validate().catch(() => {});
  894. if (!valid) return;
  895. if (
  896. this.auditModal.approvePass === "PASS" &&
  897. this.needSetApproveUser &&
  898. !this.approveUserIds.length
  899. ) {
  900. this.$message.error("请指定审批人!");
  901. return;
  902. }
  903. const actionName = this.TASK_AUDIT_RESULT[this.auditModal.approvePass];
  904. const result = await this.$confirm(
  905. `确定${actionName}该申请吗?`,
  906. "提示",
  907. {
  908. type: "warning"
  909. }
  910. ).catch(() => {});
  911. if (result !== "confirm") return;
  912. if (this.auditModal.approvePass === "EXCHANGE") {
  913. let datas = {
  914. taskId: this.curTaskApply.flowTaskId,
  915. userId: this.auditModal.userId
  916. };
  917. const data = await taskApproverExchange(datas).catch(() => {});
  918. if (!data) return;
  919. } else {
  920. let datas = { ...this.auditModal };
  921. datas.taskId = this.curTaskApply.flowTaskId;
  922. if (this.auditModal.approvePass === "PASS")
  923. datas.approveUserIds = this.approveUserIds;
  924. const data = await updateTaskReview(datas).catch(() => {});
  925. if (!data) return;
  926. }
  927. this.$message.success("审批成功!");
  928. this.$emit("modified");
  929. },
  930. async toAuditApply() {
  931. const result = await this.$confirm("确定提交该任务吗?", "提示", {
  932. type: "warning"
  933. }).catch(() => {});
  934. if (result !== "confirm") return;
  935. const datas = {
  936. examTaskDetail: this.getTaskData(),
  937. flowTaskId: this.curTaskApply.flowTaskId,
  938. approvePass: "PASS"
  939. };
  940. const data = await taskAuditApply(datas).catch(() => {});
  941. if (!data) return;
  942. this.$message.success("审批成功!");
  943. this.$emit("modified");
  944. },
  945. // image-preview
  946. toPreview(index) {
  947. this.curImageIndex = index;
  948. this.selectImage(index);
  949. this.$refs.SimpleImagePreview.open();
  950. },
  951. selectImage(index) {
  952. this.curImage = this.paperConfirmAttachments[index];
  953. },
  954. toPrevImage() {
  955. if (this.curImageIndex === 0) {
  956. this.curImageIndex = this.paperConfirmAttachments.length - 1;
  957. } else {
  958. this.curImageIndex--;
  959. }
  960. this.selectImage(this.curImageIndex);
  961. },
  962. toNextImage() {
  963. if (this.curImageIndex === this.paperConfirmAttachments.length - 1) {
  964. this.curImageIndex = 0;
  965. } else {
  966. this.curImageIndex++;
  967. }
  968. this.selectImage(this.curImageIndex);
  969. }
  970. }
  971. };
  972. </script>