GradeAction.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. <template>
  2. <div class="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. clearable
  22. >
  23. </Input>
  24. <Button size="small" type="primary" class="search-btn" @click="searchCode"
  25. >查询</Button
  26. >
  27. </div>
  28. <!-- 头部信息 ------ -->
  29. <!-- 试卷状态 -->
  30. <!-- 状态:已评,待评,打回,仲裁 -->
  31. <div class="action-paper-state" v-if="stepType === 'reject'">
  32. <p class="paper-state-cont">
  33. {{ curPaperOrTask.isRejectedByLeader ? "科组长打回" : "自动打回" }}
  34. </p>
  35. <p class="paper-state-intro" v-if="curPaperOrTask.rejectedCount">
  36. 共打回{{ curPaperOrTask.rejectedCount }}次
  37. </p>
  38. </div>
  39. <div class="action-paper-state" v-else>
  40. <p class="paper-state-cont">{{ stepLabel }}</p>
  41. </div>
  42. <!-- 试卷信息 -->
  43. <div class="action-paper-info">
  44. <p v-if="IS_ADMIN">
  45. <span>试卷考号:</span><span>{{ curPaperOrTask.examNumber }}</span>
  46. </p>
  47. <p>
  48. <span v-if="IS_MARKER">任务密号:</span>
  49. <span v-else>试卷密号:</span>
  50. <span>NO.{{ curPaperOrTask.sn }}</span>
  51. </p>
  52. </div>
  53. <!-- 档位信息 -->
  54. <!-- 已评(已评档位),打回(建议档位) -->
  55. <h3 class="action-grade-info-title" v-if="curPaperOrTask.rejected">
  56. 建议档位:
  57. </h3>
  58. <div class="action-grade-info" v-if="rights.gradeInfo">
  59. <h3 class="grade-info-name">{{ curLevel.name }}</h3>
  60. <div class="grade-info-range">
  61. <p>分数范围</p>
  62. <p>
  63. <span>{{ curLevel.minScore }}</span>
  64. <span>~</span>
  65. <span>{{ curLevel.maxScore }}</span>
  66. </p>
  67. </div>
  68. </div>
  69. <!-- 选择档位 -->
  70. <div class="action-grade-list" v-if="rights.gradeList">
  71. <div
  72. class="action-grade-item"
  73. v-for="(level, index) in levels"
  74. :key="index"
  75. >
  76. <div
  77. :class="[
  78. 'action-grade-item-content',
  79. { 'action-item-content-disabled': btnClicked }
  80. ]"
  81. @click="selectLevel(level)"
  82. >
  83. <p>{{ level.name }}</p>
  84. <p>{{ level.minScore }}~{{ level.maxScore }}</p>
  85. </div>
  86. </div>
  87. </div>
  88. <div
  89. class="action-grade-pass"
  90. v-if="rights.gradeList && IS_MARKER"
  91. @click="toPass"
  92. >
  93. 跳过
  94. </div>
  95. <!-- 评卷记录 -->
  96. <div class="action-grade-history" v-if="rights.gradeHis">
  97. <h3>评卷记录</h3>
  98. <div class="grade-history-list">
  99. <div
  100. class="grade-history-item"
  101. v-for="his in gradingHistory"
  102. :key="his.id"
  103. >
  104. <p>{{ his.loginName }}</p>
  105. <p>{{ his.value }}</p>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </template>
  111. <script>
  112. import { markHistoryList } from "@/api";
  113. import { CODE_TYPE } from "@/constants/enumerate";
  114. // 三种情况:
  115. // 管理员(ADMIN),科组长(MARK_LEADER),评卷员(MARKER)
  116. // 管理员:查询,头部信息,评卷记录
  117. // 科组长:查询,头部信息,选择档位,评卷记录
  118. // 评卷员:头部信息,选择档位
  119. // MARK_LEADER / ADMIN: curPaperOrTask => paper
  120. // MARKER: curPaperOrTask => task
  121. //
  122. /*
  123. [paper template]
  124. {
  125. "id": 165,
  126. "sn": "029947536",
  127. "examNumber": "1901040084",
  128. "level": "A",
  129. "score": null,
  130. "redoLevel": null,
  131. "updatedOn": 1591767742000,
  132. "imgSrc": "",
  133. "thumbSrc": "",
  134. "markByLeader": false,
  135. "markedLogic": true,
  136. "areaCode": "2",
  137. "inspectScore": null,
  138. "inspectLevel": null,
  139. "inspector": null,
  140. "sheetSrc": null,
  141. "stage": "LEVEL",
  142. "test": 0,
  143. "paperTest": 0,
  144. "markResults": [],
  145. "rejected": false,
  146. "arbitrated": false,
  147. "sample": false,
  148. "tagged": false,
  149. "missing": false,
  150. "manual": false
  151. }
  152. [marktask template]
  153. {
  154. "id": 511,
  155. "sn": "4929446110",
  156. "redoLevel": null,
  157. "level": "A",
  158. "score": null,
  159. "result": "100",
  160. "originLevel": null,
  161. "markerId": 49,
  162. "marker": "pj061001",
  163. "updatedOn": 1594775592000,
  164. "imgSrc": "",
  165. "thumbSrc": "",
  166. "markByLeader": true,
  167. "oldRejected": false,
  168. "paperId": 168,
  169. "randomSeqNew": 9446110,
  170. "randomSeq": null,
  171. "rejected": false,
  172. "sample": true
  173. }
  174. */
  175. const initRights = {
  176. search: false,
  177. gradeInfo: false,
  178. gradeList: false,
  179. gradeHis: false
  180. };
  181. export default {
  182. name: "grade-action",
  183. props: {
  184. curPaperOrTask: {
  185. type: Object,
  186. default() {
  187. return {};
  188. }
  189. },
  190. levels: {
  191. type: Array,
  192. default() {
  193. return [];
  194. }
  195. },
  196. userRole: {
  197. type: String,
  198. default: "MARKER"
  199. }
  200. },
  201. data() {
  202. return {
  203. rights: {
  204. ...initRights
  205. },
  206. roleRight: {
  207. SUPER_ADMIN: {
  208. done: ["search", "gradeHis", "gradeInfo"],
  209. reject: ["search", "gradeInfo", "gradeHis"],
  210. arbitrate: ["search", "gradeHis"]
  211. },
  212. ADMIN: {
  213. done: ["search", "gradeHis", "gradeInfo"],
  214. reject: ["search", "gradeInfo", "gradeHis"],
  215. arbitrate: ["search", "gradeHis"]
  216. },
  217. MARK_LEADER: {
  218. undo: ["search", "gradeList", "gradeInfo"],
  219. done: ["search", "gradeList", "gradeHis", "gradeInfo"],
  220. reject: ["search", "gradeList", "gradeInfo", "gradeHis"],
  221. arbitrate: ["search", "gradeList", "gradeHis"]
  222. },
  223. MARKER: {
  224. done: ["gradeList", "gradeInfo"],
  225. undo: ["gradeList"],
  226. reject: ["gradeList", "gradeInfo"]
  227. },
  228. STANDARD: ["gradeInfo"]
  229. },
  230. filter: {
  231. codeType: "examNumber",
  232. code: ""
  233. },
  234. codeTypes: [],
  235. stepDict: {
  236. undo: "待评",
  237. done: "已评",
  238. reject: "打回",
  239. arbitrate: "待仲裁",
  240. sample: "标准卷"
  241. },
  242. stepType: "",
  243. stepLabel: "",
  244. gradingHistory: [],
  245. curLevel: {},
  246. setT: null,
  247. btnClicked: false
  248. };
  249. },
  250. computed: {
  251. IS_ADMIN() {
  252. return this.userRole === "ADMIN" || this.userRole === "SUPER_ADMIN";
  253. },
  254. IS_MARKER() {
  255. return this.userRole === "MARKER";
  256. },
  257. IS_MARK_LEADER() {
  258. return this.userRole === "MARK_LEADER";
  259. }
  260. },
  261. watch: {
  262. curPaperOrTask(val) {
  263. this.rebuildRight();
  264. }
  265. },
  266. mounted() {
  267. this.codeTypes = Object.entries(CODE_TYPE)
  268. .map(([key, val]) => {
  269. return {
  270. key,
  271. val
  272. };
  273. })
  274. .filter(item => this.IS_ADMIN || item.key !== "examNumber");
  275. this.rebuildRight();
  276. },
  277. methods: {
  278. getStepType() {
  279. const info = this.curPaperOrTask;
  280. if (info.sample) return "sample";
  281. if (info.level) return "done";
  282. if (info.arbitrated) return "arbitrate";
  283. if (info.rejected) return "reject";
  284. if (!info.rejected && !info.arbitrated && !info.level) return "undo";
  285. return;
  286. },
  287. rebuildRight() {
  288. let roleRights = [];
  289. this.stepType = this.getStepType();
  290. this.stepLabel = this.stepDict[this.stepType];
  291. if (this.stepType === "sample") {
  292. roleRights = this.roleRight.STANDARD;
  293. } else {
  294. roleRights = this.roleRight[this.userRole][this.stepType] || [];
  295. }
  296. this.rights = { ...initRights };
  297. roleRights.map(key => {
  298. this.rights[key] = true;
  299. });
  300. this.getCurLevel();
  301. if (this.rights.gradeHis) {
  302. this.getMarkHistory();
  303. }
  304. },
  305. getCurLevel() {
  306. const levelName = this.curPaperOrTask.rejected
  307. ? this.curPaperOrTask.redoLevel
  308. : this.curPaperOrTask.level;
  309. if (levelName) {
  310. this.curLevel = this.levels.find(item => item.name === levelName);
  311. }
  312. },
  313. async getMarkHistory() {
  314. // 只有科组长和超管才会展示评卷记录
  315. const data = await markHistoryList(this.curPaperOrTask.id, "LEVEL");
  316. this.gradingHistory = data.map(item => {
  317. let level = item.result || "未评";
  318. if (this.stepType === "reject" && !item.result) {
  319. level = `${level}(${item.originLevel})`;
  320. }
  321. return {
  322. id: item.id,
  323. markerId: item.markerId,
  324. name: item.marker,
  325. loginName: item.loginName,
  326. value: level
  327. };
  328. });
  329. },
  330. selectLevel(level) {
  331. if (this.IS_MARKER && this.curPaperOrTask.level === level.name) return;
  332. if (this.btnClicked) return;
  333. this.btnClicked = true;
  334. this.setT = setTimeout(() => {
  335. this.btnClicked = false;
  336. }, 500);
  337. if (this.IS_MARK_LEADER) {
  338. this.$emit(
  339. "on-leader-level",
  340. {
  341. paperIds: this.curPaperOrTask.id + "",
  342. curLevel: this.curPaperOrTask.level,
  343. selectedLevel: level.name
  344. },
  345. this.gradingHistory.map(item => {
  346. return {
  347. id: item.markerId,
  348. name: item.loginName
  349. };
  350. })
  351. );
  352. return;
  353. }
  354. this.$emit("on-select-level", level);
  355. },
  356. toPass() {
  357. this.$emit("on-pass");
  358. },
  359. searchCode() {
  360. if (!this.filter.code || !this.filter.codeType) {
  361. this.$Message.error("请设置密号类型和密号!");
  362. return;
  363. }
  364. this.$emit("on-code-search", this.filter);
  365. }
  366. },
  367. beforeDestroy() {
  368. if (this.setT) clearTimeout(this.setT);
  369. }
  370. };
  371. </script>