MarkAction.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <template>
  2. <div class="mark-action grade-action">
  3. <!-- 查询 -->
  4. <div class="action-search" v-if="rights.search">
  5. <Select
  6. class="search-select"
  7. v-model="filter.codeType"
  8. placeholder="密号类型"
  9. >
  10. <Option
  11. v-for="item in codeTypes"
  12. :key="item.key"
  13. :value="item.key"
  14. :label="item.val"
  15. ></Option>
  16. </Select>
  17. <Input
  18. class="search-input"
  19. v-model.trim="filter.code"
  20. placeholder="输入密号"
  21. >
  22. </Input>
  23. <Button size="small" type="primary" class="search-btn" @click="searchCode"
  24. >查询</Button
  25. >
  26. </div>
  27. <!-- 改档处理状态查询 -->
  28. <div class="action-grade-change-search" v-if="rights.gradeChangeSearch">
  29. <Select
  30. v-model="applyChangeLevelStatus"
  31. placeholder="类型"
  32. style="width: 100px"
  33. >
  34. <Option
  35. v-for="(val, key) in CHANGE_LEVEL_STATUS"
  36. :key="key"
  37. :value="key * 1"
  38. :label="val"
  39. ></Option>
  40. </Select>
  41. <Button
  42. size="small"
  43. type="primary"
  44. class="search-btn"
  45. @click="searchGradeChange"
  46. >查询</Button
  47. >
  48. </div>
  49. <!-- 头部信息 ------ -->
  50. <!-- 试卷状态 -->
  51. <!-- 状态:已评,待评,改档,改档打分 -->
  52. <div class="action-paper-state">
  53. <p class="paper-state-cont">{{ stepLabel }}</p>
  54. </div>
  55. <!-- 试卷信息 -->
  56. <div class="action-paper-info">
  57. <p v-if="IS_ADMIN">
  58. <span>试卷考号:</span><span>{{ curPaperOrTask.examNumber }}</span>
  59. </p>
  60. <p>
  61. <span v-if="IS_MARKER">任务密号:</span>
  62. <span v-else>试卷密号:</span>
  63. <span>NO.{{ curPaperOrTask.sn }}</span>
  64. </p>
  65. </div>
  66. <!-- 改档信息 -->
  67. <div class="action-grade-change" v-if="rights.gradeChange">
  68. <p>
  69. <span>原始档位:</span><span>{{ curPaperOrTask.originLevel }}</span>
  70. </p>
  71. <p>
  72. <span v-if="IS_MARKER">建议档位:</span>
  73. <span v-else>申请档位:</span>
  74. <span>{{ curPaperOrTask.redoLevel }}</span>
  75. </p>
  76. </div>
  77. <div
  78. :class="[
  79. 'action-grade-change-status',
  80. { 'action-grade-change-status-error': curPaperOrTask.auditStatus === 0 }
  81. ]"
  82. v-if="rights.gradeChange && IS_ADMIN"
  83. >
  84. <p>{{ curPaperOrTask.auditStatus === 1 ? "同意改档" : "不同意改档" }}</p>
  85. </div>
  86. <!-- 档位信息 -->
  87. <!-- 已评/待评(已评档位),改档打分(已评档位) -->
  88. <div class="action-grade-info" v-if="rights.gradeInfo">
  89. <h3 class="grade-info-name">
  90. {{ curPaperLevel }}
  91. </h3>
  92. <!-- <div class="grade-info-range">
  93. <p>分数范围</p>
  94. <p>
  95. <span>{{ curLevel.minScore }}</span>
  96. <span>~</span>
  97. <span>{{ curLevel.maxScore }}</span>
  98. </p>
  99. </div> -->
  100. </div>
  101. <!-- 打分信息 -->
  102. <div class="action-grade-info action-mark-info" v-if="rights.markInfo">
  103. <p class="grade-info-name" v-if="curPaperScore">
  104. {{ curPaperScore }}
  105. </p>
  106. <p class="grade-info-name grade-info-none" v-else>未打分</p>
  107. </div>
  108. <!-- 选择档位 -->
  109. <div class="action-grade-list" v-if="rights.gradeList">
  110. <div
  111. class="action-grade-item"
  112. v-for="(level, index) in levels"
  113. :key="index"
  114. >
  115. <div
  116. :class="[
  117. 'action-grade-item-content',
  118. { 'action-item-content-disabled': btnClicked }
  119. ]"
  120. @click="selectLevel(level)"
  121. >
  122. <p>{{ level.name }}</p>
  123. <p>{{ level.minScore }}~{{ level.maxScore }}</p>
  124. </div>
  125. </div>
  126. </div>
  127. <!-- 选择分数 -->
  128. <div class="action-mark-list" v-if="rights.levelList">
  129. <div
  130. class="action-mark-item"
  131. v-for="(score, index) in scores"
  132. :key="index"
  133. >
  134. <div
  135. :class="[
  136. 'action-mark-item-content',
  137. { 'action-item-content-disabled': btnClicked }
  138. ]"
  139. @click="selectScore(score)"
  140. >
  141. <p>{{ score }}</p>
  142. </div>
  143. </div>
  144. </div>
  145. <div class="action-grade-pass" v-if="rights.levelList">
  146. <Button @click="toPass">跳过</Button>
  147. </div>
  148. <!-- mark confirm grade change -->
  149. <div
  150. class="action-grade-change-confirm"
  151. v-if="IS_MARKER && stepType === 'shift'"
  152. >
  153. <Button type="primary" @click="gradeChangeConfirm">确认改档</Button>
  154. </div>
  155. <!-- 评卷记录 -->
  156. <div class="action-grade-history" v-if="rights.markHis">
  157. <h3>评卷记录</h3>
  158. <div class="grade-history-list">
  159. <div
  160. class="grade-history-item"
  161. v-for="(his, hindex) in gradingHistory"
  162. :key="hindex"
  163. >
  164. <p>{{ his.name }}</p>
  165. <p>{{ his.value }}</p>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </template>
  171. <script>
  172. import { markHistoryList } from "@/api";
  173. import { CODE_TYPE, CHANGE_LEVEL_STATUS } from "@/constants/enumerate";
  174. // 三种情况:
  175. // 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
  176. // 管理员:查询,头部信息,评卷记录
  177. // 科组长:查询,头部信息,选择档位,评卷记录
  178. // 评卷员:头部信息,选择分数
  179. /*
  180. [paper template]
  181. {
  182. "id": 42,
  183. "sn": "5314987744",
  184. "redoLevel": null,
  185. "level": "B",
  186. "score": null,
  187. "result": "88",
  188. "originLevel": null,
  189. "markerId": 52,
  190. "marker": "zj-pj-01",
  191. "updatedOn": 1595812145000,
  192. "imgSrc": "http://192.168.10.145:9000/images/34/SC/1/1901130046.jpg?random=f5549bb0-ba58-4cd3-a88e-0559be4e06e5",
  193. "thumbSrc": "http://192.168.10.145:9000/thumbs/34/SC/1/1901130046.jpg?random=e7f880b8-4cb6-4963-8e66-532f0f8bdeb0",
  194. "markByLeader": false,
  195. "oldRejected": false,
  196. "paperId": 116,
  197. "randomSeqNew": 4987744,
  198. "randomSeq": null,
  199. "serialNumber": "B1",
  200. "displayNumber": true,
  201. "shift": false,
  202. "shiftScore": false,
  203. "rejected": false,
  204. "sample": false
  205. }
  206. [marktask template]
  207. {
  208. "id": 38,
  209. "sn": "5314266469",
  210. "redoLevel": null,
  211. "level": "A",
  212. "score": null,
  213. "result": "96",
  214. "originLevel": null,
  215. "markerId": 52,
  216. "marker": "zj-pj-01",
  217. "updatedOn": 1595812012000,
  218. "imgSrc": "http://192.168.10.145:9000/images/34/SC/1/1901130043.jpg?random=bffc061c-7a80-42a4-ad56-36ec6eba0d45",
  219. "thumbSrc": "http://192.168.10.145:9000/thumbs/34/SC/1/1901130043.jpg?random=da743f9d-8d46-4499-bb6f-b9c26e003ba2",
  220. "markByLeader": true,
  221. "oldRejected": false,
  222. "paperId": 113,
  223. "randomSeqNew": 4266469,
  224. "randomSeq": null,
  225. "serialNumber": "A1",
  226. "displayNumber": true,
  227. "shift": false,
  228. "shiftScore": false,
  229. "rejected": false,
  230. "sample": true
  231. }
  232. */
  233. const initRights = {
  234. search: false,
  235. gradeChangeSearch: false,
  236. gradeChange: false,
  237. gradeInfo: false,
  238. markInfo: false,
  239. gradeList: false,
  240. levelList: false,
  241. markHis: false
  242. };
  243. export default {
  244. name: "mark-action",
  245. props: {
  246. curPaperOrTask: {
  247. type: Object,
  248. default() {
  249. return {};
  250. }
  251. },
  252. levels: {
  253. type: Array,
  254. default() {
  255. return [];
  256. }
  257. },
  258. userRole: {
  259. type: String,
  260. default: "MARKER"
  261. }
  262. },
  263. data() {
  264. return {
  265. rights: {
  266. ...initRights
  267. },
  268. roleRight: {
  269. ADMIN: {
  270. done: ["search", "markHis", "gradeInfo", "markInfo"],
  271. shift: ["search", "gradeChangeSearch", "gradeChange"]
  272. },
  273. MARK_LEADER: {
  274. undo: ["search", "gradeList", "gradeInfo", "markInfo"],
  275. done: ["search", "gradeList", "markHis", "gradeInfo", "markInfo"],
  276. shift: ["search", "gradeList", "gradeChange"]
  277. },
  278. MARKER: {
  279. done: ["levelList", "gradeInfo", "markInfo"],
  280. undo: ["levelList", "gradeInfo"],
  281. shift: ["gradeChange"],
  282. shiftScore: ["levelList", "gradeInfo"]
  283. }
  284. },
  285. filter: {
  286. codeType: "examNumber",
  287. code: ""
  288. },
  289. codeTypes: [],
  290. CHANGE_LEVEL_STATUS,
  291. applyChangeLevelStatus: null,
  292. stepDict: {
  293. undo: "待评",
  294. done: "已评",
  295. shift: "改档",
  296. shiftScore: "改档打分"
  297. },
  298. stepType: "",
  299. stepLabel: "",
  300. curPaperLevel: "",
  301. curPaperScore: "",
  302. scores: [],
  303. gradingHistory: [],
  304. curLevel: {},
  305. setT: null,
  306. btnClicked: false
  307. };
  308. },
  309. computed: {
  310. IS_ADMIN() {
  311. return this.userRole === "ADMIN";
  312. },
  313. IS_MARKER() {
  314. return this.userRole === "MARKER";
  315. },
  316. IS_MARK_LEADER() {
  317. return this.userRole === "MARK_LEADER";
  318. }
  319. },
  320. watch: {
  321. curPaperOrTask(val) {
  322. this.rebuildRight();
  323. }
  324. },
  325. mounted() {
  326. this.codeTypes = Object.entries(CODE_TYPE)
  327. .map(([key, val]) => {
  328. return {
  329. key,
  330. val
  331. };
  332. })
  333. .filter(item => this.IS_ADMIN || item.key !== "examNumber");
  334. this.rebuildRight();
  335. },
  336. methods: {
  337. getStepType() {
  338. const paper = this.curPaperOrTask;
  339. if (paper.shift && paper.shiftScore && !paper.level) return "shift";
  340. if (!paper.shift && paper.shiftScore) return "shiftScore";
  341. if (this.IS_MARKER) {
  342. if (!paper.result) return "undo";
  343. if (paper.result) return "done";
  344. } else {
  345. if (paper.score !== null) return "done";
  346. if (paper.score === null) return "undo";
  347. }
  348. },
  349. rebuildRight() {
  350. const curPaperScore = this.IS_MARKER
  351. ? this.curPaperOrTask.result
  352. : this.curPaperOrTask.score;
  353. this.curPaperScore = curPaperScore !== null ? curPaperScore + "" : "";
  354. this.stepType = this.getStepType();
  355. this.stepLabel = this.stepDict[this.stepType];
  356. this.rights = { ...initRights };
  357. const roleRights = this.roleRight[this.userRole][this.stepType] || [];
  358. roleRights.map(key => {
  359. this.rights[key] = true;
  360. });
  361. if (this.curPaperOrTask.level) {
  362. this.curLevel = this.levels.find(
  363. level => level.name === this.curPaperOrTask.level
  364. );
  365. this.curPaperLevel =
  366. this.curPaperOrTask["displayNumber"] && this.stepType !== "shiftScore"
  367. ? this.curPaperOrTask["serialNumber"]
  368. : this.curLevel.name;
  369. this.updateScoreList();
  370. }
  371. if (this.rights.markHis) {
  372. this.getMarkHistory();
  373. }
  374. },
  375. updateScoreList() {
  376. let scores = [];
  377. const { minScore, maxScore } = this.curLevel;
  378. for (let i = minScore; i <= maxScore; i++) {
  379. scores.push(i);
  380. }
  381. this.scores = scores;
  382. },
  383. async getMarkHistory() {
  384. const data = await markHistoryList(this.curPaperOrTask.id, "SCORE");
  385. this.gradingHistory = data.map(item => {
  386. return {
  387. id: item.markerId,
  388. name: item.marker,
  389. value: item.result || "未评"
  390. };
  391. });
  392. },
  393. selectLevel(level) {
  394. if (this.curPaperOrTask.level === level.name) return;
  395. if (this.btnClicked) return;
  396. this.btnClicked = true;
  397. this.setT = setTimeout(() => {
  398. this.btnClicked = false;
  399. }, 500);
  400. // 科组长改档 / 评卷同意改档
  401. this.$emit("on-leader-level", {
  402. paperId: this.curPaperOrTask.id,
  403. curLevel: this.curPaperOrTask.level,
  404. selectedLevel: level.name
  405. });
  406. },
  407. gradeChangeConfirm() {
  408. this.selectLevel({ name: this.curPaperOrTask.redoLevel });
  409. },
  410. selectScore(score) {
  411. if (this.btnClicked) return;
  412. this.btnClicked = true;
  413. this.setT = setTimeout(() => {
  414. this.btnClicked = false;
  415. }, 500);
  416. // 评卷员打分
  417. this.$emit("on-select-score", score * 1);
  418. },
  419. toPass() {
  420. this.$emit("on-pass");
  421. },
  422. searchCode() {
  423. if (!this.filter.code || !this.filter.codeType) {
  424. this.$Message.error("请设置密号类型和密号!");
  425. return;
  426. }
  427. this.$emit("on-code-search", this.filter);
  428. },
  429. searchGradeChange() {
  430. this.$emit("on-grade-change-search", this.applyChangeLevelStatus);
  431. }
  432. }
  433. };
  434. </script>