LeaderGrading.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <template>
  2. <div class="marker-grading">
  3. <marker-header
  4. v-if="curSubject.id"
  5. show-select-all
  6. @area-change="areaChange"
  7. @step-change="stepChange"
  8. @page-set-change="pageSetChange"
  9. @to-progress="toProgress"
  10. @to-select-all="toSelectAll"
  11. @to-history="toHistory"
  12. @to-standard="toStandard"
  13. @to-statistics="toStatistics"
  14. @on-code-search="serachPaperByCode"
  15. @on-mark-search="serachPaperByCode"
  16. ></marker-header>
  17. <div
  18. :class="[
  19. 'marker-action',
  20. 'dark-mark',
  21. { 'marker-action-fullscreen': isFullscreenMarking }
  22. ]"
  23. v-show="!multipleGradingList.length"
  24. >
  25. <grade-action
  26. :cur-paper-or-task="curPaper"
  27. :levels="levels"
  28. :params-set="paramsSet"
  29. :key="curPaper.key"
  30. @on-leader-level="leaderSelectLevel"
  31. ref="GradeAction"
  32. v-if="curPaper.id"
  33. ></grade-action>
  34. </div>
  35. <!-- multiple grading action -->
  36. <div class="marker-action" v-show="multipleGradingList.length">
  37. <div class="grade-action">
  38. <div class="action-paper-state">
  39. <p class="paper-state-cont">批量操作</p>
  40. </div>
  41. <div class="action-paper-info">
  42. <p><span>试卷密号:</span><span>--</span></p>
  43. </div>
  44. <h3 class="action-grade-info-title" v-if="markLeaderOnlyRight">
  45. 当前操作:{{ markLeaderOnlyRight.name }}
  46. </h3>
  47. <div class="action-grade-list">
  48. <div
  49. class="action-grade-item"
  50. v-for="(level, index) in levels"
  51. :key="index"
  52. >
  53. <div
  54. :class="[
  55. 'action-grade-item-content',
  56. { 'action-item-content-disabled': multiplebtnClicked }
  57. ]"
  58. @click="multipleSelectLevel(level)"
  59. >
  60. <p>{{ level.name }}</p>
  61. <p>{{ level.minScore }}~{{ level.maxScore }}</p>
  62. </div>
  63. </div>
  64. </div>
  65. </div>
  66. </div>
  67. <div class="marker-body">
  68. <div :class="markerImageListClasses" v-if="papers.length">
  69. <div
  70. v-for="(paper, index) in papers"
  71. :key="paper.key"
  72. :class="[
  73. 'marker-image-item',
  74. {
  75. 'marker-image-item-act': curPaperIndex === index
  76. }
  77. ]"
  78. >
  79. <div class="marker-image-content">
  80. <marker-image-view
  81. ref="MarkerImageView"
  82. :data="paper"
  83. :can-select="ACTION_CAN_BATCH"
  84. @to-review="toReview(index)"
  85. @to-select="selectMultiplePaper"
  86. ></marker-image-view>
  87. </div>
  88. </div>
  89. </div>
  90. <div v-else class="marker-image-none">暂无数据</div>
  91. </div>
  92. <!-- LeaderStatistics -->
  93. <leader-statistics
  94. :question-id="filter.questionId"
  95. ref="LeaderStatistics"
  96. ></leader-statistics>
  97. <!-- LeaderProgress -->
  98. <leader-progress ref="LeaderProgress"></leader-progress>
  99. <!-- MarkerHistory -->
  100. <marker-history
  101. :question-id="filter.questionId"
  102. @on-paper-click="
  103. (index, papers) => {
  104. toViewCarouselPaper(index, papers, 'history');
  105. }
  106. "
  107. ref="MarkerHistory"
  108. ></marker-history>
  109. <!-- MarkerStandard -->
  110. <marker-standard
  111. :question-id="filter.questionId"
  112. :levels="levels"
  113. @on-paper-click="
  114. (index, papers) => {
  115. toViewCarouselPaper(index, papers, 'sample');
  116. }
  117. "
  118. ref="MarkerStandard"
  119. v-if="levels.length && filter.questionId"
  120. ></marker-standard>
  121. <!-- modify-leader-grading -->
  122. <modify-leader-grading
  123. class="marker-modal"
  124. :level-info="levelInfo"
  125. :markers="markers"
  126. @modified="leaderGradingSuccess"
  127. ref="ModifyLeaderGrading"
  128. ></modify-leader-grading>
  129. <!-- image-preview -->
  130. <simple-image-preview
  131. class="grading-operation-image-preview"
  132. :cur-image="curPaper"
  133. @on-prev="toPrevPaper"
  134. @on-next="toNextPaper"
  135. @on-close="isFullscreenMarking = false"
  136. ref="SimpleImagePreview"
  137. ></simple-image-preview>
  138. <!-- carousel paper review -->
  139. <simple-image-preview
  140. class="grading-operation-image-preview"
  141. :cur-image="curPaper"
  142. @on-prev="toCarousePaper('prev')"
  143. @on-next="toCarousePaper('next')"
  144. @on-close="carouseImagePreviewClose"
  145. ref="CarouselPapersPreview"
  146. ></simple-image-preview>
  147. </div>
  148. </template>
  149. <script>
  150. import { mapState, mapMutations } from "vuex";
  151. import MarkerHeader from "../marker/MarkerHeader";
  152. import MarkerImageView from "../marker/MarkerImageView";
  153. import MarkerHistory from "../marker/MarkerHistory";
  154. import MarkerStandard from "../marker/MarkerStandard";
  155. import LeaderProgress from "./LeaderProgress";
  156. import LeaderStatistics from "./LeaderStatistics";
  157. import GradeAction from "../components/GradeAction";
  158. import SimpleImagePreview from "@/components/SimpleImagePreview";
  159. import ModifyLeaderGrading from "../components/ModifyLeaderGrading";
  160. import {
  161. paperList,
  162. markLeaderLevelStatData,
  163. workLevelList,
  164. taskSnSearch,
  165. subjectDetail,
  166. markHistoryList,
  167. getParamsSet,
  168. leaderGradingPaper
  169. } from "@/api";
  170. export default {
  171. name: "marker-grading",
  172. components: {
  173. MarkerHeader,
  174. MarkerImageView,
  175. MarkerHistory,
  176. MarkerStandard,
  177. LeaderProgress,
  178. LeaderStatistics,
  179. GradeAction,
  180. SimpleImagePreview,
  181. ModifyLeaderGrading
  182. },
  183. data() {
  184. return {
  185. filter: {
  186. questionId: "",
  187. sort: "secretNumber"
  188. },
  189. typeFilter: {
  190. done: {
  191. level: ""
  192. },
  193. reject: {
  194. reject: true
  195. },
  196. arbitrate: {
  197. arbi: true
  198. }
  199. },
  200. workId: this.$route.params.workId,
  201. subjectId: this.$route.params.subjectId,
  202. levels: [],
  203. papers: [],
  204. curPaper: {},
  205. curPaperIndex: 0,
  206. // leader-grade
  207. levelInfo: {},
  208. markers: [],
  209. // carousel paper review,
  210. carouselType: "",
  211. carouselPapers: [],
  212. curCarouselPaperIndex: 0,
  213. isFullscreenMarking: false,
  214. // multiple grading
  215. multiplebtnClicked: false,
  216. multipleGradingList: [],
  217. // 科组长权限
  218. markLeaderOnlyRight: null
  219. };
  220. },
  221. computed: {
  222. ...mapState("marker", [
  223. "paramsSet",
  224. "page",
  225. "steps",
  226. "curStep",
  227. "curArea",
  228. "curSubject"
  229. ]),
  230. markerImageListClasses() {
  231. return ["marker-image-list", `marker-image-list-${this.page.size}`];
  232. },
  233. IS_TEST() {
  234. return this.curSubject.test === 2;
  235. },
  236. ACTION_CAN_BATCH() {
  237. return this.curStep.type === "done" && !this.paramsSet.paperStage;
  238. }
  239. },
  240. created() {
  241. this.markLeaderOnlyRight = this.$ls.get("user", {
  242. markLeaderOnlyRight: null
  243. }).markLeaderOnlyRight;
  244. const curUserRoleType = this.$ls.get("user", { role: "" }).role;
  245. this.setCurUserRoleType(curUserRoleType);
  246. this.initData();
  247. },
  248. methods: {
  249. ...mapMutations("marker", [
  250. "setParamSet",
  251. "setPage",
  252. "setSteps",
  253. "setCurStep",
  254. "setCurArea",
  255. "setCurSubject",
  256. "setCurUserRoleType",
  257. "clearState"
  258. ]),
  259. initData() {
  260. this.getParamsSetInfo();
  261. this.getSubjectDetail();
  262. this.getWorkLevels();
  263. },
  264. async getParamsSetInfo() {
  265. const data = await getParamsSet(this.workId);
  266. this.setParamSet(data || {});
  267. },
  268. async getSubjectDetail() {
  269. const curSubject = await subjectDetail(this.subjectId);
  270. this.setCurSubject(curSubject || {});
  271. },
  272. async getList() {
  273. this.multipleGradingList = [];
  274. const datas = {
  275. ...this.filter,
  276. ...this.typeFilter[this.curStep.type],
  277. page: this.page.current - 1,
  278. size: this.page.size
  279. };
  280. if (this.curStep.type === "done") datas.level = this.curStep.name;
  281. const data = await paperList(datas);
  282. this.papers = data.data.map(paper => {
  283. paper.key = this.$randomCode();
  284. paper.title = `NO.${paper.sn}`;
  285. paper.selected = false;
  286. return paper;
  287. });
  288. this.setPage({
  289. total: data.totalCount,
  290. totalPage: data.pageCount
  291. });
  292. },
  293. async toPage(page) {
  294. this.setPage({
  295. current: page
  296. });
  297. await this.getList();
  298. this.selectPaper(this.curPaperIndex);
  299. },
  300. async getStepLevels() {
  301. const data = await markLeaderLevelStatData(
  302. this.subjectId,
  303. this.filter.questionId
  304. );
  305. const undoIndex = data.findIndex(item => item.id === null);
  306. let otherStep = [];
  307. let undo = {
  308. count: 0,
  309. rejected: 0,
  310. arbitrated: 0
  311. };
  312. if (undoIndex !== -1) {
  313. undo = { ...data[undoIndex] };
  314. data.splice(undoIndex, 1);
  315. }
  316. if (this.IS_TEST) {
  317. otherStep.push({
  318. name: "待评",
  319. count: undo.count,
  320. type: "undo"
  321. });
  322. }
  323. otherStep.push({
  324. name: "打回",
  325. count: undo.rejected,
  326. type: "reject"
  327. });
  328. otherStep.push({
  329. name: "仲裁",
  330. count: undo.arbitrated,
  331. type: "arbitrate"
  332. });
  333. let levelStep = data.map(item => {
  334. return {
  335. ...item,
  336. name: item.id,
  337. type: "done"
  338. };
  339. });
  340. this.setSteps({ levelStep, otherStep });
  341. if (!this.curStep.name) {
  342. const firstStep = otherStep.find(item => item.count);
  343. const curStep = firstStep || levelStep[0];
  344. this.setCurStep(curStep);
  345. } else {
  346. const curStep = [...levelStep, ...otherStep].find(
  347. item => item.name === this.curStep.name
  348. );
  349. this.setCurStep(curStep);
  350. }
  351. },
  352. async getWorkLevels() {
  353. const data = await workLevelList(this.workId);
  354. this.levels = data.map(item => {
  355. return {
  356. id: item.id,
  357. name: item.code,
  358. minScore: item.minScore,
  359. maxScore: item.maxScore
  360. };
  361. });
  362. },
  363. async pageSetChange() {
  364. await this.getList();
  365. this.selectPaper(this.curPaperIndex);
  366. },
  367. async stepChange(step) {
  368. this.setCurStep(step);
  369. this.setPage({ current: 1 });
  370. this.isFullscreenMarking = false;
  371. await this.getList();
  372. // this.getStepLevels();
  373. if (this.papers.length) {
  374. this.selectPaper(0);
  375. } else {
  376. this.curPaper = {};
  377. }
  378. },
  379. async areaChange(curArea) {
  380. this.setCurArea(curArea);
  381. this.filter.questionId = curArea.id;
  382. await this.getStepLevels();
  383. this.toPage(1);
  384. },
  385. // selectMultiplePaper
  386. selectMultiplePaper(paper) {
  387. if (paper.sample) return;
  388. const curPaper = this.papers.find(p => p.id === paper.id);
  389. curPaper.selected = paper.selected;
  390. this.multipleGradingList = this.papers.filter(paper => paper.selected);
  391. },
  392. async multipleSelectLevel(level) {
  393. if (!this.multipleGradingList.length) return;
  394. if (this.multiplebtnClicked) return;
  395. this.multiplebtnClicked = true;
  396. const data = await markHistoryList(
  397. this.multipleGradingList[0].id,
  398. "LEVEL"
  399. ).catch(() => {
  400. this.multiplebtnClicked = false;
  401. });
  402. if (!data) return;
  403. const markers = data.map(item => {
  404. return {
  405. id: item.markerId,
  406. name: item.marker
  407. };
  408. });
  409. const levelInfo = {
  410. paperIds: this.multipleGradingList.map(item => item.id).join(),
  411. curLevel: this.curStep.name,
  412. selectedLevel: level.name,
  413. markLeaderOnlyRight: this.markLeaderOnlyRight
  414. };
  415. await this.leaderSelectLevel(levelInfo, markers).catch(() => {});
  416. this.multiplebtnClicked = false;
  417. },
  418. // paper view action
  419. toReview(index) {
  420. this.isFullscreenMarking = true;
  421. this.multipleGradingList = [];
  422. this.selectPaper(index);
  423. this.$refs.SimpleImagePreview.open();
  424. },
  425. selectPaper(index) {
  426. let nindex = index;
  427. if (!this.papers.length) {
  428. nindex = 0;
  429. } else if (index > this.papers.length - 1) {
  430. nindex = this.papers.length - 1;
  431. } else if (index < 0) {
  432. nindex = 0;
  433. }
  434. this.curPaperIndex = nindex;
  435. this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
  436. },
  437. async toPrevPaper() {
  438. if (this.curPaperIndex === 0) {
  439. if (this.page.current > 1) {
  440. this.setPage({ current: this.page.current - 1 });
  441. this.curPaperIndex = this.page.size - 1;
  442. await this.getList();
  443. } else {
  444. this.$Message.warning("当前已经是第一条数据了");
  445. return;
  446. }
  447. } else {
  448. this.curPaperIndex--;
  449. }
  450. this.selectPaper(this.curPaperIndex);
  451. },
  452. async toNextPaper() {
  453. if (this.curPaperIndex === this.papers.length - 1) {
  454. if (this.page.current === this.page.totalPage) {
  455. this.$Message.warning("当前已经是最后一条数据了");
  456. return;
  457. } else {
  458. this.setPage({ current: this.page.current + 1 });
  459. this.curPaperIndex = 0;
  460. await this.getList();
  461. }
  462. } else {
  463. this.curPaperIndex++;
  464. }
  465. this.selectPaper(this.curPaperIndex);
  466. },
  467. async toActionNextPaper() {
  468. if (this.page.current > 1 && this.papers.length === 1) {
  469. this.setPage({ current: this.page.current - 1 });
  470. this.curPaperIndex = this.page.size;
  471. }
  472. await this.getList();
  473. if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
  474. this.selectPaper(this.curPaperIndex);
  475. },
  476. async serachPaperByCode(params) {
  477. const data = await taskSnSearch(
  478. params.codeType,
  479. params.code,
  480. this.filter.questionId
  481. );
  482. if (!data) {
  483. this.$Message.error("没有查找到结果!");
  484. return;
  485. }
  486. data.title = `NO.${data.sn}`;
  487. this.papers = [data];
  488. this.setPage({ current: 1, total: 1, totalPage: 1 });
  489. this.selectPaper(0);
  490. },
  491. async serachMarkPaper(params) {
  492. console.log(params);
  493. // TODO:
  494. },
  495. async leaderSelectLevel(levelInfo, markers) {
  496. // 唯一权限时,直接操作
  497. if (levelInfo.markLeaderOnlyRight && !this.paramsSet.leaderConfirm) {
  498. const datas = {
  499. action: levelInfo.markLeaderOnlyRight.action,
  500. level: levelInfo.selectedLevel,
  501. originLevel: levelInfo.curLevel,
  502. paperIds: levelInfo.paperIds
  503. };
  504. if (datas.action === "reject") {
  505. datas.range = markers.map(item => item.id).join();
  506. }
  507. let result = true;
  508. const paper = await leaderGradingPaper(datas).catch(() => {
  509. result = false;
  510. });
  511. if (!result) return;
  512. this.leaderGradingSuccess(datas, paper);
  513. return;
  514. }
  515. this.levelInfo = levelInfo;
  516. this.markers = markers;
  517. this.$refs.ModifyLeaderGrading.open();
  518. },
  519. async leaderGradingSuccess(datas, paper) {
  520. this.getStepLevels();
  521. if (this.multipleGradingList && this.multipleGradingList.length) {
  522. // 批量处理逻辑
  523. if (
  524. this.page.current > 1 &&
  525. this.page.current === this.page.totalPage &&
  526. this.papers.length === this.multipleGradingList.length
  527. ) {
  528. this.setPage({ current: this.page.current - 1 });
  529. }
  530. this.multipleGradingList = [];
  531. await this.getList();
  532. this.selectPaper(this.curPaperIndex);
  533. } else {
  534. // 单张处理逻辑
  535. this.toActionNextPaper();
  536. }
  537. },
  538. // paper carousel
  539. toViewCarouselPaper(paperIndex, papers, type) {
  540. this.carouselType = type;
  541. this.isFullscreenMarking = true;
  542. this.carouselPapers = papers;
  543. this.selectCarouselPaper(paperIndex);
  544. this.$nextTick(() => {
  545. this.$refs.CarouselPapersPreview.open();
  546. });
  547. },
  548. selectCarouselPaper(index) {
  549. this.curCarouselPaperIndex = index;
  550. this.curPaper = { ...this.carouselPapers[index] };
  551. },
  552. toCarousePaper(type) {
  553. if (type === "prev" && this.curCarouselPaperIndex > 0) {
  554. this.curCarouselPaperIndex--;
  555. } else if (
  556. type === "next" &&
  557. this.curCarouselPaperIndex < this.carouselPapers.length - 1
  558. ) {
  559. this.curCarouselPaperIndex++;
  560. }
  561. this.selectCarouselPaper(this.curCarouselPaperIndex);
  562. },
  563. carouseImagePreviewClose() {
  564. this.isFullscreenMarking = false;
  565. this.carouselType = "";
  566. this.selectPaper(this.curPaperIndex);
  567. },
  568. // header
  569. toHistory() {
  570. this.$refs.MarkerHistory.open();
  571. },
  572. toStandard() {
  573. this.$refs.MarkerStandard.open();
  574. },
  575. toProgress() {
  576. this.$refs.LeaderProgress.open();
  577. },
  578. toSelectAll(allSelected) {
  579. this.$refs.MarkerImageView.forEach(item => {
  580. item.changeSelect(allSelected);
  581. });
  582. },
  583. toStatistics() {
  584. this.$refs.LeaderStatistics.open();
  585. }
  586. },
  587. beforeDestroy() {
  588. this.clearState();
  589. }
  590. };
  591. </script>