TaskReviewManage.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. <template>
  2. <div class="task-review-manage">
  3. <div class="mb-4">
  4. <el-button
  5. v-for="(val, key) in AUDITING_STATUS"
  6. :key="key"
  7. :type="auditStatus == key ? 'primary' : 'default'"
  8. @click="selectMenu(key)"
  9. >{{ val }}</el-button
  10. >
  11. </div>
  12. <div class="part-box part-box-filter part-box-flex">
  13. <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
  14. <el-form-item label="题卡规则:">
  15. <card-rule-select
  16. ref="CardRuleSelect"
  17. v-model.trim="filter.cardRuleId"
  18. placeholder="请选择"
  19. clearable
  20. ></card-rule-select>
  21. </el-form-item>
  22. <el-form-item label="课程(代码):" label-width="110px">
  23. <course-select
  24. ref="CourseSelect"
  25. v-model.trim="filter.courseCode"
  26. placeholder="请选择"
  27. clearable
  28. ></course-select>
  29. </el-form-item>
  30. <el-form-item label="试卷编号:">
  31. <paper-number-select
  32. ref="PaperNumberSelect"
  33. v-model="filter.paperNumber"
  34. placeholder="请选择"
  35. clearable
  36. ></paper-number-select>
  37. </el-form-item>
  38. <el-form-item label="命题老师:">
  39. <question-teacher-select
  40. ref="QuestionTeacherSelect"
  41. v-model="filter.userId"
  42. :course-code="filter.courseCode"
  43. placeholder="请选择"
  44. ></question-teacher-select>
  45. </el-form-item>
  46. <el-form-item label="命题时间:">
  47. <el-date-picker
  48. v-model="createTime"
  49. type="datetimerange"
  50. :picker-options="pickerOptions"
  51. range-separator="至"
  52. start-placeholder="开始日期"
  53. end-placeholder="结束日期"
  54. value-format="timestamp"
  55. align="right"
  56. unlink-panels
  57. >
  58. </el-date-picker>
  59. </el-form-item>
  60. <el-form-item label="审核结果:" v-if="AUDITED">
  61. <el-select
  62. v-model="filter.reviewStatus"
  63. style="width: 142px;"
  64. placeholder="请选择"
  65. clearable
  66. >
  67. <el-option
  68. v-for="(val, key) in AUDITING_RESULT"
  69. :key="key"
  70. :value="key"
  71. :label="val"
  72. ></el-option>
  73. </el-select>
  74. </el-form-item>
  75. <el-form-item label-width="0px">
  76. <el-button type="primary" icon="icon icon-search" @click="toPage(1)"
  77. >查询</el-button
  78. >
  79. </el-form-item>
  80. </el-form>
  81. <div class="part-box-action" v-if="!AUDITED">
  82. <el-button
  83. icon="el-icon-download"
  84. type="primary"
  85. :disabled="loading"
  86. @click="toExport"
  87. >
  88. 导出审核样本
  89. </el-button>
  90. <el-button
  91. icon="el-icon-coordinate"
  92. type="danger"
  93. @click="toBatchAudit(0)"
  94. >
  95. 批量不通过
  96. </el-button>
  97. <el-button
  98. icon="el-icon-coordinate"
  99. type="primary"
  100. @click="toBatchAudit(1)"
  101. >
  102. 批量通过
  103. </el-button>
  104. </div>
  105. </div>
  106. <div class="part-box">
  107. <el-table
  108. ref="TableList"
  109. :data="examTasks"
  110. border
  111. stripe
  112. @selection-change="handleSelectionChange"
  113. >
  114. <el-table-column
  115. v-if="!AUDITED"
  116. type="selection"
  117. width="55"
  118. ></el-table-column>
  119. <el-table-column
  120. type="index"
  121. label="序号"
  122. width="70"
  123. align="center"
  124. :index="indexMethod"
  125. ></el-table-column>
  126. <el-table-column
  127. prop="paperNumber"
  128. label="试卷编号"
  129. width="120"
  130. ></el-table-column>
  131. <el-table-column prop="courseName" label="课程(代码)">
  132. <template slot-scope="scope">
  133. {{ scope.row.courseName }}({{ scope.row.courseCode }})
  134. </template>
  135. </el-table-column>
  136. <el-table-column
  137. prop="specialty"
  138. label="适用专业(方向)"
  139. ></el-table-column>
  140. <el-table-column prop="cardRuleName" label="题卡规则"></el-table-column>
  141. <el-table-column
  142. prop="userName"
  143. label="命题老师"
  144. width="100"
  145. ></el-table-column>
  146. <el-table-column prop="startTime" label="命题开始时间">
  147. <span slot-scope="scope">{{
  148. scope.row.startTime | timestampFilter
  149. }}</span>
  150. </el-table-column>
  151. <el-table-column prop="endTime" label="命题结束时间">
  152. <span slot-scope="scope">{{
  153. scope.row.endTime | timestampFilter
  154. }}</span>
  155. </el-table-column>
  156. <el-table-column prop="createTime" label="申请时间">
  157. <template slot-scope="scope">
  158. {{ scope.row.createTime | timestampFilter }}
  159. </template>
  160. </el-table-column>
  161. <el-table-column
  162. class-name="action-column"
  163. label="操作"
  164. align="center"
  165. width="80px"
  166. >
  167. <template slot-scope="scope">
  168. <el-button
  169. v-if="auditStatus === 'NOT_AUDITED'"
  170. class="btn-table-icon"
  171. type="text"
  172. icon="icon icon-edit"
  173. @click="toEdit(scope.row)"
  174. title="审核"
  175. ></el-button>
  176. <el-button
  177. v-else
  178. class="btn-table-icon"
  179. type="text"
  180. icon="icon icon-circle-right"
  181. @click="toPreview(scope.row)"
  182. title="查看详情"
  183. ></el-button>
  184. </template>
  185. </el-table-column>
  186. </el-table>
  187. <div class="part-page">
  188. <el-pagination
  189. background
  190. layout="total,prev, pager, next"
  191. :current-page="current"
  192. :total="total"
  193. :page-size="size"
  194. @current-change="toPage"
  195. >
  196. </el-pagination>
  197. </div>
  198. </div>
  199. <!-- ModifyTaskApply -->
  200. <modify-task-apply
  201. ref="ModifyTaskApply"
  202. :edit-type="editType"
  203. :instance="curExamTask"
  204. @modified="taskModified"
  205. ></modify-task-apply>
  206. <!-- audit-dialog-->
  207. <el-dialog
  208. class="modify-task-apply"
  209. :visible.sync="auditDialogShow"
  210. title="审核意见"
  211. width="500px"
  212. :close-on-click-modal="false"
  213. :close-on-press-escape="false"
  214. append-to-body
  215. >
  216. <el-form ref="AuditForm" :rules="auditRules" :model="auditModal">
  217. <el-form-item prop="reason">
  218. <el-input
  219. class="mb-2"
  220. v-model.trim="auditModal.reason"
  221. type="textarea"
  222. resize="none"
  223. :rows="5"
  224. :maxlength="1000"
  225. clearable
  226. show-word-limit
  227. placeholder="建议不超过1000个字"
  228. ></el-input>
  229. </el-form-item>
  230. </el-form>
  231. <div slot="footer">
  232. <el-button type="primary" @click="auditNotPass">确认</el-button>
  233. <el-button type="danger" @click="auditDialogShow = false" plain
  234. >取消</el-button
  235. >
  236. </div>
  237. </el-dialog>
  238. </div>
  239. </template>
  240. <script>
  241. import ModifyTaskApply from "../components/ModifyTaskApply";
  242. import { AUDITING_RESULT, AUDITING_STATUS } from "@/constants/enumerate";
  243. import pickerOptions from "@/constants/datePickerOptions";
  244. import {
  245. taskReviewAuditedListPage,
  246. taskReviewUnauditedListPage,
  247. batchUpdateTaskReview
  248. } from "../api";
  249. import { download, randomCode } from "@/plugins/utils";
  250. import { mapActions } from "vuex";
  251. export default {
  252. name: "task-review-manage",
  253. components: {
  254. ModifyTaskApply
  255. },
  256. data() {
  257. return {
  258. auditStatus: "NOT_AUDITED",
  259. filter: {
  260. userId: "",
  261. cardRuleId: "",
  262. courseCode: "",
  263. paperNumber: "",
  264. startTime: null,
  265. endTime: null
  266. },
  267. current: 1,
  268. size: this.GLOBAL.pageSize,
  269. total: 0,
  270. editType: "APPLY",
  271. AUDITING_RESULT,
  272. AUDITING_STATUS,
  273. caches: {},
  274. examTasks: [],
  275. curExamTask: {},
  276. multipleSelection: [],
  277. loading: false,
  278. // audit-dialog
  279. auditDialogShow: false,
  280. auditModal: { reason: "" },
  281. auditRules: {
  282. reason: [
  283. { required: true, message: "请输入审核意见", trigger: "change" }
  284. ]
  285. },
  286. // date-picker
  287. createTime: [],
  288. pickerOptions
  289. };
  290. },
  291. computed: {
  292. AUDITED() {
  293. return this.auditStatus === "AUDITED";
  294. }
  295. },
  296. created() {
  297. this.toPage(1);
  298. },
  299. methods: {
  300. ...mapActions("exam", ["updateWaitTaskCount"]),
  301. async getList() {
  302. const datas = {
  303. ...this.filter,
  304. pageNumber: this.current,
  305. pageSize: this.size
  306. };
  307. if (this.createTime) {
  308. datas.startTime = this.createTime[0];
  309. datas.endTime = this.createTime[1];
  310. }
  311. const func = this.AUDITED
  312. ? taskReviewAuditedListPage
  313. : taskReviewUnauditedListPage;
  314. const data = await func(datas);
  315. this.examTasks = data.records;
  316. this.total = data.total;
  317. },
  318. toPage(page) {
  319. this.current = page;
  320. this.getList();
  321. this.multipleSelection = [];
  322. },
  323. handleSelectionChange(val) {
  324. this.multipleSelection = val.map(item => item.id);
  325. console.log(this.multipleSelection);
  326. },
  327. selectMenu(val) {
  328. this.caches[this.auditStatus] = {
  329. current: this.current,
  330. examTasks: this.examTasks,
  331. total: this.total
  332. };
  333. this.auditStatus = val;
  334. if (this.caches[val] && this.caches[val].examTasks) {
  335. this.current = this.caches[val].current;
  336. this.total = this.caches[val].total;
  337. this.examTasks = this.caches[val].examTasks;
  338. } else {
  339. this.toPage(1);
  340. }
  341. },
  342. toBatchAudit(isPass) {
  343. if (!this.multipleSelection.length) {
  344. this.$message.error("请选择要审核的记录!");
  345. return;
  346. }
  347. if (isPass) {
  348. this.auditApply("PASS", this.multipleSelection);
  349. } else {
  350. this.auditModal.reason = "";
  351. this.auditDialogShow = true;
  352. }
  353. },
  354. async auditNotPass() {
  355. const valid = await this.$refs.AuditForm.validate().catch(() => {});
  356. if (!valid) return;
  357. await this.auditApply("NOT_PASS", this.multipleSelection);
  358. this.auditDialogShow = false;
  359. },
  360. async auditApply(type, ids) {
  361. const data = await batchUpdateTaskReview({
  362. reviewStatus: type,
  363. examTaskIds: ids,
  364. reason: this.auditModal.reason
  365. }).catch(() => {});
  366. if (!data) return;
  367. this.$message.success("审核成功!");
  368. this.taskModified();
  369. },
  370. async toExport() {
  371. if (this.loading) return;
  372. if (!this.multipleSelection.length) {
  373. this.$message.error("请选择要导出的记录!");
  374. return;
  375. }
  376. this.loading = true;
  377. const res = await download({
  378. type: "post",
  379. url: this.GLOBAL.domain + "/api/admin/exam/task_review/export",
  380. data: {
  381. examTaskIds: this.multipleSelection
  382. },
  383. fileName: `${Date.now()}${randomCode()}.zip`,
  384. header: this.getHeadIds()
  385. }).catch(error => {
  386. this.$message.error(error + "文件下载失败,请重新尝试!");
  387. });
  388. this.loading = false;
  389. if (!res) return;
  390. this.$message.success("文件下载成功!");
  391. },
  392. toEdit(row) {
  393. this.curExamTask = row;
  394. this.editType = "AUDIT";
  395. this.$refs.ModifyTaskApply.open();
  396. },
  397. toPreview(row) {
  398. this.curExamTask = row;
  399. this.editType = "PREVIEW";
  400. this.$refs.ModifyTaskApply.open();
  401. },
  402. taskModified() {
  403. this.getList();
  404. this.updateWaitTaskCount();
  405. }
  406. }
  407. };
  408. </script>