ApplyContent.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. <template>
  2. <div class="apply-content task-detail">
  3. <p class="tips-info tips-dark mb-2">
  4. 提示:多卷型试卷由于会绑定一个答题卡模板,因此试卷结构必须相同。多卷型试卷之间客观题要求试题内容相同,可允许大题内的小题题序不同。
  5. </p>
  6. <div class="task-body">
  7. <div v-if="IS_APPLY" class="mb-2 text-right">
  8. <el-button @click="addAtachment" icon="icon icon-plus-act"
  9. >增加卷型</el-button
  10. >
  11. </div>
  12. <table class="table">
  13. <tr>
  14. <th>试卷类型</th>
  15. <th>试卷文件</th>
  16. <th>答题卡</th>
  17. <th v-if="IS_APPLY">操作</th>
  18. </tr>
  19. <tr v-for="(attachment, index) in paperAttachments" :key="index">
  20. <td>{{ attachment.name }}卷</td>
  21. <td class="td-link">
  22. <span
  23. v-if="IS_APPLY"
  24. @click="toUpload(attachment)"
  25. title="点击上传试卷"
  26. >
  27. <i
  28. :class="[
  29. 'icon',
  30. attachment.attachmentId ? 'icon-files-act' : 'icon-files'
  31. ]"
  32. ></i
  33. >{{
  34. attachment.attachmentId
  35. ? attachment.filename
  36. : "点击上传试卷文件"
  37. }}
  38. </span>
  39. <span
  40. v-else
  41. @click="downloadPaper(attachment)"
  42. title="点击下载试卷"
  43. >
  44. <i class="icon icon-download-act"></i>
  45. <i>{{ attachment.filename }}</i>
  46. </span>
  47. </td>
  48. <td
  49. class="td-link"
  50. :rowspan="paperAttachments.length"
  51. v-if="index === 0"
  52. >
  53. <span v-if="IS_APPLY" @click="toCreateOrViewCard"
  54. ><i class="icon icon-plus-act"></i>{{ cardTodoName }}</span
  55. >
  56. <span v-else @click="toViewCard">
  57. <i class="icon icon-circle-right"></i>
  58. <i>查看题卡</i>
  59. </span>
  60. </td>
  61. <td v-if="IS_APPLY">
  62. <el-button
  63. class="btn-table-icon"
  64. type="text"
  65. icon="icon icon-delete"
  66. title="删除"
  67. @click="deleteAttachment(index)"
  68. ></el-button>
  69. </td>
  70. </tr>
  71. </table>
  72. <h4 class="mb-2">备注说明:</h4>
  73. <el-input
  74. class="mb-2"
  75. v-model.trim="curTaskApply.remark"
  76. type="textarea"
  77. resize="none"
  78. :rows="2"
  79. :maxlength="100"
  80. clearable
  81. show-word-limit
  82. placeholder="建议不超过100个字"
  83. :disabled="!IS_APPLY"
  84. ></el-input>
  85. <h4 class="mb-2">上传入库审核表(最多4张)</h4>
  86. <div class="image-list">
  87. <div
  88. class="image-item"
  89. v-for="(img, index) in paperConfirmAttachments"
  90. :key="index"
  91. >
  92. <img :src="img.url" :alt="img.filename" />
  93. <div v-if="IS_APPLY" class="image-delete">
  94. <i
  95. class="el-icon-delete-solid"
  96. @click="deletePaperConfirmAttachment(index)"
  97. ></i>
  98. </div>
  99. </div>
  100. <div
  101. v-if="paperConfirmAttachments.length < 4 && IS_APPLY"
  102. class="image-item image-add"
  103. title="上传入库审核表"
  104. @click="toUploadPaperConfirm"
  105. >
  106. <i class="el-icon-plus"></i>
  107. </div>
  108. </div>
  109. <!-- audit -->
  110. <h4 v-if="IS_AUDIT" class="mb-2">审核意见:</h4>
  111. <el-input
  112. v-if="IS_AUDIT"
  113. class="mb-2"
  114. v-model.trim="reason"
  115. type="textarea"
  116. resize="none"
  117. :rows="5"
  118. :maxlength="1000"
  119. clearable
  120. show-word-limit
  121. placeholder="建议不超过1000个字"
  122. ></el-input>
  123. </div>
  124. <div class="task-action">
  125. <el-button
  126. v-if="IS_APPLY"
  127. type="primary"
  128. :disabled="isSubmit"
  129. @click="submit"
  130. >确认提交</el-button
  131. >
  132. <el-button
  133. v-if="IS_APPLY"
  134. type="primary"
  135. :disabled="isSubmit"
  136. style="width:88px;"
  137. @click="toSave"
  138. >暂存</el-button
  139. >
  140. <el-button
  141. v-if="IS_AUDIT"
  142. type="primary"
  143. :disabled="isSubmit"
  144. @click="toAuditApply('PASS')"
  145. >通过</el-button
  146. >
  147. <el-button
  148. v-if="IS_AUDIT"
  149. type="danger"
  150. plain
  151. @click="toAuditApply('NOT_PASS')"
  152. >不通过</el-button
  153. >
  154. <el-button type="danger" @click="cancel" plain>取消</el-button>
  155. </div>
  156. <!-- upload-paper-dialog -->
  157. <upload-paper-dialog
  158. :paper-attachment="curAttachment"
  159. :upload-type="curUploadType"
  160. @confirm="uploadConfirm"
  161. ref="UploadPaperDialog"
  162. ></upload-paper-dialog>
  163. <!-- card-option-dialog -->
  164. <card-option-dialog
  165. :data="task"
  166. ref="CardOptionDialog"
  167. @upload-sample-over="initData"
  168. @draft-task="silentSave"
  169. @confirm="cardConfirm"
  170. ></card-option-dialog>
  171. </div>
  172. </template>
  173. <script>
  174. import UploadPaperDialog from "./UploadPaperDialog";
  175. import CardOptionDialog from "./CardOptionDialog";
  176. import { taskApplyDetail, updateTaskApply, updateTaskReview } from "../api";
  177. const initTaskApply = {
  178. examTaskId: "",
  179. paperType: "A",
  180. paperAttachmentIds: "",
  181. paperConfirmAttachmentIds: "",
  182. cardId: "",
  183. cardRuleId: "",
  184. makeMethod: "",
  185. remark: "",
  186. courseCode: "",
  187. courseName: "",
  188. status: "" // 题卡状态
  189. };
  190. export default {
  191. name: "apply-content",
  192. components: { UploadPaperDialog, CardOptionDialog },
  193. props: {
  194. examTask: {
  195. type: Object,
  196. default() {
  197. return {};
  198. }
  199. },
  200. editType: {
  201. type: String,
  202. default: "APPLY",
  203. validator: val => ["APPLY", "PREVIEW", "AUDIT"].includes(val)
  204. }
  205. },
  206. data() {
  207. return {
  208. isSubmit: false,
  209. curTaskApply: { ...initTaskApply },
  210. paperConfirmAttachmentId: { attachmentId: "", filename: "", url: "" },
  211. paperAttachments: [],
  212. paperConfirmAttachments: [],
  213. curAttachment: {},
  214. curUploadType: "paper",
  215. attachmentLimitCount: 26,
  216. abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
  217. task: {},
  218. reason: ""
  219. };
  220. },
  221. computed: {
  222. IS_APPLY() {
  223. return this.editType === "APPLY";
  224. },
  225. IS_PREVIEW() {
  226. return this.editType === "PREVIEW";
  227. },
  228. IS_AUDIT() {
  229. return this.editType === "AUDIT";
  230. },
  231. cardTodoName() {
  232. let name = "创建答题卡";
  233. if (this.curTaskApply.cardId) {
  234. if (this.curTaskApply.makeMethod === "SELECT") {
  235. name = "选择题卡";
  236. } else if (this.curTaskApply.makeMethod === "SELF") {
  237. name = "编辑题卡";
  238. } else {
  239. // 已经审核的题卡可以自行编辑,未审核的题卡只能查看
  240. name =
  241. this.curTaskApply.status === "SUBMIT" ? "编辑题卡" : "查看题卡";
  242. }
  243. }
  244. return name;
  245. }
  246. },
  247. mounted() {
  248. this.initData();
  249. },
  250. methods: {
  251. async initData() {
  252. const data = await taskApplyDetail(this.examTask.id);
  253. this.curTaskApply = this.$objAssign(initTaskApply, data || {});
  254. this.curTaskApply.examTaskId = this.examTask.id;
  255. this.curTaskApply.courseCode = this.examTask.courseCode;
  256. this.curTaskApply.courseName = this.examTask.courseName;
  257. this.curTaskApply.cardRuleId = this.examTask.cardRuleId;
  258. this.paperAttachments = this.curTaskApply.paperAttachmentIds
  259. ? JSON.parse(this.curTaskApply.paperAttachmentIds)
  260. : [];
  261. this.paperConfirmAttachments = this.curTaskApply.paperConfirmAttachmentIds
  262. ? JSON.parse(this.curTaskApply.paperConfirmAttachmentIds)
  263. : [];
  264. },
  265. addAtachment() {
  266. if (this.paperAttachments.length >= this.attachmentLimitCount) return;
  267. const newAttachment = {
  268. name: this.abc[this.paperAttachments.length],
  269. attachmentId: "",
  270. filename: "",
  271. pages: 0
  272. };
  273. this.paperAttachments.push(newAttachment);
  274. },
  275. deleteAttachment(index) {
  276. if (this.paperAttachments.length <= 1) {
  277. this.$message.error("试卷类型数量不得少于1");
  278. return;
  279. }
  280. this.paperAttachments.splice(index, 1);
  281. this.paperAttachments.forEach((item, itemIndex) => {
  282. item.name = this.abc[itemIndex];
  283. });
  284. },
  285. toUpload(attachment) {
  286. this.curUploadType = "paper";
  287. this.curAttachment = {
  288. ...attachment
  289. };
  290. this.$refs.UploadPaperDialog.open();
  291. },
  292. toUploadPaperConfirm() {
  293. if (this.paperConfirmAttachments.length >= 4) return;
  294. this.curUploadType = "paperConfirm";
  295. this.curAttachment = {
  296. ...this.paperConfirmAttachmentId
  297. };
  298. this.$refs.UploadPaperDialog.open();
  299. },
  300. uploadConfirm(attachment, uploadType) {
  301. if (uploadType === "paper") {
  302. const index = this.paperAttachments.findIndex(
  303. item => item.name === attachment.name
  304. );
  305. this.paperAttachments.splice(index, 1, { ...attachment });
  306. } else {
  307. this.paperConfirmAttachments.push(attachment);
  308. }
  309. },
  310. deletePaperConfirmAttachment(index) {
  311. this.paperConfirmAttachments.splice(index, 1);
  312. },
  313. toViewCard() {
  314. window.open(
  315. this.getRouterPath({
  316. name: "CardPreview",
  317. params: {
  318. cardId: this.curTaskApply.cardId,
  319. viewType: "view"
  320. }
  321. })
  322. );
  323. },
  324. toEditCard() {
  325. this.cachePrepareTcpCard();
  326. this.$router.push({
  327. name: "CardDesign",
  328. params: {
  329. cardId: this.curTaskApply.cardId
  330. }
  331. });
  332. },
  333. cachePrepareTcpCard() {
  334. this.$ls.set("prepareTcPCard", {
  335. examTaskId: this.task.examTaskId,
  336. courseCode: this.task.courseCode,
  337. courseName: this.task.courseName,
  338. makeMethod: this.task.makeMethod,
  339. cardRuleId: this.task.cardRuleId,
  340. paperType: this.task.paperType
  341. });
  342. },
  343. async toCreateOrViewCard() {
  344. await this.silentSave();
  345. this.task = this.getTaskData();
  346. if (!this.curTaskApply.cardId) {
  347. this.$refs.CardOptionDialog.open();
  348. return;
  349. }
  350. if (this.curTaskApply.makeMethod === "SELECT") {
  351. this.$refs.CardOptionDialog.open();
  352. } else if (this.curTaskApply.makeMethod === "SELF") {
  353. this.toEditCard();
  354. } else {
  355. // 客服制卡:制作完毕则可以编辑,未制作完毕则可以查看
  356. if (this.curTaskApply.status === "SUBMIT") {
  357. this.toEditCard();
  358. } else {
  359. this.toViewCard();
  360. }
  361. }
  362. },
  363. cancel() {
  364. this.$emit("cancel");
  365. },
  366. downloadPaper(attachment) {
  367. window.open(attachment.url);
  368. },
  369. cardConfirm(data) {
  370. this.curTaskApply = this.$objAssign(this.curTaskApply, data);
  371. },
  372. getTaskData() {
  373. let data = { ...this.curTaskApply };
  374. data.paperType = this.paperAttachments.map(item => item.name).join(",");
  375. data.paperAttachmentIds = JSON.stringify(this.paperAttachments);
  376. data.paperConfirmAttachmentIds = JSON.stringify(
  377. this.paperConfirmAttachments
  378. );
  379. return data;
  380. },
  381. checkDataValid() {
  382. const attachmentValid = !this.paperAttachments.some(
  383. item => !item.attachmentId
  384. );
  385. if (!attachmentValid) {
  386. this.$message.error("请完成试卷文件上传!");
  387. return;
  388. }
  389. if (!this.paperConfirmAttachments.length) {
  390. this.$message.error("请上传入库审核表!");
  391. return;
  392. }
  393. if (!this.curTaskApply.cardId) {
  394. this.$message.error("请选择题卡创建方式!");
  395. return;
  396. }
  397. if (
  398. this.curTaskApply.makeMethod !== "SELECT" &&
  399. this.curTaskApply.status !== "SUBMIT"
  400. ) {
  401. this.$message.error("请先提交题卡!");
  402. return;
  403. }
  404. return true;
  405. },
  406. async toSave() {
  407. if (this.isSubmit) return;
  408. this.isSubmit = true;
  409. const datas = this.getTaskData();
  410. datas.operateType = "STAGE";
  411. const data = await updateTaskApply(datas).catch(() => {});
  412. this.isSubmit = false;
  413. if (!data) return;
  414. this.$message.success("保存成功!");
  415. },
  416. async silentSave() {
  417. const datas = this.getTaskData();
  418. datas.operateType = "STAGE";
  419. await updateTaskApply(datas).catch(() => {});
  420. },
  421. async submit() {
  422. if (!this.checkDataValid()) return;
  423. this.$confirm(
  424. "任务确定提交后,则不可更改试卷及答题卡内容,确定提交该任务?",
  425. "提示",
  426. {
  427. cancelButtonClass: "el-button--danger is-plain",
  428. confirmButtonClass: "el-button--primary",
  429. type: "warning"
  430. }
  431. )
  432. .then(async () => {
  433. const datas = this.getTaskData();
  434. datas.operateType = "SUBMIT";
  435. const data = await updateTaskApply(datas).catch(() => {});
  436. if (!data) return;
  437. this.$message.success("提交成功!");
  438. this.$emit("modified");
  439. })
  440. .catch(() => {});
  441. },
  442. toAuditApply(type) {
  443. if (type === "PASS") {
  444. this.auditApply(type);
  445. } else {
  446. if (!this.reason) {
  447. this.$message.error("请输入审核意见!");
  448. return;
  449. }
  450. this.$confirm("确定不通过该申请吗?", "提示", {
  451. cancelButtonClass: "el-button--danger is-plain",
  452. confirmButtonClass: "el-button--primary",
  453. type: "warning"
  454. })
  455. .then(() => {
  456. this.auditApply(type);
  457. })
  458. .catch(() => {});
  459. }
  460. },
  461. async auditApply(type) {
  462. const data = await updateTaskReview({
  463. reviewStatus: type,
  464. examTaskId: this.examTask.id,
  465. reason: this.reason
  466. }).catch(() => {});
  467. if (!data) return;
  468. this.$message.success("审核成功!");
  469. this.$emit("modified");
  470. }
  471. }
  472. };
  473. </script>