ApplyContent.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  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"
  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 v-model="auditModal.setup" placeholder="请选择">
  226. <el-option
  227. v-for="item in setups"
  228. :key="item.taskKey"
  229. :value="item.setup"
  230. :label="item.taskName"
  231. >
  232. </el-option>
  233. </el-select>
  234. </el-form-item>
  235. <el-form-item
  236. v-if="auditModal.approvePass !== 'EXCHANGE'"
  237. :key="auditModal.approvePass"
  238. prop="remark"
  239. label="审批意见:"
  240. >
  241. <el-input
  242. class="mb-2"
  243. v-model="auditModal.remark"
  244. type="textarea"
  245. resize="none"
  246. :rows="5"
  247. :maxlength="1000"
  248. clearable
  249. show-word-limit
  250. placeholder="建议不超过1000个字"
  251. ref="ReasonInput"
  252. ></el-input>
  253. </el-form-item>
  254. <el-form-item
  255. v-if="auditModal.approvePass === 'EXCHANGE'"
  256. prop="userId"
  257. label="审批人:"
  258. >
  259. <el-select
  260. v-model="auditModal.userId"
  261. filterable
  262. placeholder="请选择"
  263. >
  264. <el-option
  265. v-for="user in approveExchangePeople"
  266. :key="user.id"
  267. :value="user.id"
  268. :label="user.realName"
  269. ></el-option>
  270. </el-select>
  271. </el-form-item>
  272. <el-form-item
  273. v-if="needSetApproveUser && auditModal.approvePass === 'PASS'"
  274. label="指定审批人:"
  275. >
  276. <el-select
  277. v-model="approveUserIds"
  278. placeholder="请选择"
  279. multiple
  280. filterable
  281. clearable
  282. style="width: 700px"
  283. >
  284. <el-option
  285. v-for="user in approveUserList"
  286. :key="user.id"
  287. :value="user.id"
  288. :label="`${user.realName}(${user.orgName})`"
  289. >
  290. {{ user.realName }}({{ user.orgName }})
  291. </el-option>
  292. </el-select>
  293. </el-form-item>
  294. </el-form>
  295. </div>
  296. </div>
  297. <div class="task-action">
  298. <el-button
  299. v-if="IS_APPLY"
  300. type="primary"
  301. :disabled="isSubmit"
  302. @click="submit"
  303. >确认提交</el-button
  304. >
  305. <el-button
  306. v-if="IS_APPLY"
  307. type="primary"
  308. :disabled="isSubmit"
  309. @click="toSave"
  310. >暂存</el-button
  311. >
  312. <el-button
  313. v-if="IS_AUDIT"
  314. type="primary"
  315. :disabled="isSubmit"
  316. @click="toAuditApply"
  317. >确定</el-button
  318. >
  319. <el-button @click="cancel">取消</el-button>
  320. </div>
  321. <!-- upload-paper-dialog -->
  322. <upload-paper-dialog
  323. :paper-attachment="curAttachment"
  324. :upload-type="curUploadType"
  325. @confirm="uploadConfirm"
  326. ref="UploadPaperDialog"
  327. ></upload-paper-dialog>
  328. <!-- card-option-dialog -->
  329. <card-option-dialog
  330. ref="CardOptionDialog"
  331. :data="task"
  332. @upload-sample-over="initData"
  333. @draft-task="silentSave"
  334. @confirm="cardConfirm"
  335. ></card-option-dialog>
  336. <!-- image-preview -->
  337. <simple-image-preview
  338. :cur-image="curImage"
  339. @on-prev="toPrevImage"
  340. @on-next="toNextImage"
  341. ref="SimpleImagePreview"
  342. ></simple-image-preview>
  343. </div>
  344. </template>
  345. <script>
  346. import UploadPaperDialog from "./UploadPaperDialog";
  347. import CardOptionDialog from "./CardOptionDialog";
  348. import {
  349. taskApplyDetail,
  350. updateTaskApply,
  351. updateTaskReview,
  352. switchCardCreateMethod,
  353. taskAllFlowSetups,
  354. taskAllApproverPeople,
  355. taskAllApproverExchangePeople,
  356. taskApproverExchange,
  357. taskApproverNextPeople
  358. } from "../api";
  359. import { attachmentPreview } from "../../login/api";
  360. import SimpleImagePreview from "@/components/SimpleImagePreview";
  361. import { CARD_SOURCE_TYPE, TASK_AUDIT_RESULT } from "@/constants/enumerate";
  362. const initTaskApply = {
  363. examTaskId: "",
  364. paperType: "A",
  365. paperAttachmentIds: "",
  366. paperConfirmAttachmentIds: "",
  367. cardId: "",
  368. cardRuleId: "",
  369. makeMethod: "",
  370. remark: "",
  371. courseCode: "",
  372. courseName: "",
  373. drawCount: 1,
  374. exposedPaperType: "",
  375. // 流程
  376. flowId: "",
  377. setup: 0,
  378. // 工作台任务id
  379. flowTaskId: "",
  380. // 题卡状态
  381. status: "",
  382. // 考务规则
  383. review: false,
  384. includePaper: false,
  385. customCard: false
  386. };
  387. export default {
  388. name: "apply-content",
  389. components: { UploadPaperDialog, CardOptionDialog, SimpleImagePreview },
  390. props: {
  391. examTask: {
  392. type: Object,
  393. default() {
  394. return {};
  395. }
  396. },
  397. editType: {
  398. type: String,
  399. default: ""
  400. }
  401. },
  402. data() {
  403. return {
  404. isSubmit: false,
  405. curTaskApply: { ...initTaskApply },
  406. paperConfirmAttachmentId: { attachmentId: "", filename: "", url: "" },
  407. paperAttachments: [],
  408. paperConfirmAttachments: [],
  409. curAttachment: {},
  410. curUploadType: "paper",
  411. attachmentLimitCount: 26,
  412. abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
  413. task: {},
  414. reason: "",
  415. // audit
  416. TASK_AUDIT_RESULT: { ...TASK_AUDIT_RESULT, EXCHANGE: "转他人审批" },
  417. flows: [],
  418. setups: [],
  419. auditModal: {
  420. approvePass: "PASS",
  421. setup: "",
  422. remark: ""
  423. },
  424. auditRules: {
  425. approvePass: [
  426. {
  427. required: true
  428. }
  429. ],
  430. setup: [
  431. {
  432. required: true,
  433. validator: (rule, value, callback) => {
  434. if (this.auditModal.approvePass === "REJECT" && !value) {
  435. callback(new Error(`请选择要驳回到的节点`));
  436. } else {
  437. callback();
  438. }
  439. },
  440. trigger: "change"
  441. }
  442. ],
  443. remark: [
  444. {
  445. required: false,
  446. validator: (rule, value, callback) => {
  447. if (this.auditModal.approvePass === "REJECT" && !value) {
  448. callback(new Error(`请输入审批意见`));
  449. } else {
  450. callback();
  451. }
  452. },
  453. trigger: "change"
  454. }
  455. ],
  456. userId: [
  457. {
  458. required: true,
  459. message: "请选择审批人",
  460. trigger: "change"
  461. }
  462. ]
  463. },
  464. approveExchangePeople: [],
  465. needSetApproveUser: false,
  466. approveUserIds: [],
  467. approveUserList: [], //审批人
  468. // image-preview
  469. curImage: {},
  470. curImageIndex: 0
  471. };
  472. },
  473. computed: {
  474. IS_APPLY() {
  475. return this.editType
  476. ? this.editType === "APPLY"
  477. : this.curTaskApply.setup === 1 || this.curTaskApply.setup === null;
  478. },
  479. IS_PREVIEW() {
  480. return this.editType
  481. ? this.editType === "PREVIEW"
  482. : this.curTaskApply.setup !== null && this.curTaskApply.setup <= 0;
  483. },
  484. IS_AUDIT() {
  485. return this.editType
  486. ? this.editType === "AUDIT"
  487. : this.curTaskApply.setup > 1;
  488. },
  489. cardTodoName() {
  490. let name = "创建答题卡";
  491. if (this.curTaskApply.cardId) {
  492. if (this.curTaskApply.makeMethod === "SELECT") {
  493. name = "选择题卡";
  494. } else if (this.curTaskApply.makeMethod === "SELF") {
  495. name = "编辑题卡";
  496. } else {
  497. // 已经审核的题卡可以自行编辑,未审核的题卡只能查看
  498. name =
  499. this.curTaskApply.status === "SUBMIT" ? "编辑题卡" : "查看题卡";
  500. }
  501. }
  502. return name;
  503. },
  504. createCardTypeName() {
  505. return CARD_SOURCE_TYPE[this.curTaskApply.makeMethod] || "";
  506. },
  507. maxFetchCount() {
  508. return this.paperAttachments.length < 1
  509. ? 1
  510. : this.paperAttachments.length;
  511. },
  512. exposedMode() {
  513. return !!this.curTaskApply.exposedPaperType;
  514. }
  515. },
  516. mounted() {
  517. this.initData();
  518. },
  519. methods: {
  520. async initData() {
  521. const data = await taskApplyDetail(
  522. this.examTask.id,
  523. this.examTask.source
  524. );
  525. this.curTaskApply = this.$objAssign(initTaskApply, data || {});
  526. this.curTaskApply.examTaskId = this.examTask.id;
  527. this.curTaskApply.courseCode = this.examTask.courseCode;
  528. this.curTaskApply.courseName = this.examTask.courseName;
  529. this.curTaskApply.cardRuleId = this.examTask.cardRuleId;
  530. this.curTaskApply.customCard = this.examTask.customCard;
  531. this.curTaskApply.setup = this.examTask.setup;
  532. this.paperAttachments = this.curTaskApply.paperAttachmentIds
  533. ? JSON.parse(this.curTaskApply.paperAttachmentIds)
  534. : [];
  535. const exposedPaperType = data.exposedPaperType || "";
  536. let exposedPaperTypes = exposedPaperType.split(",");
  537. exposedPaperTypes.sort((a, b) => (a > b ? -1 : 1));
  538. const maxExposedPaperType = exposedPaperTypes[0];
  539. this.paperAttachments.forEach(paper => {
  540. paper.canDelete = maxExposedPaperType
  541. ? paper.name > maxExposedPaperType
  542. : true;
  543. paper.isExposed = exposedPaperTypes.includes(paper.name);
  544. });
  545. this.paperConfirmAttachments = this.curTaskApply.paperConfirmAttachmentIds
  546. ? JSON.parse(this.curTaskApply.paperConfirmAttachmentIds)
  547. : [];
  548. this.buildSteps();
  549. if (this.IS_AUDIT) this.getExchangeApproverPeople();
  550. },
  551. async buildSteps() {
  552. if (
  553. !this.curTaskApply.flowId ||
  554. (this.curTaskApply.setup !== null && this.curTaskApply.setup <= 0)
  555. ) {
  556. this.$emit("step-change", []);
  557. return;
  558. }
  559. const flowStatus = {
  560. wait: "待进行",
  561. process: "进行中",
  562. success: "已完成"
  563. };
  564. const approveData = await taskAllApproverPeople({
  565. taskId: this.curTaskApply.flowTaskId
  566. });
  567. let approvePeople = {};
  568. approveData.approveUserList.forEach(item => {
  569. item.users = item.approveUser.map(
  570. user => `${user.realName}(${user.orgName})`
  571. );
  572. item.firstUser = item.users[0];
  573. item.moreUser = item.users.length > 1 ? item.users.join(",") : null;
  574. approvePeople[item.setup] = item;
  575. });
  576. const flowData = await taskAllFlowSetups(this.curTaskApply.flowId);
  577. const curSetup = this.curTaskApply.setup;
  578. this.flows = flowData.map(item => {
  579. item.status =
  580. curSetup > item.setup
  581. ? "success"
  582. : curSetup === item.setup
  583. ? "process"
  584. : "wait";
  585. item.desc = flowStatus[item.status];
  586. item.isCurrent = curSetup === item.setup;
  587. item = { ...item, ...approvePeople[item.setup] };
  588. return item;
  589. });
  590. if (!this.flows.length) {
  591. this.$emit("step-change", this.flows);
  592. return;
  593. }
  594. const curFlow = this.flows.find(item => item.isCurrent);
  595. if (curFlow) {
  596. this.setups = this.flows
  597. .filter(item => item.setup < curFlow.setup)
  598. .map(item => {
  599. return {
  600. taskKey: item.taskKey,
  601. setup: item.setup,
  602. taskName: item.taskName
  603. };
  604. });
  605. }
  606. // 下一节点审批人
  607. const nextFlow = this.flows.find(
  608. item => item.setup > this.curTaskApply.setup
  609. );
  610. if (
  611. (this.IS_APPLY || this.IS_AUDIT) &&
  612. nextFlow &&
  613. !nextFlow.approveUser.length
  614. ) {
  615. // 获取审批人
  616. this.needSetApproveUser = true;
  617. let datas = {};
  618. if (this.IS_APPLY) {
  619. datas.courseCode = this.curTaskApply.courseCode;
  620. }
  621. if (this.IS_AUDIT) {
  622. datas.taskId = this.curTaskApply.flowTaskId;
  623. }
  624. const data = await taskApproverNextPeople(datas);
  625. this.approveUserList =
  626. data && data.approveUserList && data.approveUserList[0].approveUser;
  627. }
  628. this.$emit("step-change", this.flows);
  629. },
  630. async getExchangeApproverPeople() {
  631. const data = await taskAllApproverExchangePeople({
  632. taskId: this.curTaskApply.flowTaskId
  633. });
  634. this.approveExchangePeople =
  635. (data &&
  636. data.approveUserList &&
  637. data.approveUserList[0] &&
  638. data.approveUserList[0].approveUser) ||
  639. [];
  640. const userId = this.$ls.get("user", { id: "" }).id;
  641. this.approveExchangePeople = this.approveExchangePeople.filter(
  642. user => user.id !== userId
  643. );
  644. },
  645. approvePassChange() {
  646. this.auditRules.remark[0].required =
  647. this.auditModal.approvePass === "REJECT";
  648. },
  649. addAtachment() {
  650. if (this.paperAttachments.length >= this.attachmentLimitCount) return;
  651. const name = this.abc[this.paperAttachments.length];
  652. const newAttachment = {
  653. name,
  654. attachmentId: "",
  655. filename: "",
  656. pages: 0,
  657. canDelete: true,
  658. isExposed: false
  659. };
  660. this.paperAttachments.push(newAttachment);
  661. },
  662. deleteAttachment(index) {
  663. if (this.paperAttachments.length <= 1) {
  664. this.$message.error("试卷类型数量不得少于1");
  665. return;
  666. }
  667. this.paperAttachments.splice(index, 1);
  668. this.paperAttachments.forEach((item, itemIndex) => {
  669. item.name = this.abc[itemIndex];
  670. });
  671. if (
  672. this.curTaskApply.drawCount &&
  673. this.curTaskApply.drawCount > this.paperAttachments.length
  674. ) {
  675. this.curTaskApply.drawCount = this.paperAttachments.length;
  676. }
  677. },
  678. toUpload(attachment) {
  679. this.curUploadType = "paper";
  680. this.curAttachment = {
  681. ...attachment
  682. };
  683. this.$refs.UploadPaperDialog.open();
  684. },
  685. toUploadPaperConfirm() {
  686. if (this.paperConfirmAttachments.length >= 4) return;
  687. this.curUploadType = "paperConfirm";
  688. this.curAttachment = {
  689. ...this.paperConfirmAttachmentId
  690. };
  691. this.$refs.UploadPaperDialog.open();
  692. },
  693. uploadConfirm(attachment, uploadType) {
  694. if (uploadType === "paper") {
  695. const index = this.paperAttachments.findIndex(
  696. item => item.name === attachment.name
  697. );
  698. this.paperAttachments.splice(index, 1, { ...attachment });
  699. } else {
  700. this.paperConfirmAttachments.push(attachment);
  701. }
  702. },
  703. deletePaperConfirmAttachment(index) {
  704. this.paperConfirmAttachments.splice(index, 1);
  705. },
  706. toViewCard() {
  707. window.open(
  708. this.getRouterPath({
  709. name: "CardPreview",
  710. params: {
  711. cardId: this.curTaskApply.cardId,
  712. viewType: "view"
  713. }
  714. })
  715. );
  716. },
  717. toEditCard() {
  718. this.cachePrepareTcpCard();
  719. this.$router.push({
  720. name: "CardDesign",
  721. params: {
  722. cardId: this.curTaskApply.cardId
  723. }
  724. });
  725. },
  726. cachePrepareTcpCard() {
  727. this.$ls.set("prepareTcPCard", {
  728. examTaskId: this.task.examTaskId,
  729. courseCode: this.task.courseCode,
  730. courseName: this.task.courseName,
  731. makeMethod: this.task.makeMethod,
  732. cardRuleId: this.task.cardRuleId
  733. });
  734. },
  735. async toCreateOrViewCard() {
  736. await this.silentSave();
  737. this.task = this.getTaskData();
  738. if (!this.curTaskApply.cardId) {
  739. this.$refs.CardOptionDialog.open();
  740. return;
  741. }
  742. if (this.curTaskApply.makeMethod === "SELECT") {
  743. this.$refs.CardOptionDialog.open();
  744. } else if (this.curTaskApply.makeMethod === "SELF") {
  745. this.toEditCard();
  746. } else {
  747. // 客服制卡:制作完毕则可以编辑,未制作完毕则可以查看
  748. if (this.curTaskApply.status === "SUBMIT") {
  749. this.toEditCard();
  750. } else {
  751. this.toViewCard();
  752. }
  753. }
  754. },
  755. cancel() {
  756. this.$emit("cancel");
  757. },
  758. async downloadPaper(attachment) {
  759. if (!attachment.attachmentId) return;
  760. const data = await attachmentPreview(attachment.attachmentId);
  761. window.open(data.url);
  762. },
  763. cardConfirm(data) {
  764. this.curTaskApply = this.$objAssign(this.curTaskApply, data);
  765. },
  766. async changeCreateCardType() {
  767. const h = this.$createElement;
  768. const result = await this.$msgbox({
  769. title: "切换题卡操作说明",
  770. message: h("div", null, [
  771. h("p", null, "1、切换题卡会将之前选择题卡数据删除。"),
  772. h(
  773. "p",
  774. null,
  775. "2、之前选择专卡进行绘制,切换题卡后再次选择专卡,需要重新开始绘制。"
  776. )
  777. ]),
  778. showCancelButton: true,
  779. type: "warning"
  780. }).catch(() => {});
  781. if (result !== "confirm") return;
  782. await this.clearMakeMethod();
  783. this.toCreateOrViewCard();
  784. },
  785. async clearMakeMethod() {
  786. // 清除后台记录的题卡
  787. if (this.curTaskApply.cardId && this.curTaskApply.makeMethod !== "CUST") {
  788. await switchCardCreateMethod(this.examTask.id);
  789. }
  790. this.curTaskApply.makeMethod = "";
  791. this.curTaskApply.cardId = "";
  792. },
  793. getTaskData() {
  794. let data = { ...this.curTaskApply };
  795. data.paperType = this.paperAttachments.map(item => item.name).join(",");
  796. data.paperAttachmentIds = JSON.stringify(this.paperAttachments, (k, v) =>
  797. k === "url" ? undefined : v
  798. );
  799. data.paperConfirmAttachmentIds = JSON.stringify(
  800. this.paperConfirmAttachments
  801. );
  802. if (this.needSetApproveUser) data.approveUserIds = this.approveUserIds;
  803. return data;
  804. },
  805. checkDataValid() {
  806. const attachmentValid = !this.paperAttachments.some(
  807. item => !item.attachmentId
  808. );
  809. // 设置了入库强制包含试卷时,校验试卷是否上传。
  810. if (this.curTaskApply.includePaper && !attachmentValid) {
  811. this.$message.error("请完成试卷文件上传!");
  812. return;
  813. }
  814. // if (!this.paperConfirmAttachments.length) {
  815. // this.$message.error("请上传附件!");
  816. // return;
  817. // }
  818. if (!this.curTaskApply.cardId) {
  819. this.$message.error("请选择题卡创建方式!");
  820. return;
  821. }
  822. if (
  823. this.curTaskApply.makeMethod !== "SELECT" &&
  824. this.curTaskApply.status !== "SUBMIT"
  825. ) {
  826. this.$message.error("请先提交题卡!");
  827. return;
  828. }
  829. if (this.needSetApproveUser && !this.approveUserIds.length) {
  830. this.$message.error("请指定审批人!");
  831. return;
  832. }
  833. return true;
  834. },
  835. async toSave() {
  836. if (this.isSubmit) return;
  837. this.isSubmit = true;
  838. const datas = this.getTaskData();
  839. datas.operateType = "STAGE";
  840. const data = await updateTaskApply(datas).catch(() => {});
  841. this.isSubmit = false;
  842. if (!data) return;
  843. this.$message.success("保存成功!");
  844. },
  845. async silentSave() {
  846. const datas = this.getTaskData();
  847. datas.operateType = "STAGE";
  848. await updateTaskApply(datas).catch(() => {});
  849. },
  850. async submit() {
  851. if (!this.checkDataValid()) return;
  852. const result = await this.$confirm(
  853. "任务确定提交后,则不可更改试卷及答题卡内容,确定提交该任务?",
  854. "提示",
  855. {
  856. type: "warning"
  857. }
  858. ).catch(() => {});
  859. if (result !== "confirm") return;
  860. const datas = this.getTaskData();
  861. datas.operateType = "SUBMIT";
  862. const data = await updateTaskApply(datas).catch(() => {});
  863. if (!data) return;
  864. this.$message.success("提交成功!");
  865. this.$emit("modified");
  866. },
  867. async toAuditApply() {
  868. const valid = await this.$refs.auditModalComp.validate().catch(() => {});
  869. if (!valid) return;
  870. if (
  871. this.auditModal.approvePass === "PASS" &&
  872. this.needSetApproveUser &&
  873. !this.approveUserIds.length
  874. ) {
  875. this.$message.error("请指定审批人!");
  876. return;
  877. }
  878. const actionName = this.TASK_AUDIT_RESULT[this.auditModal.approvePass];
  879. const result = await this.$confirm(
  880. `确定${actionName}该申请吗?`,
  881. "提示",
  882. {
  883. type: "warning"
  884. }
  885. ).catch(() => {});
  886. if (result !== "confirm") return;
  887. if (this.auditModal.approvePass === "EXCHANGE") {
  888. let datas = {
  889. taskId: this.curTaskApply.flowTaskId,
  890. userId: this.auditModal.userId
  891. };
  892. const data = await taskApproverExchange(datas).catch(() => {});
  893. if (!data) return;
  894. } else {
  895. let datas = { ...this.auditModal };
  896. datas.taskId = this.curTaskApply.flowTaskId;
  897. if (this.auditModal.approvePass === "PASS")
  898. datas.approveUserIds = this.approveUserIds;
  899. const data = await updateTaskReview(datas).catch(() => {});
  900. if (!data) return;
  901. }
  902. this.$message.success("审批成功!");
  903. this.$emit("modified");
  904. },
  905. // image-preview
  906. toPreview(index) {
  907. this.curImageIndex = index;
  908. this.selectImage(index);
  909. this.$refs.SimpleImagePreview.open();
  910. },
  911. selectImage(index) {
  912. this.curImage = this.paperConfirmAttachments[index];
  913. },
  914. toPrevImage() {
  915. if (this.curImageIndex === 0) {
  916. this.curImageIndex = this.paperConfirmAttachments.length - 1;
  917. } else {
  918. this.curImageIndex--;
  919. }
  920. this.selectImage(this.curImageIndex);
  921. },
  922. toNextImage() {
  923. if (this.curImageIndex === this.paperConfirmAttachments.length - 1) {
  924. this.curImageIndex = 0;
  925. } else {
  926. this.curImageIndex++;
  927. }
  928. this.selectImage(this.curImageIndex);
  929. }
  930. }
  931. };
  932. </script>