ApplyContent.vue 13 KB

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