Marking.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. <template>
  2. <div v-loading="loading" element-loading-text="拼命加载中">
  3. <section class="content-header">
  4. <span>
  5. <span class="pull-left">
  6. <small class="marktitle titlefont">
  7. <span>课程:{{ task.courseName }}</span>
  8. </small>
  9. <small class="marktitle titlefont">
  10. <span>试卷编号:{{ task.paperName }}</span>
  11. </small>
  12. <small class="marktitle titlefont">
  13. <span>待评:{{ task.leftCount }}</span>
  14. </small>
  15. <small class="marktitle titlefont">
  16. <span>
  17. 进度:{{
  18. (
  19. ((task.totalCount - task.leftCount) * 100) /
  20. task.totalCount
  21. ).toFixed(2)
  22. }}%
  23. </span>
  24. </small>
  25. <small class="marktitle">
  26. <el-button-group>
  27. <el-button size="small">
  28. <span class="titlefont">已评</span>
  29. </el-button>
  30. <el-button size="small" @click="markedClick">
  31. <span class="titlefont">{{ task.markedCount }}</span>
  32. </el-button>
  33. </el-button-group>
  34. </small>
  35. <small class="marktitle">
  36. <el-button
  37. class="course-tags"
  38. type="primary"
  39. @click="taskChange"
  40. size="small"
  41. >
  42. <span class="titlefont">
  43. 切换任务 <i class="el-icon-caret-bottom el-icon--right"></i>
  44. </span>
  45. </el-button>
  46. </small>
  47. <el-dialog title="切换任务" :visible.sync="taskVisible" width="80%">
  48. <div class="scroll">
  49. <el-form
  50. :inline="true"
  51. :model="taskFormSearch"
  52. label-position="right"
  53. label-width="70px"
  54. >
  55. <el-form-item label="课程代码" class="pull-left">
  56. <el-input
  57. placeholder="课程代码"
  58. v-model="taskFormSearch.courseCode"
  59. ></el-input>
  60. </el-form-item>
  61. <el-form-item label="课程名称" class="pull-left">
  62. <el-input
  63. placeholder="课程名称"
  64. v-model="taskFormSearch.courseName"
  65. ></el-input>
  66. </el-form-item>
  67. <el-form-item class="pull-right">
  68. <el-button
  69. type="primary"
  70. icon="search"
  71. @click="getChangeTasks"
  72. >查询</el-button
  73. >
  74. </el-form-item>
  75. </el-form>
  76. <el-table :data="changeTasks" border style="width: 100%">
  77. <el-table-column
  78. label="课程代码"
  79. width="250"
  80. prop="courseCode"
  81. />
  82. <el-table-column
  83. label="课程名称"
  84. width="200"
  85. prop="courseName"
  86. />
  87. <el-table-column
  88. label="任务"
  89. width="200"
  90. prop="markRangeName"
  91. />
  92. <el-table-column label="已评" prop="markedCount" />
  93. <el-table-column label="待评" prop="leftCount" />
  94. <el-table-column :context="_self" label="操作">
  95. <template slot-scope="scope">
  96. <div>
  97. <el-button
  98. size="small"
  99. type="success"
  100. @click="tasksSelect(scope.$index, scope.row)"
  101. >选择</el-button
  102. >
  103. </div>
  104. </template>
  105. </el-table-column>
  106. </el-table>
  107. <div class="page pull-right">
  108. <el-pagination
  109. background
  110. @current-change="taskCurrentChange"
  111. :current-page="taskCurrentPage"
  112. :page-size="pageSize"
  113. layout="total, prev, pager, next, jumper"
  114. :total="changeTaskTotal"
  115. ></el-pagination>
  116. </div>
  117. </div>
  118. </el-dialog>
  119. <el-dialog
  120. title="已评任务"
  121. :visible.sync="markedTaskVisible"
  122. width="80%"
  123. >
  124. <div class="scroll">
  125. <el-table :data="markedResults" border style="width: 100%;">
  126. <el-table-column
  127. label="答卷Id"
  128. width="100"
  129. prop="studentPaperId"
  130. />
  131. <el-table-column label="得分" prop="score" />
  132. <el-table-column label="评阅时间">
  133. <template slot-scope="scope">
  134. <div>
  135. <span style="margin-left: 10px">
  136. {{ dateFormatter(scope.row) }}
  137. </span>
  138. </div>
  139. </template>
  140. </el-table-column>
  141. <el-table-column label="状态">
  142. <div><span style="margin-left: 10px">已评</span></div>
  143. </el-table-column>
  144. <el-table-column label="问题卷">
  145. <template slot-scope="scope">
  146. <div>
  147. <span style="margin-left: 10px">
  148. {{ getTagName(scope.row.tag) }}
  149. </span>
  150. </div>
  151. </template>
  152. </el-table-column>
  153. <el-table-column label="评卷备注">
  154. <template slot-scope="scope">
  155. <div>
  156. <span style="margin-left: 10px">
  157. {{ scope.row.markRemark }}
  158. </span>
  159. </div>
  160. </template>
  161. </el-table-column>
  162. <el-table-column :context="_self" label="操作">
  163. <template slot-scope="scope">
  164. <div>
  165. <el-button
  166. size="small"
  167. type="success"
  168. @click="markTaskSelect(scope.$index, scope.row)"
  169. >选择</el-button
  170. >
  171. </div>
  172. </template>
  173. </el-table-column>
  174. </el-table>
  175. <div class="page pull-right">
  176. <el-pagination
  177. background
  178. @current-change="markedCurrentChange"
  179. :current-page="markedCurrentPage"
  180. :page-size="pageSize"
  181. layout="total, prev, pager, next, jumper"
  182. :total="markedTotal"
  183. ></el-pagination>
  184. </div>
  185. </div>
  186. </el-dialog>
  187. </span>
  188. <span class="pull-right icon-right">
  189. <small class="marktitle titlefont">
  190. <span class="titlefont">
  191. <v-icon name="user" style="height:12" />
  192. {{ user.displayName }}
  193. </span>
  194. </small>
  195. <small class="marktitle titlefont marksign">
  196. <el-button type="success" @click="backIndex" size="small">
  197. <!-- <v-icon name="sign-out-alt" scale="0.5"/> -->
  198. <span class="titlefont">退回</span>
  199. </el-button>
  200. </small>
  201. </span>
  202. </span>
  203. </section>
  204. <section class="content">
  205. <div class="box box-info backcolor">
  206. <div class="box-body">
  207. <!-- 文本图片阅卷主界面 -->
  208. <tpMain
  209. @changePaperSign="changePaperSign"
  210. @clearScores="clearScores"
  211. @changeSignScores="changeSignScores"
  212. :paperMarkSign="paperMarkSign"
  213. :signItem="signItem"
  214. :signScores="signScores"
  215. :signOption="signOption"
  216. :markSign="markSign"
  217. :studentPaper="studentPaper"
  218. :examType="examType"
  219. :answerHtml="answerHtml"
  220. ></tpMain>
  221. <!-- 文本图片给分板 -->
  222. <tpScoreboard
  223. @submitMark="getNext"
  224. @changeSign="changeSign"
  225. :paperMarkSign="paperMarkSign"
  226. :signItem="signItem"
  227. :signScores="signScores"
  228. :signOption="signOption"
  229. :markSign="markSign"
  230. :paperMark="paperMark"
  231. :markedResult="markedResult"
  232. :resultItems="resultItems"
  233. :studentPaperId="studentPaper.id"
  234. :markTaskId="task.id"
  235. ></tpScoreboard>
  236. </div>
  237. </div>
  238. </section>
  239. </div>
  240. </template>
  241. <script>
  242. import { mapState } from "vuex";
  243. import TpMain from "./TpMain.vue";
  244. import TpScoreBoard from "./TpScoreBoard.vue";
  245. import {
  246. MARKING_API,
  247. DATA_PROCESS_API,
  248. QUESTION_API
  249. } from "@/constants/constants";
  250. export default {
  251. components: {
  252. tpMain: TpMain,
  253. tpScoreboard: TpScoreBoard
  254. },
  255. data() {
  256. return {
  257. markSign: false,
  258. paperMarkSign: [],
  259. signScores: [],
  260. signItem: {},
  261. signOption: { score: 0, data: "", width: 800, height: 8000, loc: [] },
  262. tasks: [],
  263. task: {},
  264. changeTasks: [],
  265. changeTaskTotal: 0,
  266. studentPaper: {},
  267. markRange: {},
  268. resultItems: [],
  269. markedResults: [],
  270. markedResult: {},
  271. loading: true,
  272. taskCurrentPage: 1,
  273. taskTotal: 0,
  274. markedCurrentPage: 1,
  275. markedTotal: 0,
  276. pageSize: 10,
  277. mark_type: "正评",
  278. mark_task: {},
  279. taskVisible: false,
  280. markedTaskVisible: false,
  281. problemTaskVisible: false,
  282. degree: [{ label: "是", value: "Y" }, { label: "否", value: "N" }],
  283. markTaskFormSearch: {
  284. courseCode: "",
  285. courseName: "",
  286. degree: ""
  287. },
  288. taskFormSearch: {
  289. courseCode: "",
  290. courseName: "",
  291. paperCode: ""
  292. },
  293. course: {},
  294. workId: "",
  295. examType: "",
  296. markSearch: {
  297. userId: "",
  298. workId: ""
  299. },
  300. //回评标志
  301. backMark: false,
  302. //获取试卷标志(成功获取true,没有试卷false)
  303. paperMark: true,
  304. tags: [],
  305. answerHtml: null
  306. };
  307. },
  308. methods: {
  309. getTags() {
  310. this.$http.get(MARKING_API + "/markResults/tag").then(response => {
  311. this.tags = response.data;
  312. });
  313. },
  314. getTagName(code) {
  315. for (let tag of this.tags) {
  316. if (tag.code === code) {
  317. return tag.name;
  318. }
  319. }
  320. },
  321. clearScores() {
  322. this.signScores.splice(0, this.signScores.length);
  323. },
  324. changePaperSign(val) {
  325. this.paperMarkSign = val;
  326. },
  327. changeSignScores(val) {
  328. this.signScores = val;
  329. },
  330. changeSign(val) {
  331. console.log(val);
  332. this.signItem = val;
  333. },
  334. taskChange() {
  335. this.taskVisible = true;
  336. this.getChangeTasks();
  337. },
  338. async tasksSelect(index, row) {
  339. this.answerHtml = null;
  340. await this.initMarkItem();
  341. await this.markInit();
  342. this.task = row;
  343. await this.getPaper();
  344. await this.getAnswerHtml();
  345. await this.getMarkRange();
  346. await this.getMarkedTask();
  347. this.taskVisible = false;
  348. },
  349. markedClick() {
  350. this.markedTaskVisible = true;
  351. this.getMarkedTask();
  352. },
  353. problemClick() {
  354. this.problemTaskVisible = true;
  355. },
  356. backIndex() {
  357. this.$router.push({ path: "/marking/mark_setting_work/marking" });
  358. },
  359. taskCurrentChange(val) {
  360. this.taskCurrentPage = val;
  361. this.getChangeTasks();
  362. },
  363. markedCurrentChange(val) {
  364. this.markedCurrentPage = val;
  365. this.getMarkedTask();
  366. },
  367. async markTaskSelect(index, row) {
  368. this.backMark = true;
  369. this.paperMark = true;
  370. this.textarea = row.markRemark;
  371. await this.getMarkedPaper(row.studentPaperId);
  372. await this.getMarkedResultItems(row.id);
  373. await this.getAnswerHtml();
  374. this.markedTaskVisible = false;
  375. },
  376. async markInit() {
  377. console.log("markInit");
  378. var self = this;
  379. this.workId = this.$route.params.workId;
  380. this.examType = this.$route.params.examType;
  381. var userId = this.user.userId;
  382. await self.$http
  383. .get(
  384. DATA_PROCESS_API +
  385. "/markTasks?workId=" +
  386. self.workId +
  387. "&userId=" +
  388. userId
  389. )
  390. .then(response => {
  391. self.tasks = response.data;
  392. self.taskTotal = self.tasks.length;
  393. //切换任务提交试卷后,继续维持该任务
  394. if (self.changeTaskCur != self.taskCur) {
  395. //切换任务评完后,继续跳转原来的任务
  396. if (self.tasks[self.changeTaskCur].leftCount == 0) {
  397. if (self.tasks[self.taskCur]) {
  398. self.task = self.tasks[self.taskCur];
  399. }
  400. } else if (self.tasks[self.changeTaskCur]) {
  401. self.task = self.tasks[self.changeTaskCur];
  402. }
  403. } else {
  404. if (self.tasks[self.taskCur]) {
  405. self.task = self.tasks[self.taskCur];
  406. }
  407. }
  408. console.log("tasks", self.tasks);
  409. });
  410. },
  411. async getChangeTasks() {
  412. console.log("getChangeTasks");
  413. var self = this;
  414. this.workId = this.$route.params.workId;
  415. var userId = this.user.userId;
  416. await self.$http
  417. .get(
  418. DATA_PROCESS_API +
  419. "/markTasks?workId=" +
  420. self.workId +
  421. "&userId=" +
  422. userId
  423. )
  424. .then(response => {
  425. self.changeTasks = response.data;
  426. self.changeTaskTotal = self.changeTasks.length;
  427. self.filterChangeTasks();
  428. self.pagingChangeTasks();
  429. console.log("changeTasks", self.changeTasks);
  430. });
  431. },
  432. filterChangeTasks() {
  433. var tempData = this.changeTasks.filter(element => {
  434. var flag = true;
  435. if (this.taskFormSearch.courseCode || this.taskFormSearch.courseName) {
  436. if (this.taskFormSearch.courseCode) {
  437. flag =
  438. flag &&
  439. element.courseCode.includes(this.taskFormSearch.courseCode);
  440. }
  441. if (this.taskFormSearch.courseName) {
  442. flag =
  443. flag &&
  444. element.courseName.includes(this.taskFormSearch.courseName);
  445. }
  446. return flag;
  447. } else {
  448. return flag;
  449. }
  450. });
  451. this.changeTasks = tempData;
  452. this.changeTaskTotal = tempData.length;
  453. },
  454. pagingChangeTasks() {
  455. var start = (this.taskCurrentPage - 1) * this.pageSize;
  456. var end =
  457. this.taskCurrentPage * this.pageSize < this.changeTaskTotal
  458. ? this.taskCurrentPage * this.pageSize
  459. : this.changeTaskTotal;
  460. var tempData = [];
  461. console.log(`当前页: ${this.taskCurrentPage},开始:${start},结束:${end}`);
  462. for (let i = start; i < end; i++) {
  463. tempData.push(this.changeTasks[i]);
  464. }
  465. this.changeTasks = tempData;
  466. },
  467. async getPaper() {
  468. console.log("getPaper");
  469. var self = this;
  470. await self.$http
  471. .get(
  472. DATA_PROCESS_API +
  473. "/studentPapers?markTaskId=" +
  474. self.task.id +
  475. "&examType=" +
  476. self.examType
  477. )
  478. .then(response => {
  479. if (!response.data) {
  480. self.$notify({
  481. message: "该任务下试卷已评完,如有剩余任务将自动切换任务",
  482. type: "info"
  483. });
  484. self.studentPaper = { id: "" };
  485. self.paperMark = false;
  486. return false;
  487. } else {
  488. self.studentPaper = response.data;
  489. self.paperMark = true;
  490. console.log("paper", self.studentPaper);
  491. }
  492. });
  493. return true;
  494. },
  495. async getMarkedTask() {
  496. console.log("getMarkedTask");
  497. var self = this;
  498. await self.$http
  499. .get(
  500. MARKING_API +
  501. "/markResults/" +
  502. this.task.id +
  503. "/" +
  504. this.markedCurrentPage +
  505. "/" +
  506. this.pageSize
  507. )
  508. .then(response => {
  509. self.markedResults = response.data.data;
  510. self.markedTotal = response.data.pageInfo.totalElements;
  511. self.markedCurrentPage = response.data.pageInfo.page + 1;
  512. console.log("markedTask", self.markedResults);
  513. });
  514. },
  515. async getMarkedPaper(studentPaperId) {
  516. var self = this;
  517. await self.$http
  518. .get(
  519. DATA_PROCESS_API +
  520. "/studentPapers/" +
  521. studentPaperId +
  522. "/" +
  523. this.examType
  524. )
  525. .then(response => {
  526. self.studentPaper = response.data;
  527. });
  528. },
  529. async getMarkedResultItems(markResultId) {
  530. var self = this;
  531. await self.$http
  532. .get(MARKING_API + "/markResults/" + markResultId)
  533. .then(response => {
  534. self.resultItems = response.data.resultItems;
  535. self.markedResult = response.data;
  536. console.log(self.markedResult);
  537. });
  538. },
  539. async getMarkRange() {
  540. console.log("getMarkRange");
  541. if (!this.paperMark) {
  542. return;
  543. }
  544. var self = this;
  545. await self.$http
  546. .get(MARKING_API + "/markRanges/" + self.task.markRangeId)
  547. .then(response => {
  548. self.markRange = response.data;
  549. self.getResultItems(self.markRange);
  550. console.log("markRange", self.markRange);
  551. console.log("resultItems", self.resultItems);
  552. });
  553. },
  554. getResultItems(markRange) {
  555. for (let markItem of markRange.markItems) {
  556. var resultItem = { markItem: markItem, score: "" };
  557. this.resultItems.push(resultItem);
  558. }
  559. },
  560. async getNext() {
  561. this.answerHtml = null;
  562. //试卷全部评完且回评时不继续获取试卷
  563. if (this.backMark && this.allMarked) {
  564. return;
  565. }
  566. this.initMarkItem();
  567. await this.markInit();
  568. await this.getPaper();
  569. await this.getAnswerHtml();
  570. await this.getChangeTasks();
  571. await this.getMarkRange();
  572. await this.getMarkedTask();
  573. this.backMark = false;
  574. },
  575. dateFormatter(row) {
  576. var fulldate = new Date(row.markedOn);
  577. var year = fulldate.getFullYear();
  578. var month = fulldate.getMonth() + 1;
  579. var date = fulldate.getDate();
  580. var formatDate = [year, month, date].join("-");
  581. return formatDate;
  582. },
  583. initMarkItem() {
  584. this.resultItems.splice(0, this.resultItems.length);
  585. this.markResult = {};
  586. this.markedResult = {};
  587. },
  588. markSignChange() {
  589. if (this.markSign) {
  590. this.$message({
  591. showClose: true,
  592. message: "轨迹模式已开启,只支持鼠标操作",
  593. type: "warning"
  594. });
  595. }
  596. },
  597. async getAnswerHtml() {
  598. if (this.studentPaper.basePaperId) {
  599. var paperId = this.studentPaper.basePaperId;
  600. await this.$http
  601. .get(QUESTION_API + "/extract/getAnswerHtml/" + paperId)
  602. .then(response => {
  603. this.answerHtml = response.data;
  604. });
  605. }
  606. }
  607. },
  608. computed: {
  609. allMarked() {
  610. if (this.tasks.length == 0) {
  611. return false;
  612. } else {
  613. for (let task of this.tasks) {
  614. if (task.leftCount > 0) {
  615. return false;
  616. }
  617. }
  618. return true;
  619. }
  620. },
  621. taskCur() {
  622. //任务及时动态切换
  623. if (this.tasks.length == 0) {
  624. return 0;
  625. } else {
  626. for (let [index, task] of this.tasks.entries()) {
  627. if (task.leftCount > 0) {
  628. return index;
  629. }
  630. }
  631. return 0;
  632. }
  633. },
  634. changeTaskCur() {
  635. for (let [index, task] of this.tasks.entries()) {
  636. if (task.id == this.task.id) {
  637. return index;
  638. }
  639. }
  640. return this.taskCur;
  641. },
  642. ...mapState({ user: state => state.user })
  643. },
  644. async created() {
  645. this.loading = true;
  646. await this.markInit();
  647. await this.getChangeTasks();
  648. await this.getPaper();
  649. await this.getAnswerHtml();
  650. await this.getMarkRange();
  651. await this.getMarkedTask();
  652. this.getTags();
  653. this.loading = false;
  654. }
  655. };
  656. </script>
  657. <style scoped>
  658. .el-select {
  659. width: 160px;
  660. }
  661. .content {
  662. min-height: 600px;
  663. margin-right: auto;
  664. margin-left: auto;
  665. padding-left: 15px;
  666. }
  667. small {
  668. font-size: 18px;
  669. font-weight: bold;
  670. margin-left: 10px;
  671. margin-top: 20px;
  672. }
  673. .content-header {
  674. margin-top: 10px;
  675. margin-left: 15px;
  676. overflow: hidden;
  677. background-color: rgb(77, 124, 196);
  678. height: 55px;
  679. }
  680. .box-body {
  681. height: 100%;
  682. border-top-left-radius: 0;
  683. border-top-right-radius: 0;
  684. border-bottom-right-radius: 3px;
  685. border-bottom-left-radius: 3px;
  686. padding-left: 40px;
  687. padding-right: 15px;
  688. overflow: hidden;
  689. }
  690. li {
  691. list-style-type: none;
  692. }
  693. .marktitle {
  694. margin-right: 20px;
  695. margin-bottom: 10px;
  696. font-size: 18px;
  697. font-weight: 700;
  698. color: white;
  699. }
  700. .titlefont {
  701. font-size: 12px;
  702. display: inline-block;
  703. }
  704. .box-card {
  705. width: 200px;
  706. height: 120px;
  707. }
  708. .block {
  709. display: inline-block;
  710. }
  711. .text {
  712. text-align: center;
  713. }
  714. .markcount {
  715. margin-right: 10px;
  716. }
  717. .reject {
  718. color: red;
  719. }
  720. .marksign {
  721. margin-left: 20px;
  722. }
  723. .label-danger {
  724. background-color: #d9534f;
  725. color: #fff;
  726. padding: 2px;
  727. }
  728. .box {
  729. position: relative;
  730. border-radius: 3px;
  731. margin-bottom: 20px;
  732. width: 100%;
  733. }
  734. .pull-right {
  735. float: right !important;
  736. }
  737. .pull-left {
  738. float: left !important;
  739. }
  740. .scroll {
  741. overflow: auto;
  742. height: 450px;
  743. }
  744. .el-button {
  745. background: rgb(77, 124, 196);
  746. color: white;
  747. border-radius: 8px;
  748. border-color: white;
  749. }
  750. .course-tags {
  751. background: rgb(84, 191, 255);
  752. }
  753. .icon-right {
  754. margin-top: -6px;
  755. }
  756. </style>