TpScoreBoard.vue 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246
  1. <template>
  2. <div class="scoreboard pull-right">
  3. <div class="board-margin">
  4. <div class="first-board">
  5. <span class="title-font">操作方式切换:</span>
  6. <el-switch
  7. v-model="isMouseMode"
  8. class="pull-right"
  9. active-text="鼠标"
  10. inactive-text="键盘"
  11. active-color="#4cb0f9"
  12. inactive-color="#13ce66"
  13. ></el-switch>
  14. </div>
  15. <div v-show="examType != 'OFFLINE'" class="first-board">
  16. <el-checkbox v-model="showBody">显示题干</el-checkbox
  17. ><el-checkbox v-model="showAnswer">显示标答</el-checkbox>
  18. </div>
  19. <div class="second-board">
  20. <div class="board-title"><span>总分</span></div>
  21. <div class="board-score">
  22. <span>{{ totalScore }}分</span>
  23. </div>
  24. <div class="total-all-score-title"><span>全卷分</span></div>
  25. <div class="total-all-score">
  26. <span>{{ totalAllScore }}</span>
  27. </div>
  28. </div>
  29. <!-- 鼠标模式 -->
  30. <div v-if="isMouseMode">
  31. <div class="title-board"><span class="title-font">评分</span></div>
  32. <div class="itemScroll">
  33. <div
  34. v-for="(resultItemInner, index) in resultItemsData"
  35. :id="resultItemInner.markItem.id"
  36. :key="resultItemInner.markItem.id"
  37. class="pull-left scoretitle titlebutton"
  38. size="small"
  39. @click="
  40. itemClick(
  41. resultItemInner.markItem.id,
  42. $event,
  43. resultItemInner.markItem.orders
  44. )
  45. "
  46. >
  47. <div
  48. :class="{ 'active-btn': itemClass[index] }"
  49. class="title-item-top"
  50. >
  51. <span>
  52. {{ resultItemInner.markItem.mainNumber }}({{
  53. resultItemInner.markItem.orders
  54. }})
  55. </span>
  56. </div>
  57. <div
  58. class="title-item-bottom"
  59. :class="{ 'active-text': itemClass[index] }"
  60. >
  61. <span>{{ resultItemInner.score }}分</span>
  62. </div>
  63. </div>
  64. </div>
  65. <div v-if="markTypeView">
  66. <div class="step-board"></div>
  67. <div class="title-board"><span class="title-font">打分</span></div>
  68. <div class="itemScroll">
  69. <div
  70. v-for="(score, index) in itemScores"
  71. :key="score"
  72. class="pull-left scoretitle"
  73. >
  74. <div
  75. class="scorebutton"
  76. :class="{ 'score-btn': itemScoreBtn[index] }"
  77. @click="scoreClick(score, index)"
  78. >
  79. <span class="score-item">{{ score }}</span>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. <!-- 键盘模式 -->
  86. <div v-if="!isMouseMode">
  87. <div class="title-board"><span class="title-font">评分</span></div>
  88. <div>
  89. <div class="itemScroll">
  90. <div
  91. v-for="(resultItemInner, index) in resultItemsData"
  92. :key="resultItemInner.markItem.id"
  93. class="scoretitle"
  94. >
  95. <div class="box-card">
  96. <div class="item-title">
  97. <div class="pull-left item-number">
  98. {{ resultItemInner.markItem.mainNumber }}({{
  99. resultItemInner.markItem.orders
  100. }})
  101. </div>
  102. <div class="pull-left item-number2">
  103. <span>{{ resultItemInner.markItem.maxScore }}分</span>
  104. </div>
  105. <div class="pull-left item-number3">
  106. 间隔:{{
  107. itemScoreStep(resultItemInner.markItem.scoreInterval)
  108. }}
  109. </div>
  110. </div>
  111. <div class="item-score">
  112. <input
  113. :id="getItemId(resultItemInner.markItem.id)"
  114. v-model="resultItemInner.score"
  115. class="score-input"
  116. @focus="scoreFocus(resultItemInner)"
  117. @keydown.enter="scoreEnter(index, resultItemInner)"
  118. @keydown.up="scoreUp(index, resultItemInner)"
  119. @keydown.down="scoreDown(index, resultItemInner)"
  120. @change="scoreChange(index, resultItemInner.score)"
  121. />
  122. </div>
  123. </div>
  124. </div>
  125. </div>
  126. </div>
  127. </div>
  128. <div>
  129. <div class="step-board"></div>
  130. <div class="title-board">
  131. <span class="title-font">备注</span>
  132. <div
  133. v-if="!textareaflag"
  134. class="el-icon-caret-right remark-board"
  135. @click="showTextarea"
  136. ></div>
  137. <div
  138. v-if="textareaflag"
  139. class="el-icon-caret-top remark-board"
  140. @click="showTextarea"
  141. ></div>
  142. </div>
  143. <div v-if="textareaflag" class="remark-step">
  144. <textarea
  145. id="remark"
  146. v-model="markedResultData.markRemark"
  147. type="text"
  148. rows="3"
  149. cols="35"
  150. placeholder="请输入内容"
  151. />
  152. </div>
  153. </div>
  154. <div>
  155. <div v-if="problemView">
  156. <div class="problem-button"></div>
  157. <span v-if="tagFlag">
  158. <el-radio-group
  159. v-model="markedResultData.tag"
  160. @change="processTagPaper"
  161. >
  162. <div
  163. v-for="tag in tags"
  164. :key="tag.code"
  165. class="pull-left scoretitle"
  166. >
  167. <el-radio :label="tag.code">{{ tag.name }}</el-radio>
  168. </div>
  169. </el-radio-group>
  170. </span>
  171. <span v-if="!tagFlag">
  172. <el-radio-group v-model="unusualType" @change="processTagPaper">
  173. <div
  174. v-for="tag in tags"
  175. :key="tag.code"
  176. class="pull-left scoretitle"
  177. >
  178. <el-radio :key="tag.code" :label="tag.code">{{
  179. tag.name
  180. }}</el-radio>
  181. </div>
  182. </el-radio-group>
  183. </span>
  184. </div>
  185. <div v-if="paperMark" class="pull-left btn">
  186. <el-button
  187. id="subMarkBtn"
  188. class="submit-button"
  189. type="primary"
  190. size="small"
  191. :round="true"
  192. :loading="loading"
  193. @keydown.enter="submitMark"
  194. @click="submitMark"
  195. >
  196. <span class="sub-btn">提</span> <span>交</span>
  197. </el-button>
  198. </div>
  199. <div v-if="paperMark" class="pull-left btn">
  200. <el-button
  201. type="danger"
  202. :round="true"
  203. size="small"
  204. @click="problemClick"
  205. >问题卷</el-button
  206. >
  207. </div>
  208. <div v-if="paperMark && problemView" class="pull-left btn">
  209. <el-button
  210. type="danger"
  211. :round="true"
  212. size="small"
  213. @click="resetProblem"
  214. >清除问题卷</el-button
  215. >
  216. </div>
  217. </div>
  218. </div>
  219. </div>
  220. </template>
  221. <script>
  222. import { mapActions } from "vuex";
  223. import { USER_SIGNOUT } from "../../portal/store/user";
  224. import { mapState } from "vuex";
  225. import { CORE_API, MARKING_API } from "@/constants/constants";
  226. import { EVENTHUB } from "../constants/constants";
  227. export default {
  228. props: {
  229. objectiveScore: { type: Number, default: 0.0 },
  230. paperMarkSign: {
  231. type: Array,
  232. default: () => [],
  233. },
  234. signScores: {
  235. type: Array,
  236. default: () => [],
  237. },
  238. signOption: {
  239. type: Object,
  240. default: () => {},
  241. },
  242. markSign: {
  243. type: Boolean,
  244. default: false,
  245. },
  246. studentPaperId: {
  247. type: [String, Number],
  248. default: "",
  249. },
  250. markTaskId: {
  251. type: Number,
  252. default: 0,
  253. },
  254. resultItems: {
  255. type: Array,
  256. default: () => [],
  257. },
  258. markedResult: {
  259. type: Object,
  260. default: () => {},
  261. },
  262. paperMark: {
  263. type: Boolean,
  264. default: true,
  265. },
  266. scoreStep: {
  267. type: Number,
  268. default: 0.5,
  269. },
  270. examType: {
  271. type: String,
  272. default: "",
  273. },
  274. },
  275. data() {
  276. return {
  277. showBody: true,
  278. showAnswer: true,
  279. resultItemsData: this.resultItems,
  280. signOptionData: this.signOption,
  281. signScoresData: this.signScores,
  282. markedResultData: this.markedResult,
  283. activeName: "first",
  284. markType: "mouse",
  285. isMouseMode: true,
  286. op: "first",
  287. maxScore: 0,
  288. markItemId: "",
  289. resultItem: {
  290. markItem: {},
  291. score: 0,
  292. },
  293. markTypeView: false,
  294. problemView: false,
  295. markBack: false,
  296. markSame: false,
  297. markBlank: false,
  298. markDiff: false,
  299. curIndex: 0,
  300. steps: [],
  301. btnflag: false,
  302. textareaflag: false,
  303. tmpSignItem: this.signItem,
  304. tags: [],
  305. unusualType: "",
  306. scoreError: [],
  307. itemScoreBtn: [],
  308. loading: false,
  309. };
  310. },
  311. computed: {
  312. tagFlag() {
  313. if (this.markedResultData.id) {
  314. return true;
  315. } else {
  316. return false;
  317. }
  318. },
  319. paperKey() {
  320. if (!this.markSign) return "";
  321. return this.studentPaperId;
  322. },
  323. signScoreSum() {
  324. var sum = 0;
  325. for (let signScore of this.signScoresData) {
  326. sum += signScore;
  327. }
  328. return sum;
  329. },
  330. itemClass() {
  331. var itemClass = [];
  332. for (let resultItem of this.resultItemsData) {
  333. if (resultItem.score.length == 0) {
  334. itemClass.push(false);
  335. } else {
  336. itemClass.push(true);
  337. }
  338. }
  339. return itemClass;
  340. },
  341. totalScore() {
  342. var totalScore = 0;
  343. for (let resultItem of this.resultItemsData) {
  344. if (resultItem.score.length == 0) {
  345. totalScore = this.accAdd(totalScore, 0);
  346. } else {
  347. totalScore = this.accAdd(
  348. totalScore,
  349. Number.parseFloat(resultItem.score)
  350. );
  351. }
  352. }
  353. return totalScore;
  354. },
  355. totalAllScore() {
  356. return this.accAdd(this.totalScore, this.objectiveScore);
  357. },
  358. itemScores() {
  359. var itemScores = [];
  360. var scoreInterval = this.resultItem.markItem.scoreInterval;
  361. if (this.scoreStep != null) {
  362. scoreInterval = this.scoreStep;
  363. }
  364. let i = 0;
  365. let j = 0;
  366. do {
  367. itemScores[j] = i;
  368. i = this.accAdd(i, scoreInterval);
  369. j++;
  370. } while (i <= this.resultItem.markItem.maxScore);
  371. if (
  372. itemScores[itemScores.length - 1] < this.resultItem.markItem.maxScore
  373. ) {
  374. itemScores[itemScores.length] = this.resultItem.markItem.maxScore;
  375. }
  376. return itemScores;
  377. },
  378. ...mapState({ user: (state) => state.user }),
  379. },
  380. watch: {
  381. resultItems: {
  382. immediate: false,
  383. handler(val) {
  384. this.resultItemsData = val;
  385. if (!this.isMouseMode) {
  386. //切换不同考试的试卷时,光标定位要在resultItems变化之后做
  387. this.initKeyBoardMode();
  388. }
  389. },
  390. },
  391. signOption: {
  392. immediate: false,
  393. handler(val) {
  394. this.signOptionData = val;
  395. },
  396. },
  397. signScores: {
  398. immediate: false,
  399. handler(val) {
  400. this.signScoresData = val;
  401. },
  402. },
  403. markedResult: {
  404. immediate: false,
  405. handler(val) {
  406. this.markedResultData = val;
  407. },
  408. },
  409. signItem(val) {
  410. this.tmpSignItem = val;
  411. },
  412. tmpSignItem(val) {
  413. this.$emit("changeSign", val);
  414. },
  415. isMouseMode(val) {
  416. if (!val) {
  417. this.initKeyBoardMode();
  418. }
  419. },
  420. studentPaperId() {
  421. if (!this.isMouseMode) {
  422. this.initKeyBoardMode();
  423. }
  424. },
  425. showAnswer: {
  426. immediate: false,
  427. handler() {
  428. this.showAnswerChange();
  429. },
  430. },
  431. showBody: {
  432. immediate: false,
  433. handler() {
  434. this.showBodyChange();
  435. },
  436. },
  437. },
  438. created() {
  439. this.getTags();
  440. },
  441. methods: {
  442. ...mapActions([USER_SIGNOUT]),
  443. showAnswerChange() {
  444. if (this.examType == "OFFLINE") {
  445. return;
  446. }
  447. var es = Array.from(document.getElementsByClassName("right-answer"));
  448. var displayVal = this.showAnswer ? "block" : "none";
  449. es.forEach((element) => {
  450. element.style.display = displayVal;
  451. });
  452. },
  453. showBodyChange() {
  454. if (this.examType == "OFFLINE") {
  455. return;
  456. }
  457. var es = Array.from(document.getElementsByClassName("question-body"));
  458. var displayVal = this.showBody ? "block" : "none";
  459. es.forEach((element) => {
  460. element.style.display = displayVal;
  461. });
  462. },
  463. resetProblem() {
  464. if (this.markedResultData.tag) {
  465. this.markedResultData.tag = "";
  466. }
  467. if (this.unusualType) {
  468. this.unusualType = "";
  469. }
  470. },
  471. //处理问题卷
  472. processTagPaper() {
  473. if (!this.markedResultData.id) {
  474. if (this.unusualType) {
  475. for (let resultItem of this.resultItemsData) {
  476. resultItem.score = 0;
  477. }
  478. }
  479. } else {
  480. if (this.markedResultData.tag) {
  481. for (let resultItem of this.resultItemsData) {
  482. resultItem.score = 0;
  483. }
  484. }
  485. }
  486. },
  487. getTags() {
  488. this.$http.get(MARKING_API + "/markResults/tag").then((response) => {
  489. this.tags = response.data;
  490. //移除科目错误
  491. for (let i = 0; i < this.tags.length; i++) {
  492. if (this.tags[i].code === "SUBJECT_ERROR") {
  493. this.tags.splice(i, 1);
  494. }
  495. }
  496. });
  497. },
  498. //在内存中对试卷进行标记保存
  499. saveMarkSign() {
  500. localStorage.removeItem(this.paperKey);
  501. localStorage.setItem(this.paperKey, JSON.stringify(this.paperMarkSign));
  502. },
  503. checkItemClass(resultItem) {
  504. if (resultItem.score.length > 0) {
  505. return true;
  506. } else {
  507. return false;
  508. }
  509. },
  510. itemClick(id, event, order) {
  511. this.markTypeView = true;
  512. this.resultItemsData.find((value, index) => {
  513. if (value.markItem.id === id) {
  514. this.maxScore = value.markItem.maxScore;
  515. this.markItemId = value.markItem.id;
  516. if (value.score.length > 0) {
  517. this.resultItem = value;
  518. } else {
  519. this.resultItem = {
  520. markItem: value.markItem,
  521. score: "",
  522. };
  523. }
  524. this.curIndex = index;
  525. }
  526. });
  527. this.showItemTitle();
  528. if (this.markSign) {
  529. this.tmpSignItem = this.resultItem.markItem;
  530. this.signScoresData.splice(0, this.signScoresData.length);
  531. }
  532. this.positionDiv(order);
  533. //重置打分板样式
  534. this.itemScoreBtn = [];
  535. },
  536. positionDiv(order) {
  537. EVENTHUB.$emit("positionDiv", order);
  538. },
  539. showItemTitle() {
  540. var title =
  541. this.resultItem.markItem.mainNumber +
  542. "(" +
  543. this.resultItem.markItem.orders +
  544. ")";
  545. this.$notify({
  546. showClose: true,
  547. message: "当前选择题目为" + title,
  548. type: "warning",
  549. });
  550. },
  551. checkSignScore(score) {
  552. var sum = 0;
  553. for (let signScore of this.signScoresData) {
  554. sum += signScore;
  555. }
  556. if (sum + score > this.maxScore) {
  557. return false;
  558. } else {
  559. return true;
  560. }
  561. },
  562. //检查每项分数是否满足要求
  563. checkScore(resultItem) {
  564. var score = resultItem.score + "";
  565. var maxScore = resultItem.markItem.maxScore + "";
  566. if (score.trim().length === 0) {
  567. this.$notify({
  568. message: "分数不能为空",
  569. type: "error",
  570. duration: 2000,
  571. });
  572. return false;
  573. } else {
  574. let regex = "^\\d+(\\.[\\d])?$";
  575. if (!score.match(regex)) {
  576. this.$notify({
  577. message: "分数必须为数字且最多一位小数",
  578. type: "error",
  579. duration: 2000,
  580. });
  581. return false;
  582. } else {
  583. if (parseFloat(score) > parseFloat(maxScore)) {
  584. this.$notify({
  585. message: "分数不能超过" + maxScore + "分",
  586. type: "error",
  587. duration: 2000,
  588. });
  589. return false;
  590. }
  591. }
  592. }
  593. //校验分数是否是间隔的倍数
  594. var scoreInterval = resultItem.markItem.scoreInterval;
  595. if (this.scoreStep != null) {
  596. scoreInterval = this.scoreStep;
  597. }
  598. if (
  599. parseFloat(score) != 0 &&
  600. parseFloat(score) != parseFloat(maxScore) &&
  601. (parseFloat(score) * 10) % (scoreInterval * 10) != 0
  602. ) {
  603. this.$notify({
  604. message: "分数必须是给分间隔的倍数或者零分、满分",
  605. type: "error",
  606. duration: 2000,
  607. });
  608. return false;
  609. }
  610. return true;
  611. },
  612. scoreClick(score, index1) {
  613. //轨迹模式处理分值问题
  614. if (this.markSign) {
  615. if (this.checkSignScore(score)) {
  616. this.signScoresData.push(score);
  617. this.signOptionData.score = score;
  618. this.resultItem.score = this.signScoreSum;
  619. this.resultItemsData[this.curIndex].score = this.signScoreSum;
  620. } else {
  621. this.$notify({
  622. message: "轨迹总分不能超过满分",
  623. type: "error",
  624. });
  625. }
  626. } else {
  627. //正常模式
  628. this.resultItem.score = score;
  629. this.resultItemsData[this.curIndex].score = score;
  630. //设置动态样式(打分板)
  631. this.itemScoreBtn = [];
  632. for (let i = 0; i < this.itemScores.length; i++) {
  633. if (i == index1) {
  634. this.itemScoreBtn.push(true);
  635. } else {
  636. this.itemScoreBtn.push(false);
  637. }
  638. }
  639. }
  640. },
  641. //键盘打分板change事件
  642. scoreChange(index, score) {
  643. this.resultItem.score = score;
  644. this.resultItemsData[index].score = score;
  645. },
  646. //键盘打分板聚焦后试卷跳转对应试题
  647. scoreFocus(resultItem) {
  648. var order = resultItem.markItem.orders;
  649. this.positionDiv(order);
  650. },
  651. //键盘打分板下键跳转下一题
  652. scoreDown(index, resultItem) {
  653. var curItemId = this.resultItemsData[index].markItem.id;
  654. var curItemInput = "item" + curItemId;
  655. if (!this.checkScore(resultItem)) {
  656. document.getElementById(curItemInput).focus();
  657. return;
  658. }
  659. if (index === this.resultItemsData.length - 1) {
  660. return;
  661. } else {
  662. var nextResultItem = this.resultItemsData[index + 1];
  663. var nextItemId = nextResultItem.markItem.id;
  664. var nextItemInput = "item" + nextItemId;
  665. var order = nextResultItem.markItem.orders;
  666. document.getElementById(nextItemInput).focus();
  667. this.positionDiv(order);
  668. }
  669. },
  670. //键盘打分板上键跳转上一题
  671. scoreUp(index, resultItem) {
  672. var curItemId = this.resultItemsData[index].markItem.id;
  673. var curItemInput = "item" + curItemId;
  674. if (!this.checkScore(resultItem)) {
  675. document.getElementById(curItemInput).focus();
  676. return;
  677. }
  678. if (index === 0) {
  679. let preResultItem = this.resultItemsData[0];
  680. let preItemId = preResultItem.markItem.id;
  681. let preItemInput = "item" + preItemId;
  682. let order = preResultItem.markItem.orders;
  683. document.getElementById(preItemInput).focus();
  684. this.positionDiv(order);
  685. } else {
  686. let preResultItem = this.resultItemsData[index - 1];
  687. let preItemId = preResultItem.markItem.id;
  688. let preItemInput = "item" + preItemId;
  689. let order = preResultItem.markItem.orders;
  690. document.getElementById(preItemInput).focus();
  691. this.positionDiv(order);
  692. }
  693. },
  694. //键盘打分板回车后跳转下一题
  695. scoreEnter(index, resultItem) {
  696. if (!this.checkScore(resultItem)) {
  697. var curItemId = this.resultItemsData[index].markItem.id;
  698. var curItemInput = "item" + curItemId;
  699. document.getElementById(curItemInput).focus();
  700. return;
  701. }
  702. if (index === this.resultItemsData.length - 1) {
  703. document.getElementById("subMarkBtn").focus();
  704. } else {
  705. var nextResultItem = this.resultItemsData[index + 1];
  706. var nextItemId = nextResultItem.markItem.id;
  707. var nextItemInput = "item" + nextItemId;
  708. var order = nextResultItem.markItem.orders;
  709. document.getElementById(nextItemInput).focus();
  710. this.positionDiv(order);
  711. }
  712. },
  713. getItemId(itemId) {
  714. return "item" + itemId;
  715. },
  716. problemClick() {
  717. this.problemView = !this.problemView;
  718. },
  719. //检查评分项
  720. checkItems() {
  721. var itemName = "";
  722. for (var resultItem of this.resultItemsData) {
  723. if (resultItem.score.length == 0) {
  724. itemName =
  725. Number.parseInt(resultItem.markItem.mainNumber) +
  726. "(" +
  727. resultItem.markItem.orders +
  728. ")";
  729. this.$notify({
  730. title: "警告",
  731. message: itemName + "没有打分,请打分",
  732. type: "warning",
  733. });
  734. if (!this.isMouseMode) {
  735. let curItemInput = "item" + resultItem.markItem.id;
  736. document.getElementById(curItemInput).focus();
  737. }
  738. return false;
  739. } else {
  740. if (!this.checkScore(resultItem)) {
  741. if (!this.isMouseMode) {
  742. let curItemInput = "item" + resultItem.markItem.id;
  743. document.getElementById(curItemInput).focus();
  744. }
  745. return false;
  746. }
  747. }
  748. }
  749. return true;
  750. },
  751. submitMark() {
  752. if (!this.checkItems()) {
  753. return;
  754. }
  755. this.processTagPaper();
  756. this.loading = true;
  757. this.$loading({ fullscreen: true });
  758. let remarkValue = "";
  759. if (document.getElementById("remark")) {
  760. remarkValue = document.getElementById("remark").value;
  761. }
  762. if (!this.markedResultData.id) {
  763. //正常提交情况
  764. this.$httpWithMsg
  765. .post(
  766. MARKING_API +
  767. "/markResults?studentPaperId=" +
  768. this.studentPaperId +
  769. "&markTaskId=" +
  770. this.markTaskId +
  771. "&tag=" +
  772. this.unusualType +
  773. "&remark=" +
  774. remarkValue,
  775. this.resultItemsData
  776. )
  777. .then(
  778. (response) => {
  779. this.saveMarkSign();
  780. if (response.data.id) {
  781. this.$notify({
  782. message: "提交成功",
  783. type: "success",
  784. });
  785. } else {
  786. this.$notify({
  787. message: "提交失败",
  788. type: "error",
  789. });
  790. }
  791. //调用Marking.vue中方法:执行的是拿取下一份试卷
  792. this.$emit("submitMark");
  793. this.loading = false;
  794. this.markTypeView = false;
  795. this.problemView = false;
  796. this.unusualType = "";
  797. },
  798. (error) => {
  799. // 响应错误回调
  800. if (error.response.data.desc) {
  801. var errorInfo = error.response.data.desc;
  802. if (errorInfo.includes("超时")) {
  803. this.$loading().close();
  804. this.loading = false;
  805. this.$alert(
  806. "该评卷任务已超时,请点击确定重新登录!",
  807. "提示",
  808. {
  809. confirmButtonText: "确定",
  810. callback: () => {
  811. this.$http
  812. .post(CORE_API + "/auth/logout")
  813. .then(() => {
  814. const orgId = this.user.rootOrgId;
  815. this.USER_SIGNOUT();
  816. window.name = "";
  817. this.$router.replace({
  818. path: "/login" + "?orgId=" + orgId,
  819. });
  820. })
  821. .catch((response) => {
  822. const orgId = this.user.rootOrgId;
  823. if (response.status == 500) {
  824. this.$notify({
  825. showClose: true,
  826. message: response.data.desc,
  827. type: "error",
  828. });
  829. }
  830. this.USER_SIGNOUT();
  831. window.name = "";
  832. this.$router.replace({
  833. path: "/login" + "?orgId=" + orgId,
  834. });
  835. });
  836. return;
  837. },
  838. }
  839. );
  840. } else {
  841. if (error.response.data.code == 403) {
  842. this.$loading().close();
  843. return;
  844. }
  845. this.$emit("submitMark");
  846. this.loading = false;
  847. this.markTypeView = false;
  848. this.problemView = false;
  849. this.unusualType = "";
  850. }
  851. } else {
  852. this.$notify({
  853. message: "提交失败",
  854. type: "error",
  855. });
  856. this.$emit("submitMark");
  857. this.loading = false;
  858. this.markTypeView = false;
  859. this.problemView = false;
  860. this.unusualType = "";
  861. }
  862. }
  863. );
  864. } else {
  865. this.markedResultData.resultItems = this.resultItemsData;
  866. this.markedResultData.remark = remarkValue;
  867. this.$httpWithMsg
  868. .put(MARKING_API + "/markResults", this.markedResultData)
  869. .then(
  870. () => {
  871. this.saveMarkSign();
  872. this.$notify({
  873. message: "提交成功",
  874. type: "success",
  875. });
  876. this.$emit("submitMark");
  877. this.loading = false;
  878. this.markTypeView = false;
  879. this.problemView = false;
  880. this.unusualType = "";
  881. },
  882. (error) => {
  883. // 响应错误回调
  884. if (error.response.data.code == 403) {
  885. this.$loading().close();
  886. return;
  887. }
  888. this.$emit("submitMark");
  889. this.loading = false;
  890. this.markTypeView = false;
  891. this.problemView = false;
  892. this.unusualType = "";
  893. }
  894. );
  895. }
  896. },
  897. initKeyBoardMode() {
  898. if (this.resultItemsData[0]) {
  899. var itemId = this.resultItemsData[0].markItem.id;
  900. var order = this.resultItemsData[0].markItem.orders;
  901. var itemInput = "item" + itemId;
  902. this.$nextTick(() => {
  903. var firstInput = document.getElementById(itemInput);
  904. if (firstInput) {
  905. firstInput.focus();
  906. }
  907. });
  908. this.positionDiv(order);
  909. }
  910. },
  911. showTextarea() {
  912. if (this.textareaflag) {
  913. this.textareaflag = false;
  914. } else {
  915. this.textareaflag = true;
  916. }
  917. },
  918. accAdd(num1, num2) {
  919. let sq1, sq2, m;
  920. try {
  921. sq1 = num1.toString().split(".")[1].length;
  922. } catch (e) {
  923. sq1 = 0;
  924. }
  925. try {
  926. sq2 = num2.toString().split(".")[1].length;
  927. } catch (e) {
  928. sq2 = 0;
  929. }
  930. m = Math.pow(10, Math.max(sq1, sq2));
  931. return (num1 * m + num2 * m) / m;
  932. },
  933. itemScoreStep(scoreInterval) {
  934. if (this.scoreStep != null) {
  935. return this.scoreStep;
  936. }
  937. return scoreInterval;
  938. },
  939. },
  940. };
  941. </script>
  942. <style scoped>
  943. .scoreboard {
  944. width: 25%;
  945. min-height: 600px;
  946. }
  947. .itemScroll {
  948. overflow: hidden;
  949. height: 140px;
  950. margin-top: 15px;
  951. }
  952. .itemScroll:hover {
  953. overflow: auto;
  954. }
  955. .itemScroll::-webkit-scrollbar {
  956. /*滚动条整体样式*/
  957. width: 8px; /*高宽分别对应横竖滚动条的尺寸*/
  958. }
  959. .itemScroll::-webkit-scrollbar-thumb {
  960. box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  961. border-radius: 5px;
  962. background: rgba(0, 0, 0, 0.2);
  963. }
  964. .itemScroll::-webkit-scrollbar-track {
  965. /*滚动条里面轨道*/
  966. box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  967. border-radius: 0;
  968. background: rgba(0, 0, 0, 0.1);
  969. }
  970. .scoreScroll {
  971. overflow: auto;
  972. height: 100px;
  973. }
  974. .scoretitle {
  975. margin-right: 15px;
  976. margin-bottom: 15px;
  977. }
  978. li {
  979. list-style-type: none;
  980. }
  981. .actionbutton {
  982. width: 80px;
  983. height: 30px;
  984. }
  985. .second-board {
  986. color: white;
  987. margin-top: 20px;
  988. padding-bottom: 54px;
  989. border-bottom: 1px solid #ccc;
  990. }
  991. .clear {
  992. clear: both;
  993. }
  994. .board-margin {
  995. margin-left: 20px;
  996. }
  997. .sub-btn {
  998. margin-right: 15px;
  999. }
  1000. .active-btn {
  1001. background: rgb(85, 191, 255) !important;
  1002. border-color: rgb(85, 191, 255) !important;
  1003. }
  1004. .score-input {
  1005. border: 1px solid black;
  1006. border-top: 0;
  1007. border-left: 0;
  1008. border-right: 0;
  1009. box-sizing: border-box;
  1010. color: rgb(77, 124, 196);
  1011. font-size: 15px;
  1012. height: 30px;
  1013. width: 40px;
  1014. padding: 2px 10px;
  1015. transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  1016. outline: none;
  1017. text-align: center;
  1018. }
  1019. .el-switch__label {
  1020. position: absolute;
  1021. left: 0;
  1022. top: 0;
  1023. z-index: 2;
  1024. }
  1025. .button-border.button-small {
  1026. line-height: 26px;
  1027. }
  1028. .button-small {
  1029. font-size: 12px;
  1030. }
  1031. .button-border {
  1032. border-width: 2px;
  1033. border-style: solid;
  1034. }
  1035. .button-box {
  1036. padding: 0 !important;
  1037. border-radius: 10px;
  1038. }
  1039. .button-primary {
  1040. border-color: #1b9af7;
  1041. }
  1042. .button {
  1043. font-weight: 300;
  1044. text-decoration: none;
  1045. text-align: center;
  1046. margin: 0;
  1047. display: inline-block;
  1048. outline: none;
  1049. }
  1050. .pull-left {
  1051. float: left;
  1052. }
  1053. .pull-right {
  1054. float: right;
  1055. }
  1056. .scorebutton {
  1057. width: 40px;
  1058. height: 40px;
  1059. cursor: pointer;
  1060. color: rgb(77, 124, 196);
  1061. border-radius: 15px;
  1062. font-weight: 600;
  1063. border: 1px solid rgb(77, 124, 196);
  1064. text-align: center;
  1065. }
  1066. .scorebutton:hover {
  1067. background: rgb(85, 191, 255);
  1068. color: white;
  1069. border-color: rgb(85, 191, 255);
  1070. }
  1071. .titlebutton {
  1072. border-radius: 15px;
  1073. cursor: pointer;
  1074. }
  1075. .titlebutton:hover {
  1076. background: yellow;
  1077. }
  1078. .title-font {
  1079. font-size: 14px;
  1080. font-weight: 800;
  1081. }
  1082. .first-board {
  1083. margin-top: 20px;
  1084. height: 50px;
  1085. border-bottom: 1px solid #ccc;
  1086. }
  1087. .board-title {
  1088. height: 34px;
  1089. width: 80px;
  1090. background: rgb(255, 109, 109);
  1091. border: 2px solid rgb(255, 109, 109);
  1092. text-align: center;
  1093. padding-top: 20px;
  1094. font-weight: 600;
  1095. border-top-left-radius: 15px;
  1096. border-bottom-left-radius: 15px;
  1097. float: left;
  1098. font-size: 24px;
  1099. line-height: 0;
  1100. }
  1101. .board-score {
  1102. float: left;
  1103. height: 34px;
  1104. border: 2px solid rgb(255, 109, 109);
  1105. text-align: center;
  1106. padding-top: 20px;
  1107. padding-right: 10px;
  1108. font-weight: 600;
  1109. color: rgb(255, 109, 109);
  1110. border-top-right-radius: 15px;
  1111. border-bottom-right-radius: 15px;
  1112. font-size: 20px;
  1113. line-height: 0;
  1114. }
  1115. .total-all-score-title {
  1116. color: black;
  1117. margin-left: 10px;
  1118. float: left;
  1119. font-weight: 600;
  1120. line-height: 3;
  1121. }
  1122. .total-all-score {
  1123. color: red;
  1124. margin-left: 10px;
  1125. font-weight: 600;
  1126. line-height: 3;
  1127. float: left;
  1128. }
  1129. .title-board {
  1130. margin-top: 20px;
  1131. }
  1132. .title-item-top {
  1133. color: white;
  1134. width: 50px;
  1135. height: 25px;
  1136. border: 1px solid rgb(77, 124, 196);
  1137. text-align: center;
  1138. line-height: 2;
  1139. font-size: 12px;
  1140. border-top-left-radius: 15px;
  1141. border-top-right-radius: 15px;
  1142. background: rgb(77, 124, 196);
  1143. border-bottom: 0px;
  1144. }
  1145. .title-item-bottom {
  1146. width: 50px;
  1147. height: 30px;
  1148. border: 1px solid rgb(77, 124, 196);
  1149. text-align: center;
  1150. font-size: 12px;
  1151. line-height: 2.5;
  1152. border-bottom-left-radius: 15px;
  1153. border-bottom-right-radius: 15px;
  1154. border-top: 0px;
  1155. font-weight: 600;
  1156. color: rgb(77, 124, 196);
  1157. display: block;
  1158. }
  1159. .active-text {
  1160. color: rgb(85, 191, 255) !important;
  1161. border-color: rgb(85, 191, 255);
  1162. }
  1163. .score-item {
  1164. line-height: 2.5;
  1165. }
  1166. textarea {
  1167. background: rgb(245, 245, 245);
  1168. border-radius: 10px;
  1169. outline: none;
  1170. }
  1171. .step-board {
  1172. margin-top: 20px;
  1173. border-bottom: 1px solid #ccc;
  1174. }
  1175. .problem-button {
  1176. border-bottom: 1px solid #ccc;
  1177. margin-bottom: 15px;
  1178. margin-top: 20px;
  1179. }
  1180. .remark-step {
  1181. height: 100px;
  1182. margin-top: 15px;
  1183. }
  1184. .box-card {
  1185. width: 160px;
  1186. height: 60px;
  1187. border: 1px solid rgb(77, 124, 196);
  1188. border-radius: 10px;
  1189. }
  1190. .item-title {
  1191. background: rgb(77, 124, 196);
  1192. color: white;
  1193. height: 25px;
  1194. border-top-left-radius: 10px;
  1195. border-top-right-radius: 10px;
  1196. font-size: 12px;
  1197. text-align: center;
  1198. }
  1199. .item-score {
  1200. height: 35px;
  1201. color: rgb(77, 124, 196);
  1202. font-weight: bold;
  1203. font-size: 15px;
  1204. text-align: center;
  1205. }
  1206. .item-number {
  1207. width: 52px;
  1208. height: 22px;
  1209. text-align: center;
  1210. line-height: 1.5;
  1211. }
  1212. .item-number2 {
  1213. width: 40px;
  1214. height: 22px;
  1215. border: 1px solid rgb(77, 124, 196);
  1216. border-right-color: white;
  1217. border-left-color: white;
  1218. text-align: center;
  1219. line-height: 1.5;
  1220. }
  1221. .item-number3 {
  1222. width: 62px;
  1223. height: 22px;
  1224. text-align: center;
  1225. line-height: 1.5;
  1226. }
  1227. .btn {
  1228. margin-top: 20px;
  1229. margin-bottom: 10px;
  1230. padding-right: 1px;
  1231. }
  1232. .score-btn {
  1233. background: rgb(85, 191, 255);
  1234. color: white;
  1235. border-color: rgb(85, 191, 255);
  1236. }
  1237. .remark-board {
  1238. cursor: pointer;
  1239. }
  1240. .el-button {
  1241. outline: none;
  1242. }
  1243. </style>