Commit 079cb4cf3372babc7d21215a01eecb79fef45a2a

Authored by 梁保满
1 parent 86201e49

即时测导出

src/components/charts/lineChart.vue
@@ -9,6 +9,7 @@ export default { @@ -9,6 +9,7 @@ export default {
9 id: String, 9 id: String,
10 params: Array, 10 params: Array,
11 xAxis: Array, 11 xAxis: Array,
  12 + colors: Array
12 }, 13 },
13 watch: { 14 watch: {
14 params: { 15 params: {
@@ -25,7 +26,7 @@ export default { @@ -25,7 +26,7 @@ export default {
25 chart: null, 26 chart: null,
26 }; 27 };
27 }, 28 },
28 - created() {}, 29 + created() { },
29 mounted() { 30 mounted() {
30 this.initData(); 31 this.initData();
31 }, 32 },
@@ -33,7 +34,7 @@ export default { @@ -33,7 +34,7 @@ export default {
33 setOption() { 34 setOption() {
34 const that = this; 35 const that = this;
35 const options = { 36 const options = {
36 - color: this.colors || ["#4472c4", "#ed7d32", "#a5a5a5"], 37 + color: this.colors || ["#9772ff", "#79cd91", "#72b8ff"],
37 backgroundColor: "#fff", 38 backgroundColor: "#fff",
38 tooltip: { 39 tooltip: {
39 trigger: "item", 40 trigger: "item",
@@ -41,8 +42,10 @@ export default { @@ -41,8 +42,10 @@ export default {
41 }, 42 },
42 legend: { 43 legend: {
43 show: true, 44 show: true,
44 - bottom: 0,  
45 - itemHeight: 2, 45 + top: 0,
  46 + right: 20,
  47 + itemHeight: 15,
  48 + icon: "circle"
46 }, 49 },
47 xAxis: { 50 xAxis: {
48 type: "category", 51 type: "category",
@@ -52,7 +55,7 @@ export default { @@ -52,7 +55,7 @@ export default {
52 show: false, 55 show: false,
53 }, 56 },
54 axisLabel: { 57 axisLabel: {
55 - color: "#666", 58 + color: "#333",
56 }, 59 },
57 }, 60 },
58 yAxis: { 61 yAxis: {
@@ -63,13 +66,16 @@ export default { @@ -63,13 +66,16 @@ export default {
63 }, 66 },
64 axisLabel: { 67 axisLabel: {
65 color: "#666", 68 color: "#666",
  69 + formatter: function (name) {
  70 + return name + "%"
  71 + },
66 }, 72 },
67 }, 73 },
68 grid: { 74 grid: {
69 - top:28,  
70 - left: "10%",  
71 - right: "10%",  
72 - bottom: 30, 75 + top: 36,
  76 + left: 20,
  77 + right: 20,
  78 + bottom: 20,
73 containLabel: true, 79 containLabel: true,
74 }, 80 },
75 series: that.params.map((item) => { 81 series: that.params.map((item) => {
@@ -77,9 +83,9 @@ export default { @@ -77,9 +83,9 @@ export default {
77 name: item.name, 83 name: item.name,
78 type: "line", 84 type: "line",
79 symbol: "circle", 85 symbol: "circle",
80 - symbolSize: "8", 86 + symbolSize: "6",
81 lineStyle: { 87 lineStyle: {
82 - width: 3, 88 + width: 1,
83 }, 89 },
84 data: item.value, 90 data: item.value,
85 }; 91 };
src/components/charts/radarChart.vue
@@ -24,45 +24,62 @@ export default { @@ -24,45 +24,62 @@ export default {
24 chart: null, 24 chart: null,
25 }; 25 };
26 }, 26 },
27 - created() {}, 27 + created() { },
28 mounted() { 28 mounted() {
29 this.initData(); 29 this.initData();
30 }, 30 },
31 methods: { 31 methods: {
32 setOption() { 32 setOption() {
  33 + let that = this
33 const option = { 34 const option = {
34 - color: this.colors || ["#4472c4", "#ed7d32", "#a5a5a5"], 35 + color: that.colors || ["#4472c4", "#ed7d32", "#a5a5a5"],
35 backgroundColor: "#fff", 36 backgroundColor: "#fff",
36 tooltip: { 37 tooltip: {
37 trigger: "item", 38 trigger: "item",
38 confine: true, 39 confine: true,
  40 + formatter: function (param) {
  41 + let marker = param.marker
  42 + let oHtml = `<p>${marker}${param.name}</p>`
  43 + param.value.map((item, index) => {
  44 + oHtml += `<p>${that.params.indicator[index].name}:${item}</p>`
  45 + })
  46 + return oHtml
  47 + }
39 }, 48 },
40 legend: { 49 legend: {
41 - show:true,  
42 - bottom:0,  
43 - itemHeight:2 50 + show: true,
  51 + top: 0,
  52 + right: 20,
  53 + itemHeight: 15,
  54 + icon: "circle"
44 }, 55 },
  56 +
45 radar: { 57 radar: {
46 - indicator: [...this.params.indicator], 58 + indicator: [...that.params.indicator],
47 splitNumber: 5, 59 splitNumber: 5,
48 - center:['50%', '48%'],  
49 - radius:"70%", 60 + center: ['50%', '48%'],
  61 + radius: "80%",
50 shape: "polygon", 62 shape: "polygon",
51 - nameGap:10,  
52 - axisLine:{  
53 - show:false 63 + nameGap: 6,
  64 + axisLine: {
  65 + show: false
54 }, 66 },
55 - splitLine:{ 67 + splitLine: {
56 lineStyle: { 68 lineStyle: {
57 width: 0.5, 69 width: 0.5,
58 - color:'#e2e2e2' 70 + color: '#e2e2e2'
59 }, 71 },
60 }, 72 },
61 - splitArea:{  
62 - areaStyle:{  
63 - color:['rgba(250,250,250,0)','rgba(200,200,200,0)'] 73 + splitArea: {
  74 + areaStyle: {
  75 + color: ['rgba(250,250,250,0)', 'rgba(200,200,200,0)']
64 } 76 }
65 - } 77 + },
  78 + // axisLabel: {
  79 + // show: false,
  80 + // hideOverlap: true,
  81 + // formatter: '{value}%'
  82 + // },
66 }, 83 },
67 series: [ 84 series: [
68 { 85 {
@@ -74,7 +91,7 @@ export default { @@ -74,7 +91,7 @@ export default {
74 areaStyle: { 91 areaStyle: {
75 color: "transparent", 92 color: "transparent",
76 }, 93 },
77 - data: this.params.num, 94 + data: that.params.seriesData,
78 }, 95 },
79 ], 96 ],
80 }; 97 };
src/mock/index.js
@@ -35,7 +35,7 @@ Mock.mock( @@ -35,7 +35,7 @@ Mock.mock(
35 "answerOptions": "A,B,C,D", 35 "answerOptions": "A,B,C,D",
36 "correctAnswer|1": ["A", "B", "C", "D"], 36 "correctAnswer|1": ["A", "B", "C", "D"],
37 "screenshot": "./1.html", 37 "screenshot": "./1.html",
38 - "knowledge":"数与式#有理数#正数和负数,数与式#有理数#有理数" 38 + "knowledge": "数与式#有理数#正数和负数,数与式#有理数#有理数"
39 }, 39 },
40 { 40 {
41 "questionType": 2, 41 "questionType": 2,
@@ -45,7 +45,7 @@ Mock.mock( @@ -45,7 +45,7 @@ Mock.mock(
45 "answerOptions": "A,B,C,D", 45 "answerOptions": "A,B,C,D",
46 "correctAnswer|1": ["A", "B", "C", "D"], 46 "correctAnswer|1": ["A", "B", "C", "D"],
47 "screenshot": "./1.html", 47 "screenshot": "./1.html",
48 - "knowledge":"数与式#有理数#正数和负数" 48 + "knowledge": "数与式#有理数#正数和负数"
49 }, 49 },
50 { 50 {
51 "questionType": 2, 51 "questionType": 2,
@@ -208,4 +208,503 @@ Mock.mock( @@ -208,4 +208,503 @@ Mock.mock(
208 ] 208 ]
209 } 209 }
210 } 210 }
  211 +)
  212 +
  213 +Mock.mock(
  214 + "/api_html/teaching/examReportList", {
  215 + info: "success",
  216 + status: 0,
  217 + data: {
  218 + "list|2": [
  219 + {
  220 + "id": "@id",
  221 + subjectName: '语文',
  222 + className: '2班',
  223 + classId: "3215",
  224 + "title": "@cTitle",
  225 + "score|80-100": 85,
  226 + "answeredNum|45-50": 48,
  227 + classPersonNum: 50,
  228 + "examStartTime": '@date',
  229 + answerNum: 0,
  230 + recordStatus: 2,
  231 + classList: [{
  232 + classId: "@id",
  233 + className: "@cname",
  234 + }, {
  235 + classId: "@id",
  236 + className: "@cname",
  237 + }]
  238 + },
  239 + {
  240 + "id": "@id",
  241 + subjectName: '数学',
  242 + className: '2班',
  243 + classId: "3215",
  244 + "title": "@cTitle",
  245 + "score|80-100": 85,
  246 + "answeredNum|45-50": 48,
  247 + classPersonNum: 50,
  248 + "examStartTime": '@date',
  249 + answerNum: 0,
  250 + recordStatus: 2,
  251 + classList: [{
  252 + classId: "@id",
  253 + className: "@cname",
  254 + }, {
  255 + classId: "@id",
  256 + className: "@cname",
  257 + }]
  258 + },
  259 + {
  260 + "id": "@id",
  261 + subjectName: '英语',
  262 + className: '2班',
  263 + classId: "3215",
  264 + "title": "@cTitle",
  265 + "score|80-100": 85,
  266 + "answeredNum|45-50": 48,
  267 + classPersonNum: 50,
  268 + "examStartTime": '@date',
  269 + answerNum: 0,
  270 + recordStatus: 2,
  271 + classList: [{
  272 + classId: "@id",
  273 + className: "@cname",
  274 + }, {
  275 + classId: "@id",
  276 + className: "@cname",
  277 + }]
  278 + }
  279 + ]
  280 + }
  281 +}
  282 +)
  283 +Mock.mock(
  284 + "/api_html/teaching/phaseExamReport", {
  285 + info: "success",
  286 + status: 0,
  287 + data: {
  288 + "list|5": [
  289 + {
  290 + "studentId": "@id",
  291 + "studentName": '@cname',
  292 + "studentCode": '@id',
  293 + "shortNumber": "@id",
  294 + "title": "@cTitle",
  295 + "examList": [
  296 + {
  297 + "title": "结石分气在织织",
  298 + "score": 80,
  299 + "classRank|+1": 1,
  300 + "participationRate|+1": 80,
  301 + "correctRate|+1": 82,
  302 + "answerCorrectRate|+1": 85,
  303 + },
  304 + {
  305 + "title": "第业适声",
  306 + "score": 81,
  307 + "classRank|+1": 1,
  308 + "participationRate|+1": 81,
  309 + "correctRate|+1": 88,
  310 + "answerCorrectRate|+1": 90,
  311 + },
  312 + {
  313 + "title": "把住六",
  314 + "score": 82,
  315 + "classRank|+1": 1,
  316 + "participationRate|+1": 82,
  317 + "correctRate|+1": 91,
  318 + "answerCorrectRate|+1": 95,
  319 + },
  320 + {
  321 + "title": "取严酸百列县",
  322 + "score": 83,
  323 + "classRank|+1": 1,
  324 + "participationRate|+1": 85,
  325 + "correctRate|+1": 90,
  326 + "answerCorrectRate|+1": 93,
  327 + },
  328 + {
  329 + "title": "三原上光",
  330 + "score": 84,
  331 + "classRank|+1": 1,
  332 + "participationRate|+1": 83,
  333 + "correctRate|+1": 93,
  334 + "answerCorrectRate|+1": 96,
  335 + }
  336 + ]
  337 + }
  338 + ]
  339 + }
  340 +}
  341 +)
  342 +Mock.mock(
  343 + "/api_html/teaching/examMultiClassReport", {
  344 + info: "success",
  345 + status: 0,
  346 + data: {
  347 + "classes": [],
  348 + "students": [],
  349 + }
  350 +}
  351 +)
  352 +Mock.mock(
  353 + "/api_html/teaching/listStudentsAndQuestions", {
  354 + info: "success",
  355 + status: 0,
  356 + data: {
  357 + "students": [{
  358 + "studentId": "@id",
  359 + "studentName": "@cname",
  360 + "questionList": [
  361 + {
  362 + "examQuestionId|+1": 0,
  363 + "questionId|+1": 1,
  364 + "questionTitle": "@cname",
  365 + "questionType|1-4": 1,
  366 + "score|1-2": 1,
  367 + "subQuestions": [
  368 + {
  369 + id: 1,
  370 + "questionType": 2,
  371 + "score": 1,
  372 + },
  373 + {
  374 + id: 2,
  375 + "questionType": 2,
  376 + "score": 2,
  377 + },
  378 + {
  379 + id: 3,
  380 + "questionType": 2,
  381 + "score": 1,
  382 + },
  383 + {
  384 + id: 4,
  385 + "questionType": 2,
  386 + "score": 1,
  387 + },
  388 + {
  389 + id: 5,
  390 + "questionType": 2,
  391 + "score": 1,
  392 + },
  393 + {
  394 + id: 6,
  395 + "questionType": 3,
  396 + "score": 1,
  397 + },
  398 + ]
  399 + },
  400 + {
  401 + "examQuestionId|+1": 0,
  402 + "questionId|+1": 1,
  403 + "questionTitle": "@cname",
  404 + "questionType|1-4": 1,
  405 + "score|1-2": 1,
  406 + "subQuestions": [
  407 + {
  408 + id: 7,
  409 + "questionType": 2,
  410 + "score": 2,
  411 + },
  412 + {
  413 + id: 8,
  414 + "questionType": 2,
  415 + "score": 3,
  416 + },
  417 + {
  418 + id: 9,
  419 + "questionType": 2,
  420 + "score": 1,
  421 + },
  422 + {
  423 + id: 10,
  424 + "questionType": 2,
  425 + "score": 1,
  426 + },
  427 + {
  428 + id: 11,
  429 + "questionType": 2,
  430 + "score": 1,
  431 + },
  432 + {
  433 + id: 12,
  434 + "questionType": 3,
  435 + "score": 1,
  436 + },
  437 + {
  438 + id: 13,
  439 + "questionType": 2,
  440 + "score": 1,
  441 + },
  442 + {
  443 + id: 14,
  444 + "questionType": 2,
  445 + "score": 1,
  446 + },
  447 + {
  448 + id: 15,
  449 + "questionType": 2,
  450 + "score": 1,
  451 + },
  452 + {
  453 + id: 16,
  454 + "questionType": 2,
  455 + "score": 1,
  456 + }
  457 + ]
  458 + },
  459 + ]
  460 + }, {
  461 + "studentId": "@id",
  462 + "studentName": "@cname",
  463 + "questionList": [
  464 + {
  465 + "examQuestionId|+1": 0,
  466 + "questionId|+1": 1,
  467 + "questionTitle": "@cname",
  468 + "questionType|1-4": 1,
  469 + "score|1-2": 1,
  470 + "subQuestions": [
  471 + {
  472 + id: 1,
  473 + "questionType": 2,
  474 + "score": 1,
  475 + },
  476 + {
  477 + id: 2,
  478 + "questionType": 2,
  479 + "score": 2,
  480 + },
  481 + {
  482 + id: 3,
  483 + "questionType": 2,
  484 + "score": 1,
  485 + },
  486 + {
  487 + id: 4,
  488 + "questionType": 2,
  489 + "score": 1,
  490 + },
  491 + {
  492 + id: 5,
  493 + "questionType": 2,
  494 + "score": 1,
  495 + },
  496 + {
  497 + id: 6,
  498 + "questionType": 3,
  499 + "score": 1,
  500 + },
  501 + ]
  502 + },
  503 + {
  504 + "examQuestionId|+1": 0,
  505 + "questionId|+1": 1,
  506 + "questionTitle": "@cname",
  507 + "questionType|1-4": 1,
  508 + "score|1-2": 1,
  509 + "subQuestions": [
  510 + {
  511 + id: 7,
  512 + "questionType": 2,
  513 + "score": 2,
  514 + },
  515 + {
  516 + id: 8,
  517 + "questionType": 2,
  518 + "score": 3,
  519 + },
  520 + {
  521 + id: 9,
  522 + "questionType": 2,
  523 + "score": 1,
  524 + },
  525 + {
  526 + id: 10,
  527 + "questionType": 2,
  528 + "score": 1,
  529 + },
  530 + {
  531 + id: 11,
  532 + "questionType": 2,
  533 + "score": 1,
  534 + },
  535 + {
  536 + id: 12,
  537 + "questionType": 3,
  538 + "score": 1,
  539 + },
  540 + {
  541 + id: 13,
  542 + "questionType": 2,
  543 + "score": 1,
  544 + },
  545 + {
  546 + id: 14,
  547 + "questionType": 2,
  548 + "score": 1,
  549 + },
  550 + {
  551 + id: 15,
  552 + "questionType": 2,
  553 + "score": 1,
  554 + },
  555 + {
  556 + id: 16,
  557 + "questionType": 2,
  558 + "score": 1,
  559 + }
  560 + ]
  561 + },
  562 + ]
  563 + }, {
  564 + "studentId": "@id",
  565 + "studentName": "@cname",
  566 + "questionList": [
  567 + {
  568 + "examQuestionId|+1": 0,
  569 + "questionId|+1": 1,
  570 + "questionTitle": "@cname",
  571 + "questionType|1-4": 1,
  572 + "score|1-2": 1,
  573 + "subQuestions": [
  574 + {
  575 + id: 1,
  576 + "questionType": 2,
  577 + "score": 1,
  578 + },
  579 + {
  580 + id: 2,
  581 + "questionType": 2,
  582 + "score": 2,
  583 + },
  584 + {
  585 + id: 3,
  586 + "questionType": 2,
  587 + "score": 1,
  588 + },
  589 + {
  590 + id: 4,
  591 + "questionType": 2,
  592 + "score": 1,
  593 + },
  594 + {
  595 + id: 5,
  596 + "questionType": 2,
  597 + "score": 1,
  598 + },
  599 + {
  600 + id: 6,
  601 + "questionType": 3,
  602 + "score": 1,
  603 + },
  604 + ]
  605 + },
  606 + {
  607 + "examQuestionId|+1": 0,
  608 + "questionId|+1": 1,
  609 + "questionTitle": "@cname",
  610 + "questionType|1-4": 1,
  611 + "score|1-2": 1,
  612 + "subQuestions": [
  613 + {
  614 + id: 7,
  615 + "questionType": 2,
  616 + "score": 2,
  617 + },
  618 + {
  619 + id: 8,
  620 + "questionType": 2,
  621 + "score": 3,
  622 + },
  623 + {
  624 + id: 9,
  625 + "questionType": 2,
  626 + "score": 1,
  627 + },
  628 + {
  629 + id: 10,
  630 + "questionType": 2,
  631 + "score": 1,
  632 + },
  633 + {
  634 + id: 11,
  635 + "questionType": 2,
  636 + "score": 1,
  637 + },
  638 + {
  639 + id: 12,
  640 + "questionType": 3,
  641 + "score": 1,
  642 + },
  643 + {
  644 + id: 13,
  645 + "questionType": 2,
  646 + "score": 1,
  647 + },
  648 + {
  649 + id: 14,
  650 + "questionType": 2,
  651 + "score": 1,
  652 + },
  653 + {
  654 + id: 15,
  655 + "questionType": 2,
  656 + "score": 1,
  657 + },
  658 + {
  659 + id: 16,
  660 + "questionType": 2,
  661 + "score": 1,
  662 + }
  663 + ]
  664 + },
  665 + ]
  666 + }],
  667 + }
  668 +}
  669 +)
  670 +Mock.mock(
  671 + "/api_html/class/manager/phaseExamReport", {
  672 + info: "success",
  673 + status: 0,
  674 + data: {
  675 + "list": [{
  676 + "studentId": "@id",
  677 + "studentName": "@cname",
  678 + "dataList": [
  679 + {
  680 + "subjectName": "数学",
  681 + "examCount": '5',
  682 + "participationCount": '5',
  683 + "classRank": '1',
  684 + "score": '100',
  685 + "participationRate":'88',
  686 + "correctRate":'90',
  687 + },
  688 + {
  689 + "subjectName": "英语",
  690 + "examCount": '5',
  691 + "participationCount": '5',
  692 + "classRank": '2',
  693 + "score": '100',
  694 + "participationRate":'70',
  695 + "correctRate":'76',
  696 + },
  697 + {
  698 + "subjectName": "语文",
  699 + "examCount": '5',
  700 + "participationCount": '5',
  701 + "classRank": '2',
  702 + "score": '100',
  703 + "participationRate":'99',
  704 + "correctRate":'100',
  705 + },
  706 + ]
  707 + }],
  708 + }
  709 +}
211 ) 710 )
212 \ No newline at end of file 711 \ No newline at end of file
src/router/index.js
@@ -22,6 +22,7 @@ const AskList = () =&gt; import(&quot;@/views/basic/ask/list&quot;) @@ -22,6 +22,7 @@ const AskList = () =&gt; import(&quot;@/views/basic/ask/list&quot;)
22 const AskAnalysis = () => import("@/views/basic/ask/analysis") 22 const AskAnalysis = () => import("@/views/basic/ask/analysis")
23 const AskArchiving = () => import("@/views/basic/ask/archiving") 23 const AskArchiving = () => import("@/views/basic/ask/archiving")
24 const Test = () => import("@/views/basic/test/index") 24 const Test = () => import("@/views/basic/test/index")
  25 +const TestList = () => import("@/views/basic/test/list")
25 const TestAnalysis = () => import("@/views/basic/test/analysis") 26 const TestAnalysis = () => import("@/views/basic/test/analysis")
26 const TestArchiving = () => import("@/views/basic/test/archiving") 27 const TestArchiving = () => import("@/views/basic/test/archiving")
27 const DataSync = () => import("@/views/basic/dataSync/index") 28 const DataSync = () => import("@/views/basic/dataSync/index")
@@ -214,9 +215,6 @@ let addrouters = [ @@ -214,9 +215,6 @@ let addrouters = [
214 iconCls: "fa fa-bar-chart", // 图标样式class 215 iconCls: "fa fa-bar-chart", // 图标样式class
215 name: "随堂问报表", 216 name: "随堂问报表",
216 component: Ask, 217 component: Ask,
217 - meta: {  
218 - keepAlive: true,  
219 - },  
220 children: [] 218 children: []
221 219
222 }, 220 },
@@ -260,18 +258,23 @@ let addrouters = [ @@ -260,18 +258,23 @@ let addrouters = [
260 iconCls: "fa fa-pie-chart", // 图标样式class 258 iconCls: "fa fa-pie-chart", // 图标样式class
261 name: "", 259 name: "",
262 component: Test, 260 component: Test,
263 - meta: {  
264 - keepAlive: true,  
265 - },  
266 children: [] 261 children: []
267 }, 262 },
268 { 263 {
269 - path: "/testAnalysis",  
270 - iconCls: "", // 图标样式class  
271 - name: "即时测报表分析",  
272 - component: TestAnalysis,  
273 - parent: "test",  
274 - children: [] 264 + path: "/testList",
  265 + name: "",
  266 + component: TestList,
  267 +
  268 + children: [
  269 + {
  270 + path: "/testAnalysis",
  271 + iconCls: "", // 图标样式class
  272 + name: "即时测报表分析",
  273 + component: TestAnalysis,
  274 + parent: "test",
  275 + children: []
  276 + },
  277 + ]
275 }, 278 },
276 { 279 {
277 path: "/testArchiving", 280 path: "/testArchiving",
src/views/basic/ask/index.vue
@@ -97,8 +97,8 @@ export default { @@ -97,8 +97,8 @@ export default {
97 97
98 methods: { 98 methods: {
99 handleCheckAllChange(val) { 99 handleCheckAllChange(val) {
  100 + this.isIndeterminate = false;
100 this.query.subjectNames = val ? this.subjectList : []; 101 this.query.subjectNames = val ? this.subjectList : [];
101 - this.allSubject = false;  
102 }, 102 },
103 handleChecked(value) { 103 handleChecked(value) {
104 console.log(value) 104 console.log(value)
src/views/basic/test/analysis.vue
@@ -2,1013 +2,85 @@ @@ -2,1013 +2,85 @@
2 <div ref="main" class="page-container"> 2 <div ref="main" class="page-container">
3 <back-box> 3 <back-box>
4 <template slot="title"> 4 <template slot="title">
5 - <span>单卷分析</span> 5 + <span>{{ type == 1 ? '单卷测练报表' : type == 2 ? subject + "汇总报表" : type == 3 ? "多科汇总报表" :
  6 + `多班_${subjectName}_${title}_测练成绩对比分析` }}</span>
6 </template> 7 </template>
7 </back-box> 8 </back-box>
8 - <div class="tips" v-if="paperModifyLog.modifiedTime && !status">  
9 - <p class="tips-p">  
10 - <i class="fa fa-bell-o"></i>  
11 - {{  
12 - `${paperModifyLog.modifiedTime} ${paperModifyLog.realName}`  
13 - }}修改了答案,是否重新记分?  
14 - </p>  
15 - <div class="btn-box">  
16 - <el-button type="danger" round @click="_ReScore" size="mini"  
17 - >重新计分</el-button  
18 - >  
19 - <el-button  
20 - type="danger"  
21 - round  
22 - plain  
23 - size="mini"  
24 - @click="paperModifyLog.modifiedTime = ''"  
25 - >暂时不计</el-button  
26 - >  
27 - </div>  
28 - </div>  
29 - <div class="page-content">  
30 - <div class="content-header">  
31 - <div class="tab-box">  
32 - <span  
33 - v-for="(item, index) in tabList"  
34 - :key="item"  
35 - class="tab-item"  
36 - :class="type == index ? 'active' : ''"  
37 - @click="setType(index)"  
38 - >{{ item }}</span  
39 - >  
40 - </div>  
41 - <el-button  
42 - v-if="!status"  
43 - class="setMinScore"  
44 - @click="diaMinScore = true"  
45 - round  
46 - size="small"  
47 - >设置低分值</el-button  
48 - >  
49 - </div>  
50 - <div id="print-content" class="table-box" v-loading="loading">  
51 - <el-table  
52 - :max-height="tableMaxHeight"  
53 - v-show="type == 0"  
54 - :data="tableData"  
55 - border  
56 - style="width: 100%"  
57 - >  
58 - <el-table-column  
59 - prop="questionIndex"  
60 - label="题号"  
61 - align="center"  
62 - fixed  
63 - width="60"  
64 - ></el-table-column>  
65 - <el-table-column  
66 - prop="questionType"  
67 - label="题型"  
68 - align="center"  
69 - fixed  
70 - width="100"  
71 - ><template slot-scope="scope">{{  
72 - setSubPro(scope.row.questionType)  
73 - }}</template></el-table-column  
74 - >  
75 - <el-table-column  
76 - prop="score"  
77 - width="100"  
78 - label="满分值"  
79 - sortable  
80 - align="center"  
81 - ></el-table-column>  
82 - <el-table-column  
83 - width="110"  
84 - prop="highestScore"  
85 - label="班最高分"  
86 - sortable  
87 - align="center"  
88 - ></el-table-column>  
89 - <el-table-column  
90 - width="110"  
91 - prop="lowestScore"  
92 - label="班最低分"  
93 - sortable  
94 - align="center"  
95 - ></el-table-column>  
96 - <el-table-column  
97 - width="110"  
98 - prop="avgScore"  
99 - label="班平均分"  
100 - sortable  
101 - align="center"  
102 - ></el-table-column>  
103 - <el-table-column  
104 - prop="classScoringRate"  
105 - width="120"  
106 - sortable  
107 - label="班级得分率"  
108 - align="center"  
109 - ><template slot-scope="scoped"  
110 - >{{ scoped.row.classScoringRate }}%</template  
111 - ></el-table-column  
112 - >  
113 - <el-table-column prop="correctAnswer" label="答案" align="center"  
114 - ><template slot-scope="scoped">{{  
115 - scoped.row.correctAnswer == 1  
116 - ? "✓"  
117 - : scoped.row.correctAnswer == 2  
118 - ? "✗"  
119 - : scoped.row.correctAnswer  
120 - }}</template>  
121 - </el-table-column>  
122 - <el-table-column  
123 - v-for="(item, index) in optionsList"  
124 - :key="index"  
125 - :label="item.title"  
126 - :prop="'count' + index"  
127 - align="center"  
128 - width="120"  
129 - ><template slot-scope="scope"  
130 - ><p class="persent">  
131 - {{  
132 - scope.row.questionType == "5"  
133 - ? ""  
134 - : scope.row["option" + index]  
135 - ? `${scope.row["option" + index]}(${  
136 - scope.row["persent" + index]  
137 - })`  
138 - : ""  
139 - }}  
140 - </p></template  
141 - >  
142 - </el-table-column>  
143 - </el-table>  
144 - <div id="print-table">  
145 - <table class="hide">  
146 - <thead>  
147 - <tr>  
148 - <th>题号</th>  
149 - <th>题型</th>  
150 - <th>满分值</th>  
151 - <th>班最高分</th>  
152 - <th>班最低分</th>  
153 - <th>班平均分</th>  
154 - <th>班级得分率</th>  
155 - <th>答案</th>  
156 - <th>选项1</th>  
157 - <th>选项2</th>  
158 - <th>选项3</th>  
159 - <th>选项4</th>  
160 - <th>未答</th>  
161 - </tr>  
162 - </thead>  
163 - <tbody>  
164 - <tr v-for="(tr, index) in tableData">  
165 - <td width="60">{{ index + 1 }}</td>  
166 - <td width="100">{{ setSubPro(tr.questionType) }}</td>  
167 - <td width="100">{{ tr.sortable }}</td>  
168 - <td width="110">{{ tr.highestScore }}</td>  
169 - <td width="110">{{ tr.lowestScore }}</td>  
170 - <td width="110">{{ tr.avgScore }}</td>  
171 - <td width="120">{{ tr.classScoringRate }}%</td>  
172 - <td>  
173 - {{  
174 - tr.correctAnswer == 1  
175 - ? "✓"  
176 - : tr.correctAnswer == 2  
177 - ? "✗"  
178 - : tr.correctAnswer  
179 - }}  
180 - </td>  
181 - <td  
182 - v-for="(item, index) in optionsList"  
183 - :key="index"  
184 - width="120"  
185 - >  
186 - <p class="persent">  
187 - {{  
188 - tr.questionType == "5"  
189 - ? ""  
190 - : tr["option" + index]  
191 - ? `${tr["option" + index]}(${tr["persent" + index]})`  
192 - : ""  
193 - }}  
194 - </p>  
195 - </td>  
196 - </tr>  
197 - </tbody>  
198 - </table>  
199 - <div class="hui-box" v-show="type == 0">  
200 - <span class="s-txt">汇总</span>  
201 - <ul class="hui-ul">  
202 - <li class="hui-li">  
203 - <span class="hui-s s1">主观题</span>  
204 - <span class="hui-s s1">{{ examReport.subjectiveScore }}</span>  
205 - <span class="hui-s s2">{{  
206 - examReport.subjectiveHighestScore  
207 - }}</span>  
208 - <span class="hui-s s2">{{  
209 - examReport.subjectiveLowestScore  
210 - }}</span>  
211 - <span class="hui-s s2">{{  
212 - examReport.subjectiveAvgScore  
213 - }}</span>  
214 - <span class="hui-s s3"  
215 - >{{ examReport.subjectiveClassScoringRate }}%</span  
216 - >  
217 - </li>  
218 - <li class="hui-li">  
219 - <span class="hui-s s1">客观题</span>  
220 - <span class="hui-s s1">{{ examReport.objectiveScore }}</span>  
221 - <span class="hui-s s2">{{  
222 - examReport.objectiveHighestScore  
223 - }}</span>  
224 - <span class="hui-s s2">{{  
225 - examReport.objectiveLowestScore  
226 - }}</span>  
227 - <span class="hui-s s2">{{ examReport.objectiveAvgScore }}</span>  
228 - <span class="hui-s s3"  
229 - >{{ examReport.objectiveClassScoringRate }}%</span  
230 - >  
231 - </li>  
232 - <li class="hui-li">  
233 - <span class="hui-s s1">整卷</span>  
234 - <span class="hui-s s1">{{ examReport.examPaperScore }}</span>  
235 - <span class="hui-s s2">{{ examReport.highestScore }}</span>  
236 - <span class="hui-s s2">{{ examReport.lowestScore }}</span>  
237 - <span class="hui-s s2">{{ examReport.avgScore }}</span>  
238 - <span class="hui-s s3">{{ examReport.classScoringRate }}%</span>  
239 - </li>  
240 - </ul>  
241 - </div>  
242 - </div>  
243 - <el-table  
244 - v-show="type == 1"  
245 - :max-height="tableMaxHeight"  
246 - :data="tableData2"  
247 - border  
248 - style="width: 100%"  
249 - :default-sort="{ prop: 'dadui', order: 'descending' }"  
250 - >  
251 - <el-table-column  
252 - prop="studentCode"  
253 - label="学号"  
254 - align="center"  
255 - fixed  
256 - ></el-table-column>  
257 - <el-table-column  
258 - prop="studentName"  
259 - label="姓名"  
260 - fixed  
261 - align="center"  
262 - ></el-table-column>  
263 - <el-table-column  
264 - prop="examScore"  
265 - label="总分"  
266 - sortable  
267 - align="center"  
268 - ></el-table-column>  
269 - <el-table-column  
270 - prop="scoringRate"  
271 - label="得分率"  
272 - sortable  
273 - align="center"  
274 - ><template slot-scope="scope"  
275 - >{{ scope.row.scoringRate }}%</template  
276 - ></el-table-column  
277 - >  
278 - <el-table-column  
279 - prop="classRank"  
280 - label="班名"  
281 - sortable  
282 - align="center"  
283 - ></el-table-column>  
284 - <el-table-column label="客观题" align="center">  
285 - <el-table-column  
286 - prop="objectiveExamScore"  
287 - label="得分"  
288 - align="center"  
289 - ></el-table-column>  
290 - <el-table-column  
291 - prop="objectiveScoringRate"  
292 - label="得分率"  
293 - align="center"  
294 - ><template slot-scope="scope"  
295 - >{{ scope.row.objectiveScoringRate }}%</template  
296 - ></el-table-column  
297 - >  
298 - </el-table-column>  
299 - <el-table-column label="主观题" align="center">  
300 - <el-table-column  
301 - prop="subjectiveExamScore"  
302 - label="得分"  
303 - align="center"  
304 - ></el-table-column>  
305 - <el-table-column  
306 - prop="subjectiveScoringRate"  
307 - label="得分率"  
308 - align="center"  
309 - ><template slot-scope="scope"  
310 - >{{ scope.row.subjectiveScoringRate }}%</template  
311 - ></el-table-column  
312 - >  
313 - </el-table-column>  
314 - </el-table>  
315 - <el-table  
316 - v-show="type == 2"  
317 - :max-height="tableMaxHeight"  
318 - :data="tableData2"  
319 - border  
320 - style="width: 100%"  
321 - :default-sort="{ prop: '', order: 'descending' }"  
322 - >  
323 - <el-table-column  
324 - prop="studentCode"  
325 - label="学号"  
326 - fixed  
327 - align="center"  
328 - width="120"  
329 - ></el-table-column>  
330 - <el-table-column  
331 - prop="studentName"  
332 - label="姓名"  
333 - fixed  
334 - align="center"  
335 - ></el-table-column>  
336 - <el-table-column  
337 - prop="examScore"  
338 - label="总分"  
339 - sortable  
340 - align="center"  
341 - ></el-table-column>  
342 - <el-table-column label="分数组成" align="center">  
343 - <el-table-column  
344 - prop="objectiveExamScore"  
345 - label="客观题分"  
346 - align="center"  
347 - ></el-table-column>  
348 - <el-table-column  
349 - prop="subjectiveExamScore"  
350 - label="主观题分"  
351 - align="center"  
352 - ></el-table-column>  
353 - </el-table-column>  
354 - <el-table-column  
355 - align="center"  
356 - v-for="(item, index) in questionList"  
357 - :key="index"  
358 - :label="'Q' + item.id"  
359 - :prop="'score' + item.id"  
360 - >  
361 - </el-table-column>  
362 - </el-table>  
363 - <el-table  
364 - :max-height="tableMaxHeight"  
365 - v-show="type == 3"  
366 - :data="tableData2"  
367 - border  
368 - style="width: 100%"  
369 - :default-sort="{ prop: '', order: 'descending' }"  
370 - >  
371 - <el-table-column  
372 - prop="studentCode"  
373 - label="学号"  
374 - fixed  
375 - align="center"  
376 - ></el-table-column>  
377 - <el-table-column  
378 - prop="studentName"  
379 - label="姓名"  
380 - fixed  
381 - align="center"  
382 - ></el-table-column>  
383 - <el-table-column  
384 - prop="className"  
385 - label="班级"  
386 - align="center"  
387 - ></el-table-column>  
388 - <el-table-column  
389 - prop="examScore"  
390 - label="总分"  
391 - sortable  
392 - align="center"  
393 - ></el-table-column>  
394 - <el-table-column  
395 - align="center"  
396 - v-for="(item, index) in questionList"  
397 - :key="index"  
398 - :label="'Q' + item.id"  
399 - >  
400 - <template slot-scope="scope">  
401 - <span v-if="tableData[index]?.questionType == 5">*</span>  
402 - <span  
403 - v-else-if="scope.row['answer' + item.id]"  
404 - :class="scope.row['isRight' + item.id] ? '' : 'error'"  
405 - >  
406 - {{ scope.row["answer" + item.id] }}  
407 - </span>  
408 - <span  
409 - v-else  
410 - :class="scope.row['questionType' + item.id] == 5 ? '' : 'error'"  
411 - >-</span  
412 - >  
413 - </template>  
414 - </el-table-column>  
415 - </el-table>  
416 - </div>  
417 - <div class="down">  
418 - <div>  
419 - <el-button  
420 - @click="exportData"  
421 - type="primary"  
422 - plain  
423 - round  
424 - icon="fa fa-cloud-download"  
425 - >导出报表</el-button  
426 - >  
427 - <el-button  
428 - v-if="!this.$store.getters.code"  
429 - @click="print"  
430 - type="primary"  
431 - plain  
432 - round  
433 - icon="el-icon-printer"  
434 - >打印</el-button  
435 - >  
436 - </div>  
437 - <div v-if="!status">  
438 - <el-button  
439 - v-if="examReport.subjectiveScore != 0"  
440 - @click="diaUp = true"  
441 - type="primary"  
442 - round  
443 - v-loading="exportLoading"  
444 - >导入主观题分数</el-button  
445 - >  
446 - <template v-if="role == 'ROLE_JIAOSHI'">  
447 - <el-button  
448 - @click="edit"  
449 - type="primary"  
450 - v-if="examReport.subjectiveScore != examReport.examPaperScore"  
451 - round  
452 - >查看题目</el-button  
453 - ></template  
454 - >  
455 - </div>  
456 - </div>  
457 - <el-dialog  
458 - :close-on-click-modal="false"  
459 - title="导入主观题分数"  
460 - :visible.sync="diaUp"  
461 - width="600"  
462 - >  
463 - <upload :url="url" :examId="id" @upSuccess="upSuccess">  
464 - <template slot="down">  
465 - <p class="down-txt">  
466 - 第一步:下载模板并编辑完成学生分数  
467 - <el-link type="danger" @click="downExcel">模板下载</el-link> 。  
468 - </p>  
469 - <p class="down-txt">第二步:上传完成编辑的模板文件并导入。</p>  
470 - </template>  
471 - </upload>  
472 - <div class="dialog-footer" slot="footer">  
473 - <el-button @click="diaUp = false">取 消</el-button>  
474 - </div>  
475 - </el-dialog>  
476 - <el-dialog  
477 - :close-on-click-modal="false"  
478 - title="低分区间设置"  
479 - :visible.sync="diaMinScore"  
480 - width="480px"  
481 - @closed="closeDiaMinScore"  
482 - >  
483 - <el-form>  
484 - <el-form-item label="低分设置模式:">  
485 - <el-select v-model="lowRange.type" @change="changeScore">  
486 - <el-option label="按分数设置" :value="0"></el-option>  
487 - <el-option label="按已考人数比例" :value="1"></el-option>  
488 - <el-option label="按分数比例设置(按题目)" :value="2"></el-option>  
489 - </el-select>  
490 - </el-form-item>  
491 - <el-form-item label="低分区间:">  
492 - <el-input  
493 - class="score-ipt"  
494 - type="number"  
495 - v-model="lowRange.range[0]"  
496 - :min="0"  
497 - :max="100"  
498 - @input="lowRange.range[1] > 100 ? (lowRange.range[1] = 100) : ''"  
499 - @keydown.native="keydownRange($event)"  
500 - ></el-input  
501 - >{{ lowRange.type != 0 ? "%" : "分" }}(含)  
502 - <el-input  
503 - class="score-ipt"  
504 - type="number"  
505 - v-model="lowRange.range[1]"  
506 - :min="0"  
507 - :max="100"  
508 - @input="lowRange.range[1] > 100 ? (lowRange.range[1] = 100) : ''"  
509 - @keydown.native="keydownRange($event)"  
510 - ></el-input  
511 - >{{ lowRange.type != 0 ? "%" : "分" }}(含)  
512 - </el-form-item>  
513 - </el-form>  
514 -  
515 - <div  
516 - class="dialog-footer"  
517 - slot="footer"  
518 - align="center"  
519 - v-loading="loadingTange"  
520 - >  
521 - <el-button type="danger" @click="_SavelowRange">保存</el-button>  
522 - <el-button @click="diaMinScore = false">取 消</el-button>  
523 - </div>  
524 - </el-dialog>  
525 - </div> 9 + <Test v-if="type == 1" :role="role" :id="id" :classId="classId" :subjectName="subjectName" :title="title" />
  10 + <MultipleTest v-else-if="type == 2" :role="role" :ids="ids" :classId="classId" :subjectName="subjectName" />
  11 + <MultipleSubTest v-else-if="type == 3" :role="role" :ids="ids" :classId="classId" :subjectName="subjectName" />
  12 + <Contrast v-else-if="type == 4" :role="role" :ids="ids" :subjectName="subjectName" :title="title" />
526 </div> 13 </div>
527 </template> 14 </template>
528 15
529 <script> 16 <script>
530 -import { downloadFile, tablePrint } from "@/utils"; 17 +import Test from "./components/test.vue"
  18 +import MultipleTest from "./components/multipleTest.vue"
  19 +import MultipleSubTest from "./components/multipleSubTest.vue"
  20 +import Contrast from "./components/contrast.vue"
531 export default { 21 export default {
  22 + components: {
  23 + Test,
  24 + MultipleTest,
  25 + MultipleSubTest,
  26 + Contrast
  27 + },
532 data() { 28 data() {
533 return { 29 return {
534 role: "", 30 role: "",
535 - status: 0,// 1:已归档试卷  
536 - tableMaxHeight: 600,  
537 - loading: false,  
538 - exportLoading: false,  
539 - diaUp: false,  
540 - url: "/api_html/teaching/importSubjectiveScore",  
541 id: "", 31 id: "",
542 - classId: "",  
543 - subjectName: "",  
544 - title: "",  
545 - score: "",  
546 - tabList: ["试题分析", "成绩排名", "小题分报表", "作答明细表"], 32 + ids: [],
547 type: 0, 33 type: 0,
548 - paperModifyLog: { //修改信息  
549 - realName: "",  
550 - modifiedTime: "",  
551 - },  
552 - examReport: {  
553 - subjectiveScore: 0,  
554 - subjectiveHighestScore: "",  
555 - subjectiveLowestScore: "",  
556 - subjectiveAvgScore: "",  
557 - subjectiveClassScoringRate: "",  
558 - objectiveScore: "",  
559 - objectiveHighestScore: "",  
560 - objectiveLowestScore: "",  
561 - objectiveAvgScore: "",  
562 - objectiveClassScoringRate: "",  
563 - examPaperScore: "",  
564 - highestScore: "",  
565 - lowestScore: "",  
566 - avgScore: "",  
567 - classScoringRate: "",  
568 - },  
569 - tableData: [],  
570 - optionsList: [],  
571 - tableData2: [],  
572 - questionList: [],  
573 - page: 1,  
574 - size: 20,  
575 - total: 0,  
576 - // 设置低分值  
577 - loadingTange: false,  
578 - diaMinScore: false,  
579 - lowRange: {  
580 - type: 0,  
581 - range: [60, 0],  
582 - },  
583 - defaultLowRange: {  
584 - type: 0,  
585 - range: [],  
586 - }, 34 + classId: "",
  35 + subjectName: '',
  36 + title: ''
587 }; 37 };
588 }, 38 },
589 created() { 39 created() {
590 this.role = 40 this.role =
591 this.$store.getters.info.showRole || 41 this.$store.getters.info.showRole ||
592 this.$store.getters.info.permissions[0].role; 42 this.$store.getters.info.permissions[0].role;
593 - this.id = this.$route.query.id;  
594 - this.status = this.$route.query.status ? this.$route.query.status : 0;  
595 - this.title = this.$route.query.title || ""; 43 + this.id = this.$route.query.id || "";
  44 + this.ids = this.$route.query.ids && this.$route.query.ids.split() || "";
  45 + this.type = this.$route.query.type
596 this.classId = this.$route.query.classId || ""; 46 this.classId = this.$route.query.classId || "";
597 - this.subjectName = this.$route.query.subjectName || "";  
598 - this._QueryData(); 47 + this.subjectName = this.$route.query.subjectName || ""
  48 + this.title = this.$route.query.title || ""
599 }, 49 },
600 methods: { 50 methods: {
601 - print() {  
602 - if (this.type == 0) {  
603 - tablePrint("print-table", this.title + this.tabList[this.type], true);  
604 - } else {  
605 - tablePrint("print-content", this.title + this.tabList[this.type]);  
606 - }  
607 - },  
608 - upSuccess(res) {  
609 - //导入成功  
610 - this.$message.success("导入成功");  
611 - this.diaUp = false;  
612 - this._QueryData();  
613 - },  
614 - setType(type) {  
615 - console.log(this.$refs.main.offsetHeight - 50);  
616 - this.tableMaxHeight = this.$refs.main.offsetHeight;  
617 - this.type = type;  
618 - },  
619 - setSubPro(type) {  
620 - let tit;  
621 - switch (type) {  
622 - case 2:  
623 - tit = "单选题";  
624 - break;  
625 - case 3:  
626 - tit = "多选题";  
627 - break;  
628 - case 4:  
629 - tit = "判断题";  
630 - break;  
631 - case 5:  
632 - tit = "主观题";  
633 - break;  
634 - }  
635 - return tit;  
636 - },  
637 - edit() {  
638 - this.$router.push({  
639 - path: "/examinationPaperEdit",  
640 - query: {  
641 - paperId: this.id,  
642 - title: this.title,  
643 - type: 2,  
644 - },  
645 - });  
646 - },  
647 - changePage(page) {  
648 - this.page = page;  
649 - this.examQuestionReport();  
650 - },  
651 - // 切换低分设置类型设置默认分值  
652 - changeScore() {  
653 - this.lowRange.range = [...this.defaultLowRange.range];  
654 - },  
655 - // 禁止输入负数  
656 - keydownRange(event) {  
657 - if (event.key == "-" || event.key == "e") {  
658 - event.returnValue = "";  
659 - }  
660 - },  
661 - // 关闭低分设置  
662 - closeDiaMinScore() {  
663 - this.lowRange.type = this.defaultLowRange.type;  
664 - this.lowRange.range = [...this.defaultLowRange.range];  
665 - },  
666 - // 保存低分设置  
667 - async _SavelowRange() {  
668 - if(this.lowRange.range[0].trim() == "" || this.lowRange.range[1].trim() == ""){  
669 - this.$message.warning("请补全低分设置!");  
670 - return  
671 - }  
672 - this.loadingTange = true;  
673 - let { data, status, info } = await this.$request.setLowRange({  
674 - classId: this.classId,  
675 - subjectName: this.subjectName,  
676 - ...this.lowRange,  
677 - });  
678 - this.loadingTange = false;  
679 - if (status === 0) {  
680 - this.$message.success(info);  
681 - this.diaMinScore = false;  
682 - this.examDetail();  
683 - } else {  
684 - this.$message.error(info);  
685 - }  
686 - },  
687 - async _QueryData() {  
688 - this.examDetail();  
689 - this.examStudentReport();  
690 - this.examQuestionReport();  
691 - },  
692 - async examDetail() {  
693 - //详情  
694 - this.loading = true;  
695 - let { data, info, status } = await this.$request.examDetail({  
696 - examId: this.id,  
697 - });  
698 - this.loading = false;  
699 - if (status === 0) {  
700 - if (data.paperModifyLog) {  
701 - this.paperModifyLog = { ...data?.paperModifyLog };  
702 - }  
703 - this.examReport = { ...data?.examReport };  
704 - this.defaultLowRange = data.lowRange || {  
705 - type: 1,  
706 - range: [60, 0],  
707 - };  
708 - this.lowRange.type = this.defaultLowRange.type;  
709 - this.lowRange.range = [...this.defaultLowRange.range];  
710 - } else {  
711 - this.$message.error(info);  
712 - }  
713 - },  
714 - async _ReScore() {  
715 - //重新记分  
716 - this.loading = true;  
717 - let { data, info, status } = await this.$request.reScore({  
718 - examId: this.id,  
719 - });  
720 - this.loading = false;  
721 - if (status === 0) {  
722 - this.$message.success(info);  
723 - this._QueryData();  
724 - this.paperModifyLog.modifiedTime = "";  
725 - this.paperModifyLog.realName = "";  
726 - } else {  
727 - this.$message.error(info);  
728 - }  
729 - },  
730 - async examStudentReport() {  
731 - //成绩排名-小题分-作答明细  
732 - this.loading = true;  
733 - let { data, info, status } = await this.$request.examStudentReport({  
734 - examId: this.id,  
735 - });  
736 - this.loading = false;  
737 - if (status === 0) {  
738 - let optionsList = [];  
739 - this.tableData2 = data?.list.map((item) => {  
740 - let params = {};  
741 -  
742 - const detail = JSON.parse(item.detail);  
743 - if (detail.length > optionsList.length) {  
744 - optionsList = [...detail];  
745 - }  
746 - detail.map((items, index) => {  
747 - params["que" + items.id] = items.id;  
748 - params["score" + items.id] = String(items.score).includes(".")  
749 - ? Number(items.score)  
750 - : items.score;  
751 - params["answer" + items.id] =  
752 - items.answer == 1 ? "✓" : items.answer == 2 ? "✗" : items.answer;  
753 - params["isRight" + items.id] = items.isRight;  
754 - params["questionType" + items.id] = items.questionType;  
755 - });  
756 - return {  
757 - ...item,  
758 - ...params,  
759 - };  
760 - });  
761 - console.log();  
762 - this.questionList = optionsList.sort((a, b) => {  
763 - return a.id - b.id;  
764 - });  
765 - } else {  
766 - this.$message.error(info);  
767 - }  
768 - },  
769 - async examQuestionReport() {  
770 - //试题分析  
771 - this.loading = true;  
772 - let { data, info, status } = await this.$request.examQuestionReport({  
773 - examId: this.id,  
774 - page: this.page,  
775 - // size: this.size,  
776 - size: 9999,  
777 - });  
778 - this.loading = false;  
779 - if (status === 0) {  
780 - let optionsList = [{}, {}, {}, {}, {}];  
781 - let tableData = data?.list.map((item) => {  
782 - let params = {};  
783 - const detail = JSON.parse(item.detail);  
784 - let lastOPtion = detail?.find((item) => {  
785 - return item.option == "未答";  
786 - });  
787 - let defaultArr = detail?.filter((item) => {  
788 - return item.option != "未答";  
789 - });  
790 51
791 - optionsList.map((items, index) => {  
792 - if (index != 4) {  
793 - params["count" + index] =  
794 - defaultArr[index]?.option != "未答"  
795 - ? defaultArr[index]?.count  
796 - : "";  
797 - params["persent" + index] =  
798 - defaultArr[index]?.option != "未答"  
799 - ? defaultArr[index]?.persent  
800 - : "";  
801 - params["option" + index] =  
802 - defaultArr[index]?.option != "未答"  
803 - ? defaultArr[index]?.option == 1  
804 - ? "✓"  
805 - : defaultArr[index]?.option == 2  
806 - ? "✗"  
807 - : defaultArr[index]?.option  
808 - : "";  
809 - items["title"] = "选项" + (index + 1);  
810 - } else {  
811 - items["title"] = "未答";  
812 - params["count" + index] = lastOPtion.count;  
813 - params["persent" + index] = lastOPtion.persent;  
814 - params["option" + index] = "?";  
815 - }  
816 - });  
817 - return {  
818 - ...item,  
819 - ...params,  
820 - };  
821 - });  
822 - this.tableData = tableData.sort((a, b) => {  
823 - return a.questionIndex - b.questionIndex;  
824 - });  
825 - this.optionsList = [...optionsList];  
826 - this.total = data.count;  
827 - this.setType(0);  
828 - } else {  
829 - this.$message.error(info);  
830 - }  
831 - },  
832 - //导出  
833 - async exportData() {  
834 - if (this.exportLoading == true) return;  
835 - this.exportLoading = true;  
836 - const data = await this.$request.exportExamReport({  
837 - examId: this.id,  
838 - });  
839 - this.exportLoading = false;  
840 - if (data) {  
841 - let blob = new Blob([data], {  
842 - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",  
843 - });  
844 - downloadFile(  
845 - this.status  
846 - ? "即时测-已归档单卷测练报表.xlsx"  
847 - : "即时测-单卷测练报表.xlsx",  
848 - blob  
849 - );  
850 - } else {  
851 - this.$message.error("下载失败");  
852 - }  
853 - },  
854 - async downExcel() {  
855 - let data = await this.$request.subjectiveScoreTemplate({  
856 - examId: this.id,  
857 - });  
858 - if (data && !data.code) {  
859 - let blob = new Blob([data], {  
860 - type: "application/vnd.ms-excel;charset=utf-8",  
861 - });  
862 - downloadFile(`主观题模版.xlsx`, blob);  
863 - } else {  
864 - this.$message.error(data.info);  
865 - }  
866 - },  
867 - }, 52 + }
868 }; 53 };
869 </script> 54 </script>
870 -<style>  
871 -div::-webkit-scrollbar {  
872 - width: 3px;  
873 - height: 10px;  
874 -}  
875 -div::-webkit-scrollbar-thumb {  
876 - border-radius: 10px;  
877 - background-color: #ccc;  
878 -}  
879 -</style>  
880 <style lang="scss" scoped> 55 <style lang="scss" scoped>
881 -.hide {  
882 - display: none;  
883 -}  
884 .page-container { 56 .page-container {
885 position: relative; 57 position: relative;
886 height: 100%; 58 height: 100%;
  59 +
887 .table-box { 60 .table-box {
888 min-height: 100%; 61 min-height: 100%;
889 } 62 }
  63 +
890 &.active { 64 &.active {
891 overflow: hidden; 65 overflow: hidden;
892 } 66 }
893 - .edit-dia {  
894 - position: absolute;  
895 - left: 0;  
896 - top: 0;  
897 - right: 0;  
898 - bottom: 0;  
899 - width: 100%;  
900 - height: calc(100vh - 70px);  
901 - background: #fff;  
902 - overflow-y: auto;  
903 - z-index: 10;  
904 - }  
905 -}  
906 -.persent {  
907 - white-space: nowrap; 67 +
  68 +
908 } 69 }
  70 +
909 .error { 71 .error {
910 color: #f30; 72 color: #f30;
911 } 73 }
  74 +
912 .page-content { 75 .page-content {
913 padding: 20px 20px 0; 76 padding: 20px 20px 0;
914 } 77 }
915 -.tips {  
916 - height: 48px;  
917 - box-sizing: border-box;  
918 - line-height: 48px;  
919 - padding: 0 16px;  
920 - border: 1px solid #fac7cc;  
921 - border-radius: 5px;  
922 - background-color: #ffebec;  
923 - font-size: 14px;  
924 - color: #fd9795;  
925 - margin: 10px 20px 0 20px;  
926 - display: flex;  
927 - &-p {  
928 - flex: 1;  
929 - }  
930 - .fa-bell-o {  
931 - font-size: 18px;  
932 - margin-right: 5px;  
933 - }  
934 -}  
935 -.tab-box {  
936 - width: 800px;  
937 - margin: 0 auto 12px;  
938 - background: #f8f8f8;  
939 - border-radius: 20px;  
940 - display: flex;  
941 - user-select: none;  
942 - .tab-item {  
943 - flex: 1;  
944 - height: 40px;  
945 - line-height: 40px;  
946 - text-align: center;  
947 - font-size: 16px;  
948 - color: #666;  
949 - font-weight: 500;  
950 - background: transparent;  
951 - border-radius: 20px;  
952 - cursor: pointer;  
953 - &.active {  
954 - background: #667ffd;  
955 - color: #fff;  
956 - }  
957 - }  
958 -} 78 +
  79 +
959 .down { 80 .down {
960 padding-top: 20px; 81 padding-top: 20px;
961 width: 100%; 82 width: 100%;
962 display: flex; 83 display: flex;
963 justify-content: space-between; 84 justify-content: space-between;
964 } 85 }
965 -.hui-box {  
966 - display: flex;  
967 - text-align: center;  
968 - .s-txt {  
969 - width: 61px;  
970 - line-height: 144px;  
971 - background: #e2e2e2;  
972 - font-size: 16px;  
973 - color: #fff;  
974 - font-weight: 700;  
975 - }  
976 - .hui-ul {  
977 - border-top: 1px solid #e2e2e2;  
978 - }  
979 - .hui-li {  
980 - display: flex;  
981 - .hui-s {  
982 - height: 48px;  
983 - line-height: 48px;  
984 - border-right: 1px solid #e2e2e2;  
985 - border-bottom: 1px solid #e2e2e2;  
986 - box-sizing: border-box;  
987 - }  
988 - .s1 {  
989 - width: 100px;  
990 - }  
991 - .s2 {  
992 - width: 110px;  
993 - }  
994 - .s3 {  
995 - width: 120px;  
996 - }  
997 - }  
998 -}  
999 -  
1000 -// 设置低分值  
1001 -.content-header {  
1002 - width: 100%;  
1003 - position: relative;  
1004 - .setMinScore {  
1005 - position: absolute;  
1006 - bottom: 0;  
1007 - right: 0px;  
1008 - }  
1009 -}  
1010 -.score-ipt {  
1011 - width: 80px;  
1012 - margin: 0 5px;  
1013 -}  
1014 </style> 86 </style>
1015 \ No newline at end of file 87 \ No newline at end of file
src/views/basic/test/components/test.vue
@@ -308,7 +308,11 @@ export default { @@ -308,7 +308,11 @@ export default {
308 range: [], 308 range: [],
309 }, 309 },
310 //答题录分 310 //答题录分
311 - diaScoreSet: false 311 + diaScoreSet: false,
  312 +
  313 + exportType: 1,
  314 + exportStudent: [],
  315 + multipleSelection: [],
312 }; 316 };
313 }, 317 },
314 created() { 318 created() {
@@ -563,8 +567,29 @@ export default { @@ -563,8 +567,29 @@ export default {
563 async exportData() { 567 async exportData() {
564 if (this.exportLoading == true) return; 568 if (this.exportLoading == true) return;
565 this.exportLoading = true; 569 this.exportLoading = true;
566 - const data = await this.$request.exportExamReport({ 570 + let studentIds = []
  571 + if (length) {
  572 + studentIds = this.exportStudent.slice(0, 10).map(item => {
  573 + return item.studentId
  574 + })
  575 + } else {
  576 + studentIds = this.multipleSelection.map(item => {
  577 + return item.studentId
  578 + })
  579 + }
  580 + let query = {};
  581 + if (studentIds.length == this.exportStudent.length) {
  582 + query.studentIds = []
  583 + } else if (studentIds.length > 0) {
  584 + query.studentIds = studentIds
  585 + }
  586 + const exportExamReport = this.role == "ROLE_PERSONAL" ?
  587 + this.$request.pExportExamReport
  588 + : this.$request.exportExamReport;
  589 +
  590 + const data = await exportExamReport({
567 examId: this.id, 591 examId: this.id,
  592 + ...query
568 }); 593 });
569 this.exportLoading = false; 594 this.exportLoading = false;
570 if (data) { 595 if (data) {
src/views/basic/test/contrast.vue deleted
1 -<template>  
2 - <div ref="main" class="page-container">  
3 - <back-box>  
4 - <template slot="title">  
5 - <span>多班_{{ subjectNames }}_{{ title }}_测练成绩对比分析</span>  
6 - </template>  
7 - </back-box>  
8 - <div class="page-content">  
9 - <div class="content-header">  
10 - <div class="tab-box">  
11 - <span  
12 - v-for="(item, index) in tabList"  
13 - :key="item"  
14 - class="tab-item"  
15 - :class="type == index ? 'active' : ''"  
16 - @click="setType(index)"  
17 - >{{ item }}</span  
18 - >  
19 - </div>  
20 - <el-button class="setMinScore" @click="openDia" round size="small"  
21 - >对比成绩等级设置</el-button  
22 - >  
23 - </div>  
24 - <div id="print-content" class="table-box" v-loading="loading">  
25 - <el-table  
26 - :max-height="tableMaxHeight"  
27 - v-show="type == 0"  
28 - :data="tableData"  
29 - border  
30 - style="width: 100%"  
31 - >  
32 - <el-table-column  
33 - type="index"  
34 - label="序号"  
35 - fixed  
36 - align="center"  
37 - width="60"  
38 - ></el-table-column>  
39 - <el-table-column  
40 - prop="className"  
41 - label="班级"  
42 - align="center"  
43 - fixed  
44 - ></el-table-column>  
45 - <el-table-column label="测验人数/班级人数" align="center" width="84">  
46 - <template slot-scope="scope">  
47 - <p v-for="(item, index) in scope.row.count.split('/')">  
48 - {{ item }}{{ index == 0 ? "/" : "" }}  
49 - </p>  
50 - </template>  
51 - </el-table-column>  
52 - <el-table-column  
53 - prop="percent"  
54 - label="参与度"  
55 - align="center"  
56 - ></el-table-column>  
57 - <el-table-column  
58 - prop="avg"  
59 - label="班平均分"  
60 - align="center"  
61 - ></el-table-column>  
62 - <el-table-column  
63 - prop="max"  
64 - label="班最高分"  
65 - sortable  
66 - align="center"  
67 - ></el-table-column>  
68 - <el-table-column  
69 - prop="min"  
70 - label="班最低分"  
71 - sortable  
72 - align="center"  
73 - ></el-table-column>  
74 -  
75 - <el-table-column  
76 - v-for="(item, index) in defaultLevels.levels"  
77 - :label="item[0] + '数(率)'"  
78 - align="center"  
79 - ><template slot-scope="scoped">  
80 - <p class="p1">{{ scoped.row.levels[index].people }}</p>  
81 - <p class="p1">({{ scoped.row.levels[index].percent }})</p>  
82 - </template></el-table-column  
83 - >  
84 - </el-table>  
85 - <el-table  
86 - v-show="type == 1"  
87 - :max-height="tableMaxHeight"  
88 - :data="tableData2"  
89 - border  
90 - style="width: 100%"  
91 - >  
92 - <el-table-column  
93 - prop="rank"  
94 - label="排名"  
95 - sortable  
96 - align="center"  
97 - ></el-table-column>  
98 - <el-table-column  
99 - prop="name"  
100 - label="姓名"  
101 - align="center"  
102 - ></el-table-column>  
103 - <el-table-column  
104 - prop="className"  
105 - label="班级"  
106 - align="center"  
107 - ></el-table-column>  
108 - <el-table-column  
109 - prop="score"  
110 - label="总分"  
111 - sortable  
112 - align="center"  
113 - ></el-table-column>  
114 - <el-table-column  
115 - prop="levelName"  
116 - label="成绩等级"  
117 - align="center"  
118 - ></el-table-column>  
119 - </el-table>  
120 - </div>  
121 - <div class="down">  
122 - <div>  
123 - <el-button  
124 - v-loading="exportLoading"  
125 - @click="exportData"  
126 - type="primary"  
127 - plain  
128 - round  
129 - icon="fa fa-cloud-download"  
130 - >导出报表</el-button  
131 - >  
132 - <el-button  
133 - v-if="!this.$store.getters.code"  
134 - @click="print"  
135 - type="primary"  
136 - plain  
137 - round  
138 - icon="el-icon-printer"  
139 - >打印</el-button  
140 - >  
141 - </div>  
142 - </div>  
143 -  
144 - <el-dialog  
145 - :close-on-click-modal="false"  
146 - title="等级设置"  
147 - :visible.sync="diaLogBox"  
148 - width="800px"  
149 - @closed="closeDia"  
150 - >  
151 - <el-form class="use-form">  
152 - <el-form-item class="use-form-item-box">  
153 - <el-form-item label="等级名称:" class="use-form-item">  
154 - <el-select  
155 - size="small"  
156 - v-model="fromData.type"  
157 - @change="changeType"  
158 - >  
159 - <el-option label="优良合格不合格" :value="0"></el-option>  
160 - <el-option label="ABCD" :value="1"></el-option>  
161 - <el-option label="自定义" :value="2"></el-option>  
162 - </el-select>  
163 - </el-form-item>  
164 - <el-form-item label="等级设置模式:" class="use-form-item">  
165 - <el-select size="small" v-model="fromData.levelType">  
166 - <el-option label="按分数比例" :value="0"></el-option>  
167 - <el-option label="按已考人数比例" :value="1"></el-option>  
168 - </el-select>  
169 - </el-form-item>  
170 - </el-form-item>  
171 - <el-form-item>  
172 - <div class="dia-tab-box">  
173 - <p class="dia-tab-tit">  
174 - <span class="item1">编号</span>  
175 - <span class="item2"><i>*</i>等级名称</span>  
176 - <span class="item3"><i>*</i>等级最高</span>  
177 - <span class="item3"><i>*</i>等级最低</span>  
178 - <span class="item"></span>  
179 - </p>  
180 - <div  
181 - class="dia-tab-item"  
182 - v-for="(item, index) in fromData.levels"  
183 - >  
184 - <span class="item1">{{ index + 1 }}</span>  
185 - <p class="item2">  
186 - <el-input  
187 - class="score-ipt"  
188 - v-model="item[0]"  
189 - :maxlength="12"  
190 - @keydown.native="keydownRange($event)"  
191 - ></el-input>  
192 - </p>  
193 - <p class="item3">  
194 - <el-input  
195 - class="score-ipt"  
196 - type="number"  
197 - v-model="item[1]"  
198 - :min="item[2]"  
199 - :max="index == 0 ? 100 : fromData.levels[index - 1][2]"  
200 - @keydown.native="keydownRange($event)"  
201 - ></el-input>  
202 - %  
203 - <template v-if="fromData.levelType == 0">  
204 - ({{ index != 0 ? "不含" : ""  
205 - }}{{  
206 - Number(((item[1] / 100) * examPaperScore).toFixed(1))  
207 - }}分)  
208 - </template>  
209 - <template v-else>{{ index != 0 ? "不含" : "" }}</template>  
210 - </p>  
211 - <p>~</p>  
212 - <p class="item3">  
213 - <el-input  
214 - class="score-ipt"  
215 - type="number"  
216 - v-model="item[2]"  
217 - :min="0"  
218 - :max="item[1]"  
219 - @keydown.native="keydownRange($event)"  
220 - ></el-input>  
221 - %  
222 - <template v-if="fromData.levelType == 0">  
223 - ({{  
224 - Number(((item[2] / 100) * examPaperScore).toFixed(1))  
225 - }}分)  
226 - </template>  
227 - </p>  
228 - <p class="item">  
229 - <el-link  
230 - type="danger"  
231 - :underline="false"  
232 - @click="fromData.levels.splice(index, 1)"  
233 - >删除</el-link  
234 - >  
235 - </p>  
236 - </div>  
237 - <div class="add">  
238 - <p @click="fromData.levels.push(['', '', ''])">  
239 - <el-button  
240 - size="mini"  
241 - icon="el-icon-plus"  
242 - circle  
243 - type="primary"  
244 - ></el-button  
245 - >添加一行  
246 - </p>  
247 - </div>  
248 - </div>  
249 - </el-form-item>  
250 - </el-form>  
251 -  
252 - <div class="dialog-footer" slot="footer" align="center">  
253 - <el-button type="danger" @click="savefrom">保存</el-button>  
254 - <el-button @click="diaLogBox = false">取 消</el-button>  
255 - </div>  
256 - </el-dialog>  
257 - </div>  
258 - </div>  
259 -</template>  
260 -  
261 -<script>  
262 -import { downloadFile, tablePrint } from "@/utils";  
263 -export default {  
264 - data() {  
265 - return {  
266 - ids: "",  
267 - title: "",  
268 - subjectNames: "",  
269 - tabList: ["班级对比情况", "学生成绩排名"],  
270 - type: 0,  
271 - loading: false,  
272 - exportLoading: false,  
273 - diaLogBox: false,  
274 - fromData: {  
275 - type: 0,  
276 - levelType: 0,  
277 - levels: [  
278 - ["优秀", 100, 90],  
279 - ["良好", 89.9, 70],  
280 - ["合格", 69.9, 60],  
281 - ["不合格", 59.9, 0],  
282 - ],  
283 - },  
284 - defaultLevels: {  
285 - levelType: 0,  
286 - levels: [],  
287 - },  
288 - tableMaxHeight: 600,  
289 - tableData: [],  
290 - tableData2: [],  
291 - examPaperScore: 100, //卷面最高分  
292 - };  
293 - },  
294 - async created() {  
295 - this.ids = this.$route.query.ids;  
296 - await this._QueryData();  
297 - await this._QueryDefaultLevels();  
298 - },  
299 - destroyed() {  
300 - sessionStorage.setItem("levelFromData", "");  
301 - },  
302 - methods: {  
303 - // 禁止输入负数  
304 - keydownRange(event) {  
305 - if (event.key == "-" || event.key == "e") {  
306 - event.returnValue = "";  
307 - }  
308 - },  
309 - print() {  
310 - tablePrint(  
311 - "print-content",  
312 - `多班_${this.subjectNames}_${this.title}_测练成绩对比分析`  
313 - );  
314 - },  
315 - setType(type) {  
316 - console.log(this.$refs.main.offsetHeight - 50);  
317 - this.tableMaxHeight = this.$refs.main.offsetHeight;  
318 - this.type = type;  
319 - },  
320 - openDia() {  
321 - this.diaLogBox = true;  
322 - },  
323 - closeDia() {  
324 - let levelFromData = sessionStorage.getItem("levelFromData");  
325 - if (levelFromData) {  
326 - levelFromData = JSON.parse(levelFromData);  
327 - this.fromData.type = levelFromData.type;  
328 - this.fromData.levelType = levelFromData.levelType;  
329 - this.fromData.levels = [...levelFromData.levels];  
330 - } else {  
331 - this.fromData.type = 0;  
332 - this.fromData.levelType = this.defaultLevels.levelType;  
333 - this.fromData.levels = [...this.defaultLevels.levels];  
334 - }  
335 - },  
336 - changeType(val) {  
337 - if (val == this.defaultLevels.type) {  
338 - this.fromData.levels = [...this.defaultLevels.levels];  
339 - } else {  
340 - this.fromData.levels = this.fromData.levels.splice(0, 4);  
341 - if (val == 0) {  
342 - this.fromData.levels = this.fromData.levels.map((item, index) => {  
343 - let arrTxt = ["优秀", "良好", "合格", "不合格"];  
344 - return [arrTxt[index], item[1], item[2]];  
345 - });  
346 - } else if (val == 1) {  
347 - this.fromData.levels = this.fromData.levels.map((item, index) => {  
348 - let arrTxt = ["A", "B", "C", "D"];  
349 - return [arrTxt[index], item[1], item[2]];  
350 - });  
351 - } else {  
352 - this.fromData.levels = this.fromData.levels.map((item, index) => {  
353 - return ["", item[1], item[2]];  
354 - });  
355 - }  
356 - }  
357 - },  
358 - savefrom() {  
359 - for (let i = 0; i < this.fromData.levels.length; i++) {  
360 - if (this.fromData.levels[i].includes("")) {  
361 - this.$message.warning("请补全编号" + (i + 1) + "设置信息!");  
362 - return;  
363 - }  
364 - }  
365 - if (this.fromData.levels.length == 0) {  
366 - this.$message.warning("请添加等级设置!");  
367 - return;  
368 - }  
369 - let nums = [];  
370 - let ERR_OK = false;  
371 - this.fromData.levels.map((item) => {  
372 - nums.push(Number(item[1]));  
373 - nums.push(Number(item[2]));  
374 - });  
375 - for (let i = 0; i < nums.length; i++) {  
376 - if (nums[i + 1] && nums[i + 1] > nums[i]) {  
377 - ERR_OK = true;  
378 - this.$message.warning("高等级比例不能低于低等级比例!请检查");  
379 - break;  
380 - }  
381 - }  
382 - if (ERR_OK) return;  
383 - this.tableData = [];  
384 - this.tableData2 = [];  
385 - this.defaultLevels.type = this.fromData.type;  
386 - this.defaultLevels.levelType = this.fromData.levelType;  
387 - this.defaultLevels.levels = [...this.fromData.levels];  
388 - sessionStorage.setItem("levelFromData", JSON.stringify(this.fromData));  
389 - this.diaLogBox = false;  
390 - this._QueryData({  
391 - levelType: this.fromData.levelType,  
392 - levels: this.fromData.levels,  
393 - });  
394 - },  
395 -  
396 - async _QueryDefaultLevels() {  
397 - const { data, info, status } = await this.$request.defaultLevels();  
398 - if (status === 0) {  
399 - this.defaultLevels = { ...data } || {  
400 - levelType: 0,  
401 - levels: [  
402 - ["优秀", 100, 90],  
403 - ["良好", 89.9, 70],  
404 - ["合格", 69.9, 60],  
405 - ["不合格", 59.9, 0],  
406 - ],  
407 - };  
408 - this.defaultLevels.type = 0  
409 - this.fromData.levelType = this.defaultLevels.levelType;  
410 - this.fromData.levels = [...this.defaultLevels.levels];  
411 - sessionStorage.setItem(  
412 - "levelFromData",  
413 - JSON.stringify(this.defaultLevels)  
414 - );  
415 - } else {  
416 - this.$message.error(info);  
417 - }  
418 - },  
419 - async _QueryData(params) {  
420 - let query = {};  
421 - if (params) {  
422 - let paramObj = JSON.parse(JSON.stringify(params))  
423 - if (paramObj.levelType == 0) {  
424 - paramObj.levels = paramObj.levels.map((item) => {  
425 - item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);  
426 - item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);  
427 - return item;  
428 - });  
429 - }  
430 - query = { ...paramObj };  
431 - }  
432 - const { data, info, status } = await this.$request.examMultiClassReport({  
433 - examIds: this.ids,  
434 - ...query,  
435 - });  
436 - if (status === 0) {  
437 - this.title = data.title;  
438 - this.examPaperScore = data.examPaperScore || 100;  
439 - this.subjectNames = data.subjectName;  
440 - this.tableData = data.classes || [];  
441 - this.tableData2 =  
442 - data.students.map((item) => {  
443 - item.score = Number(item.score);  
444 - return item;  
445 - }) || [];  
446 - } else {  
447 - this.$message.error(info);  
448 - }  
449 - },  
450 -  
451 - //导出  
452 - async exportData() {  
453 - if (this.exportLoading == true) return;  
454 - this.exportLoading = true;  
455 - let params = { ...this.fromData };  
456 - if (params.levelType == 0) {  
457 - params.levels = params.levels.map((item) => {  
458 - console.log(item);  
459 - item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);  
460 - item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);  
461 - return item;  
462 - });  
463 - }  
464 - const data = await this.$request.exportExamMultiReport({  
465 - examIds: this.ids,  
466 - levels: params.levels,  
467 - levelType: params.levelType,  
468 - });  
469 - this.exportLoading = false;  
470 - if (data) {  
471 - let blob = new Blob([data], {  
472 - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",  
473 - });  
474 - downloadFile(  
475 - `多班_${this.subjectNames}_${this.title}_测练成绩对比分析`,  
476 - blob  
477 - );  
478 - } else {  
479 - this.$message.error("下载失败");  
480 - }  
481 - },  
482 - },  
483 -};  
484 -</script>  
485 -  
486 -<style lang="scss" scoped>  
487 -.page-container {  
488 - position: relative;  
489 - height: 100%;  
490 - .table-box {  
491 - min-height: 100%;  
492 - }  
493 - &.active {  
494 - overflow: hidden;  
495 - }  
496 - .content-header {  
497 - width: 100%;  
498 - position: relative;  
499 - .setMinScore {  
500 - position: absolute;  
501 - bottom: 0;  
502 - right: 0;  
503 - }  
504 - }  
505 - .page-content {  
506 - padding: 20px 20px 0;  
507 - }  
508 -}  
509 -.tab-box {  
510 - width: 400px;  
511 - margin: 0 auto 12px;  
512 - background: #f8f8f8;  
513 - border-radius: 20px;  
514 - display: flex;  
515 - user-select: none;  
516 - .tab-item {  
517 - flex: 1;  
518 - height: 40px;  
519 - line-height: 40px;  
520 - text-align: center;  
521 - font-size: 16px;  
522 - color: #666;  
523 - font-weight: 500;  
524 - background: transparent;  
525 - border-radius: 20px;  
526 - cursor: pointer;  
527 - &.active {  
528 - background: #667ffd;  
529 - color: #fff;  
530 - }  
531 - }  
532 -}  
533 -.down {  
534 - padding-top: 20px;  
535 - width: 100%;  
536 - display: flex;  
537 - justify-content: space-between;  
538 -}  
539 -.use-form {  
540 - padding: 0 12px;  
541 - .use-form-item-box {  
542 - :deep(.el-form-item__content) {  
543 - display: flex;  
544 - }  
545 - .use-form-item {  
546 - width: 40%;  
547 - margin-right: 20px;  
548 - }  
549 - }  
550 -}  
551 -.dia-tab-box {  
552 - .dia-tab-tit,  
553 - .dia-tab-item {  
554 - margin-bottom: 10px;  
555 - i {  
556 - color: #f30;  
557 - padding-right: 5px;  
558 - }  
559 - display: flex;  
560 - .item {  
561 - width: 40px;  
562 - }  
563 - .item1 {  
564 - padding-left: 10px;  
565 - width: 10%;  
566 - }  
567 - .item2 {  
568 - width: 18%;  
569 - }  
570 - .item3 {  
571 - padding-left: 12px;  
572 - flex: 1;  
573 - }  
574 - .score-ipt {  
575 - width: 100px;  
576 - }  
577 - }  
578 - .dia-tab-tit {  
579 - background: rgba(243, 243, 243, 1);  
580 - }  
581 - .add {  
582 - display: flex;  
583 - justify-content: center;  
584 - margin: 0 auto;  
585 - p {  
586 - cursor: pointer;  
587 - }  
588 - .el-button {  
589 - margin-right: 6px;  
590 - }  
591 - }  
592 -}  
593 -.p1 {  
594 - line-height: 18px;  
595 -}  
596 -</style>  
597 \ No newline at end of file 0 \ No newline at end of file
src/views/basic/test/index.vue
1 <template> 1 <template>
2 - <div ref="main" class="page-container">  
3 - <back-box>  
4 - <template slot="title">  
5 - <span>即时测-数据报表</span>  
6 - </template>  
7 - <template slot="btns">  
8 - <el-tooltip  
9 - v-if="!code && gdClass"  
10 - effect="dark"  
11 - content="已归档试卷"  
12 - placement="bottom"  
13 - >  
14 - <el-button  
15 - type="primary"  
16 - icon="fa fa-archive"  
17 - size="mini"  
18 - plain  
19 - circle  
20 - @click="toArchiving"  
21 - ></el-button>  
22 - </el-tooltip>  
23 - </template>  
24 - </back-box>  
25 - <div class="answer-header">  
26 - <div class="sel-box">  
27 - <el-select  
28 - class="sel"  
29 - v-model="query.classId"  
30 - placeholder="选择班级"  
31 - @change="changeclass"  
32 - >  
33 - <el-option  
34 - v-for="item in classList"  
35 - :key="item.value"  
36 - :label="item.label"  
37 - :value="item.value"  
38 - >  
39 - </el-option>  
40 - </el-select>  
41 - <el-select  
42 - v-if="role == 'ROLE_BANZHUREN'"  
43 - class="sel"  
44 - multiple  
45 - v-model="query.subjectNames"  
46 - placeholder="选择科目"  
47 - @change="changeSub"  
48 - >  
49 - <el-option  
50 - v-for="item in subjectList"  
51 - :key="item.value"  
52 - :label="item.label"  
53 - :value="item.value"  
54 - >  
55 - </el-option>  
56 - </el-select>  
57 - <el-select  
58 - v-else  
59 - class="sel"  
60 - v-model="query.subjectNames"  
61 - placeholder="选择科目"  
62 - >  
63 - <el-option  
64 - v-for="item in subjectList"  
65 - :key="item.value"  
66 - :label="item.label"  
67 - :value="item.value"  
68 - >  
69 - </el-option>  
70 - </el-select>  
71 - <div class="d1">  
72 - <el-date-picker  
73 - v-model="query.startDay"  
74 - type="date"  
75 - @change="handleChangeTimeStart"  
76 - placeholder="选择日期时间"  
77 - value-format="yyyy-MM-dd"  
78 - >  
79 - </el-date-picker>  
80 - ~  
81 - <el-date-picker  
82 - v-model="query.endDay"  
83 - type="date"  
84 - placeholder="选择日期时间"  
85 - @change="handleChangeTimeEnd"  
86 - value-format="yyyy-MM-dd"  
87 - >  
88 - </el-date-picker> 2 + <div class="main" ref="main">
  3 + <div class="sel-dia">
  4 + <p class="tit">
  5 + <span>报表数据配置</span>
  6 + <i class="el-icon-close" @click="goHome"></i>
  7 + </p>
  8 + <div class="select-box">
  9 + <div class="sel-item sel-item2">
  10 + <span class="sel-label">班级:</span>
  11 + <div class="sel-d">
  12 + <p class="p-all">
  13 + <el-checkbox :indeterminate="isIndeterminateClass" v-model="allClass"
  14 + @change="handleCheckAllChangeClass">全选</el-checkbox>
  15 + </p>
  16 + <p class="sel-p">
  17 + <el-checkbox-group v-model="query.classId" @change="changeclass">
  18 + <el-checkbox v-for="item in classList" :label="item.value" :key="item.value">{{ item.label
  19 + }}</el-checkbox>
  20 + </el-checkbox-group>
  21 + </p>
  22 + </div>
89 </div> 23 </div>
90 - <p class="p1">  
91 - <span @click="setDate(1)" :class="[date == 1 ? 'active' : '', 's1']"  
92 - >今天</span  
93 - >  
94 - <span @click="setDate(2)" :class="[date == 2 ? 'active' : '', 's1']"  
95 - >本周</span  
96 - >  
97 - <span @click="setDate(3)" :class="[date == 3 ? 'active' : '', 's1']"  
98 - >本月</span  
99 - >  
100 - <span @click="setDate(4)" :class="[date == 4 ? 'active' : '', 's1']"  
101 - >本季度</span  
102 - >  
103 - </p>  
104 - <el-button type="primary" round @click="_QueryData()">筛选</el-button>  
105 - </div>  
106 - </div>  
107 - <div class="table-box">  
108 - <el-radio-group  
109 - v-model="tabIndex"  
110 - @change="changeTab"  
111 - style="margin-bottom: 20px"  
112 - >  
113 - <template v-for="(item, index) in tabList">  
114 - <el-radio-button  
115 - v-if="index == 0 || query.startDay != query.endDay"  
116 - :key="index"  
117 - :label="index + 1"  
118 - >{{ item }}</el-radio-button  
119 - >  
120 - </template>  
121 - </el-radio-group>  
122 - <div v-show="tabIndex == 1" v-loading="loading">  
123 - <el-table :data="tableData" border style="width: 100%">  
124 - <el-table-column  
125 - prop="title"  
126 - label="试卷名称"  
127 - fixed  
128 - align="center"  
129 - ></el-table-column>  
130 - <el-table-column  
131 - prop="examPaperScore"  
132 - label="卷面分"  
133 - align="center"  
134 - width="68"  
135 - ></el-table-column>  
136 - <el-table-column prop="answeredNum" label="测验人数" align="center"  
137 - ><template slot-scope="scoped">{{  
138 - `${scoped.row.answeredNum}/${scoped.row.classPersonNum}`  
139 - }}</template></el-table-column  
140 - >  
141 - <el-table-column  
142 - prop="examStartTime"  
143 - label="测验时间"  
144 - width="100"  
145 - align="center"  
146 - ></el-table-column>  
147 - <el-table-column prop="avgScore" label="班平均分" align="center"  
148 - ><template slot-scope="scoped">{{  
149 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
150 - scoped.row.answerNum == 0) &&  
151 - scoped.row.recordStatus == 0  
152 - ? "-"  
153 - : scoped.row.avgScore  
154 - }}</template></el-table-column  
155 - >  
156 - <el-table-column prop="highestScore" label="班最高分" align="center"  
157 - ><template slot-scope="scoped">{{  
158 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
159 - scoped.row.answerNum == 0) &&  
160 - scoped.row.recordStatus == 0  
161 - ? "-"  
162 - : scoped.row.highestScore  
163 - }}</template></el-table-column  
164 - >  
165 - <el-table-column prop="lowestScore" label="班最低分" align="center"  
166 - ><template slot-scope="scoped">{{  
167 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
168 - scoped.row.answerNum == 0) &&  
169 - scoped.row.recordStatus == 0  
170 - ? "-"  
171 - : scoped.row.lowestScore  
172 - }}</template></el-table-column  
173 - >  
174 - <el-table-column  
175 - prop="excellenRate"  
176 - label="优秀数(率)"  
177 - sortable  
178 - align="center"  
179 - width="110"  
180 - class-name="p0"  
181 - ><template slot-scope="scoped">  
182 - <p  
183 - v-if="  
184 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
185 - scoped.row.answerNum == 0) &&  
186 - scoped.row.arecordStatus == 0  
187 - "  
188 - >  
189 - "-"  
190 - </p>  
191 - <template v-else>  
192 - <p>{{ scoped.row.excellenNum }}</p>  
193 - <p v-if="scoped.row.excellenNum">  
194 - {{ `(${scoped.row.excellenRate}%)` }}  
195 - </p>  
196 - </template>  
197 - </template></el-table-column  
198 - >  
199 - <el-table-column  
200 - prop="goodRate"  
201 - label="良好数(率)"  
202 - sortable  
203 - align="center"  
204 - width="110"  
205 - class-name="p0"  
206 - ><template slot-scope="scoped">  
207 - <p  
208 - v-if="  
209 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
210 - scoped.row.answerNum == 0) &&  
211 - scoped.row.arecordStatus == 0  
212 - "  
213 - >  
214 - "-"  
215 - </p>  
216 - <template v-else>  
217 - <p>{{ scoped.row.goodNum }}</p>  
218 - <p v-if="scoped.row.goodNum">  
219 - {{ `(${scoped.row.goodRate}%)` }}  
220 - </p>  
221 - </template>  
222 - </template></el-table-column  
223 - >  
224 - <el-table-column  
225 - prop="passRate"  
226 - label="及格数(率)"  
227 - sortable  
228 - align="center"  
229 - width="110"  
230 - class-name="p0"  
231 - ><template slot-scope="scoped">  
232 - <p  
233 - v-if="  
234 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
235 - scoped.row.answerNum == 0) &&  
236 - scoped.row.arecordStatus == 0  
237 - "  
238 - >  
239 - "-"  
240 - </p>  
241 - <template v-else>  
242 - <p>{{ scoped.row.passNum }}</p>  
243 - <p v-if="scoped.row.passNum">  
244 - {{ `(${scoped.row.passRate}%)` }}  
245 - </p>  
246 - </template>  
247 - </template></el-table-column  
248 - >  
249 - <el-table-column  
250 - prop="failedRate"  
251 - label="不及格数(率)"  
252 - sortable  
253 - align="center"  
254 - width="130"  
255 - class-name="p0"  
256 - ><template slot-scope="scoped">  
257 - <p  
258 - v-if="  
259 - (scoped.row.subjectiveScore == scoped.row.examPaperScore ||  
260 - scoped.row.answerNum == 0) &&  
261 - scoped.row.arecordStatus == 0  
262 - "  
263 - >  
264 - "-"  
265 - </p>  
266 - <template v-else>  
267 - <p>{{ scoped.row.failedNum }}</p>  
268 - <p v-if="scoped.row.failedNum">  
269 - {{ `(${scoped.row.failedRate}%)` }}  
270 - </p>  
271 - </template>  
272 - </template></el-table-column  
273 - >  
274 - <el-table-column label="操作" align="center">  
275 - <template slot-scope="scoped">  
276 - <el-tooltip  
277 - v-if="  
278 - scoped.row.answerNum != 0 ||  
279 - (scoped.row.recordStatus != 0 &&  
280 - scoped.row.subjectiveScore == scoped.row.examPaperScore)  
281 - "  
282 - effect="dark"  
283 - content="详情"  
284 - placement="top"  
285 - >  
286 - <el-button  
287 - type="primary"  
288 - circle  
289 - size="mini"  
290 - icon="fa fa-arrow-right"  
291 - @click="linkTo(scoped.row)"  
292 - ></el-button>  
293 - </el-tooltip>  
294 - <template  
295 - v-if="  
296 - scoped.row.answerNum == 0 &&  
297 - scoped.row.subjectiveScore != scoped.row.examPaperScore  
298 - "  
299 - >  
300 - <el-tooltip  
301 - v-if="role == 'ROLE_JIAOSHI'"  
302 - effect="dark"  
303 - content="设置答案"  
304 - placement="top"  
305 - >  
306 - <el-button  
307 - type="primary"  
308 - circle  
309 - size="mini"  
310 - icon="fa fa-file-text"  
311 - @click="edit(scoped.row)"  
312 - ></el-button>  
313 - </el-tooltip>  
314 - <template v-else>未设置答案</template>  
315 - </template>  
316 - <el-tooltip  
317 - v-if="  
318 - scoped.row.subjectiveScore == scoped.row.examPaperScore &&  
319 - scoped.row.recordStatus == 0  
320 - "  
321 - effect="dark"  
322 - content="导入主观题"  
323 - placement="top"  
324 - >  
325 - <el-button  
326 - type="primary"  
327 - circle  
328 - size="mini"  
329 - icon="fa fa-cloud"  
330 - @click="uploadSJ(scoped.row)"  
331 - ></el-button>  
332 - </el-tooltip>  
333 - </template>  
334 - </el-table-column>  
335 - </el-table>  
336 - <div class="pagination-box">  
337 - <el-pagination  
338 - small=""  
339 - layout="total,prev, pager, next"  
340 - :hide-on-single-page="true"  
341 - :total="total"  
342 - @current-change="changePage"  
343 - :current-page="page"  
344 - :page-size="size"  
345 - >  
346 - </el-pagination> 24 + <div class="sel-item sel-item2">
  25 + <span class="sel-label">科目:</span>
  26 + <div class="sel-d">
  27 + <p class="p-all">
  28 + <el-checkbox :indeterminate="isIndeterminateSub" v-model="allSubject"
  29 + @change="handleCheckAllChangeSub">全选</el-checkbox>
  30 + </p>
  31 + <p class="sel-p">
  32 + <el-checkbox-group v-model="query.subjectNames" @change="CheckedSub">
  33 + <el-checkbox v-for="item in subjectList" :label="item" :key="item">{{ item
  34 + }}</el-checkbox>
  35 + </el-checkbox-group>
  36 + </p>
  37 + </div>
347 </div> 38 </div>
348 - </div>  
349 - <div v-show="tabIndex == 2" v-loading="loading">  
350 - <el-empty  
351 - :image-size="100"  
352 - v-if="!tableData.length && loading == false"  
353 - description="没有更多数据"  
354 - ></el-empty>  
355 - <template v-if="tableData.length && loading == false">  
356 - <div id="print-content">  
357 - <el-table  
358 - :max-height="tableMaxHeight"  
359 - v-if="role == 'ROLE_JIAOSHI'"  
360 - :data="tableData"  
361 - border  
362 - style="width: 100%"  
363 - >  
364 - <el-table-column  
365 - prop="studentCode"  
366 - label="学号"  
367 - align="center"  
368 - fixed  
369 - ></el-table-column>  
370 - <el-table-column  
371 - prop="studentName"  
372 - label="姓名"  
373 - fixed  
374 - align="center"  
375 - >  
376 - <template slot-scope="scoped"  
377 - ><span class="click-b" @click="toPortrait(scoped.row)">  
378 - {{ scoped.row.studentName }}  
379 - </span></template  
380 - ></el-table-column  
381 - >  
382 - <el-table-column  
383 - align="center"  
384 - v-for="(item, index) in answerList"  
385 - :key="index"  
386 - :label="item.title"  
387 - >  
388 - <el-table-column  
389 - :prop="'score' + index"  
390 - :label="index == 0 ? '总分' : '成绩'"  
391 - align="center"  
392 - :class-name="index % 2 == 0 ? 'bg' : ''"  
393 - ></el-table-column>  
394 - <el-table-column  
395 - :prop="'classRank' + index"  
396 - label="班名"  
397 - align="center"  
398 - :class-name="index % 2 == 0 ? 'bg' : ''"  
399 - ></el-table-column>  
400 - </el-table-column>  
401 - </el-table>  
402 - <el-table  
403 - v-else  
404 - :data="tableData"  
405 - :max-height="tableMaxHeight"  
406 - border  
407 - style="width: 100%"  
408 - >  
409 - <el-table-column  
410 - prop="studentCode"  
411 - label="学号"  
412 - align="center"  
413 - fixed  
414 - ></el-table-column>  
415 -  
416 - <el-table-column  
417 - prop="studentName"  
418 - label="姓名"  
419 - fixed  
420 - align="center"  
421 - >  
422 - <template slot-scope="scoped"  
423 - ><span class="click-b" @click="toPortrait(scoped.row)">  
424 - {{ scoped.row.studentName }}  
425 - </span></template  
426 - >  
427 - </el-table-column>  
428 - <el-table-column  
429 - align="center"  
430 - v-for="(item, index) in answerList"  
431 - :key="index"  
432 - :label="item"  
433 - >  
434 - <el-table-column  
435 - :prop="'examCount' + item"  
436 - label="测练数"  
437 - align="center"  
438 - :class-name="index % 2 == 0 ? 'bg' : ''"  
439 - ></el-table-column>  
440 - <el-table-column  
441 - :prop="'participationCount' + item"  
442 - label="参与数"  
443 - align="center"  
444 - :class-name="index % 2 == 0 ? 'bg' : ''"  
445 - ></el-table-column>  
446 - <el-table-column  
447 - :prop="'score' + item"  
448 - label="总分"  
449 - align="center"  
450 - :class-name="index % 2 == 0 ? 'bg' : ''"  
451 - ></el-table-column>  
452 - <el-table-column  
453 - :prop="'classRank' + item"  
454 - label="班名"  
455 - align="center"  
456 - :class-name="index % 2 == 0 ? 'bg' : ''"  
457 - ></el-table-column>  
458 - </el-table-column>  
459 - </el-table> 39 + <div class="sel-item">
  40 + <span class="sel-label">日期:</span>
  41 + <div class="d1">
  42 + <el-date-picker v-model="query.startDay" type="date" @change="handleChangeTimeStart" placeholder="选择日期时间"
  43 + value-format="yyyy-MM-dd">
  44 + </el-date-picker>
  45 + ~
  46 + <el-date-picker v-model="query.endDay" type="date" placeholder="选择日期时间" @change="handleChangeTimeEnd"
  47 + value-format="yyyy-MM-dd">
  48 + </el-date-picker>
460 </div> 49 </div>
461 - </template>  
462 - </div>  
463 - <p class="down" v-if="tabIndex == 2 && tableData.length">  
464 - <el-button  
465 - type="primary"  
466 - plain  
467 - round  
468 - icon="fa fa-cloud-download"  
469 - @click="downExl"  
470 - >导出报表</el-button  
471 - >  
472 - <el-button  
473 - v-if="!this.$store.getters.code"  
474 - @click="print"  
475 - type="primary"  
476 - plain  
477 - round  
478 - icon="el-icon-printer"  
479 - >打印</el-button  
480 - >  
481 - </p>  
482 - </div>  
483 - <el-dialog :close-on-click-modal="false" title="导入主观题分数" :visible.sync="diaUp" width="600">  
484 - <upload  
485 - :url="url"  
486 - :examId="examId"  
487 - @upSuccess="upSuccess"  
488 - fileName="主观题分数"  
489 - v-loading="loadingDown"  
490 - >  
491 - <template slot="down">  
492 - <p class="down-txt">  
493 - 第一步:下载模板并编辑完成学生分数  
494 - <el-link type="danger" @click="downExcel">模板下载</el-link> 。 50 + <p class="p1">
  51 + <span @click="setDate(1)" :class="[date == 1 ? 'active' : '', 's1']">本周</span>
  52 + <span @click="setDate(2)" :class="[date == 2 ? 'active' : '', 's1']">本月</span>
  53 + <span @click="setDate(3)" :class="[date == 3 ? 'active' : '', 's1']">本季度</span>
495 </p> 54 </p>
496 - <p class="down-txt">第二步:上传完成编辑的模板文件并导入。</p>  
497 - </template>  
498 - </upload>  
499 - <div class="dialog-footer" slot="footer">  
500 - <el-button @click="diaUp = false">取 消</el-button> 55 + </div>
  56 + </div>
  57 + <div class="foot-box">
  58 + <el-button type="primary" round @click="goList">确定</el-button>
  59 + <el-button type="danger" round @click="goHome">取消</el-button>
501 </div> 60 </div>
502 - </el-dialog> 61 + </div>
503 </div> 62 </div>
504 </template> 63 </template>
505 64
506 <script> 65 <script>
507 -import { formatDate, downloadFile, tablePrint } from "utils";  
508 -import BusEvent from "@/utils/busEvent"; 66 +import { formatDate } from "utils";
509 export default { 67 export default {
510 data() { 68 data() {
511 return { 69 return {
512 code: "", 70 code: "",
513 - gdClass: 0, //已归档班级数量  
514 - exportLoading: false,  
515 - tableMaxHeight: 300,  
516 role: "", 71 role: "",
517 - loading: false,  
518 - diaUp: false,  
519 - loadingDown: false,  
520 - url: "/api_html/teaching/importSubjectiveScore",  
521 - examId: "",  
522 - form: {  
523 - id: "",  
524 - title: "",  
525 - examPaperScore: "",  
526 - },  
527 date: "", //今天-昨天-本周 72 date: "", //今天-昨天-本周
528 query: { 73 query: {
529 //搜索条件 74 //搜索条件
530 - classId: "",  
531 - subjectNames: "", 75 + classId: [],
  76 + subjectNames: [],
532 startDay: "", 77 startDay: "",
533 endDay: "", 78 endDay: "",
534 - day: "",  
535 }, 79 },
536 - tabList: ["单卷测练报表", "阶段测练报表"],  
537 classList: [], //班级 80 classList: [], //班级
538 subjectList: [], //科目 81 subjectList: [], //科目
539 - tabIndex: 1, //选项卡  
540 - tableData: [],  
541 - answerList: [], //设置多卷内容供tableStage表格数据用  
542 - page: 1,  
543 - size: 20,  
544 - total: 0, 82 +
  83 + isIndeterminateClass: true,//全选样式
  84 + allClass: false,//全选状态
  85 + isIndeterminateSub: true,//全选样式
  86 + allSubject: false,//全选状态
545 }; 87 };
546 }, 88 },
547 async created() { 89 async created() {
@@ -549,7 +91,7 @@ export default { @@ -549,7 +91,7 @@ export default {
549 this.role = 91 this.role =
550 this.$store.getters.info.showRole || 92 this.$store.getters.info.showRole ||
551 this.$store.getters.info.permissions[0].role; 93 this.$store.getters.info.permissions[0].role;
552 - this._QueryClassList2(); 94 + this.query.subjectNames = [];
553 await this._QueryClassList(); 95 await this._QueryClassList();
554 if (!this.query.classId) { 96 if (!this.query.classId) {
555 return; 97 return;
@@ -562,115 +104,37 @@ export default { @@ -562,115 +104,37 @@ export default {
562 this.query.endDay = new Date(); 104 this.query.endDay = new Date();
563 } 105 }
564 }, 106 },
565 - activated() {  
566 - const that = this;  
567 - BusEvent.$on("keepAlive", async function () {  
568 - // if (that.$route.path == "/test") {  
569 - that.query.subjectNames = that.role == "ROLE_BANZHUREN" ? [] : "";  
570 - that._QueryClassList2();  
571 - await that._QueryClassList();  
572 - if (!that.query.classId) {  
573 - return;  
574 - }  
575 - await that._QuerySubjectList();  
576 - await that.setDate(1);  
577 - let startDay = that.query?.startDay;  
578 - if (!startDay) {  
579 - that.query.startDay = new Date();  
580 - that.query.endDay = new Date();  
581 - }  
582 - // }  
583 - });  
584 - }, 107 +
585 methods: { 108 methods: {
586 - print() {  
587 - tablePrint("print-content", "即时测-" + this.tabList[this.tabIndex - 1]); 109 + handleCheckAllChangeClass(val) {
  110 + this.isIndeterminateClass = false
  111 + this.query.classId = val ? this.classList.map(item => item.value) : [];
588 }, 112 },
589 - changeSub(val) {  
590 - //科目改变触发事件  
591 - let sub;  
592 - if (val && val.length) {  
593 - let leng = val.length - 1;  
594 - sub = val[leng];  
595 - }  
596 - console.log(val);  
597 - this.query.subjectNames = val.filter((item) => {  
598 - return sub != "全部" ? item != "全部" : item == "全部";  
599 - }); 113 + changeclass(value) {
  114 + console.log(value)
  115 + let checkedCount = value.length;
  116 + this.allClass = checkedCount === this.classList.length;
  117 + this.isIndeterminateClass = checkedCount > 0 && checkedCount < this.classList.length;
600 }, 118 },
601 - toArchiving() {  
602 - this.$router.push({  
603 - path: "/testArchiving",  
604 - }); 119 + handleCheckAllChangeSub(val) {
  120 + this.isIndeterminate = false
  121 + this.query.subjectNames = val ? this.subjectList : [];
605 }, 122 },
606 - linkTo(obj) {  
607 - //去详情  
608 - this.$router.push({  
609 - path: "/testAnalysis",  
610 - query: {  
611 - id: obj.id,  
612 - title: obj.title,  
613 - score: obj.examPaperScore,  
614 - },  
615 - });  
616 - },  
617 - toPortrait(obj) {  
618 - //暂时不上线  
619 - return;  
620 - if (this.$store.getters.code) {  
621 - return;  
622 - }  
623 - let subjectNames = [];  
624 - subjectNames =  
625 - this.role == "ROLE_BANZHUREN"  
626 - ? [...this.query["subjectNames"]]  
627 - : [this.query["subjectNames"]];  
628 - if (  
629 - this.query["subjectNames"] &&  
630 - this.query["subjectNames"]?.length == 1 &&  
631 - this.query["subjectNames"][0] == "全部"  
632 - ) {  
633 - subjectNames = this.subjectList.map((item) => {  
634 - return item.value;  
635 - });  
636 - subjectNames?.shift();  
637 - }  
638 - //去学生画像  
639 - this.$router.push({  
640 - path: "/portraitDetail",  
641 - query: {  
642 - id: obj.studentId,  
643 - classId: this.query.classId,  
644 - subjectNames: subjectNames.join(","),  
645 - studentName: obj.studentName,  
646 - studentCode: obj.studentCode,  
647 - startDay: this.query.startDay,  
648 - endDay: this.query.endDay,  
649 - date: this.date,  
650 - },  
651 - });  
652 - },  
653 - uploadSJ(obj) {  
654 - //导入开关  
655 - this.examId = obj.id;  
656 - this.diaUp = true; 123 + CheckedSub(value) {
  124 + console.log(value)
  125 + let checkedCount = value.length;
  126 + this.allSubject = checkedCount === this.subjectList.length;
  127 + this.isIndeterminate = checkedCount > 0 && checkedCount < this.subjectList.length;
657 }, 128 },
658 setDate(index) { 129 setDate(index) {
659 const that = this; 130 const that = this;
660 this.date = index == this.date ? "" : index; 131 this.date = index == this.date ? "" : index;
661 let aYear = new Date().getFullYear(); 132 let aYear = new Date().getFullYear();
662 let aMonth = new Date().getMonth() + 1; 133 let aMonth = new Date().getMonth() + 1;
663 - that.query.day = "";  
664 that.query.startDay = ""; 134 that.query.startDay = "";
665 that.query.endDay = ""; 135 that.query.endDay = "";
666 switch (index) { 136 switch (index) {
667 case 1: 137 case 1:
668 - that.query.day = formatDate(new Date(), "yyyy-MM-dd");  
669 - that.query.startDay = that.query.day;  
670 - that.query.endDay = that.query.day;  
671 - that.tabIndex = 1;  
672 - break;  
673 - case 2:  
674 let day = new Date().getDay(); 138 let day = new Date().getDay();
675 if (day == 0) { 139 if (day == 0) {
676 //中国式星期天是一周的最后一天 140 //中国式星期天是一周的最后一天
@@ -681,12 +145,12 @@ export default { @@ -681,12 +145,12 @@ export default {
681 that.query.startDay = formatDate(new Date(aTime), "yyyy-MM-dd"); 145 that.query.startDay = formatDate(new Date(aTime), "yyyy-MM-dd");
682 that.query.endDay = formatDate(new Date(), "yyyy-MM-dd"); 146 that.query.endDay = formatDate(new Date(), "yyyy-MM-dd");
683 break; 147 break;
684 - case 3: 148 + case 2:
685 aMonth = aMonth < 10 ? "0" + aMonth : aMonth; 149 aMonth = aMonth < 10 ? "0" + aMonth : aMonth;
686 that.query.startDay = `${aYear}-${aMonth}-01`; 150 that.query.startDay = `${aYear}-${aMonth}-01`;
687 that.query.endDay = formatDate(new Date(), "yyyy-MM-dd"); 151 that.query.endDay = formatDate(new Date(), "yyyy-MM-dd");
688 break; 152 break;
689 - case 4: 153 + case 3:
690 if (aMonth > 0 && aMonth < 4) { 154 if (aMonth > 0 && aMonth < 4) {
691 aMonth = "1"; 155 aMonth = "1";
692 } else if (aMonth > 3 && aMonth < 7) { 156 } else if (aMonth > 3 && aMonth < 7) {
@@ -703,10 +167,8 @@ export default { @@ -703,10 +167,8 @@ export default {
703 break; 167 break;
704 } 168 }
705 this.page = 1; 169 this.page = 1;
706 - this._QueryData();  
707 }, 170 },
708 handleChangeTimeStart(val) { 171 handleChangeTimeStart(val) {
709 - this.query.day = "";  
710 this.date = ""; 172 this.date = "";
711 if (this.query.endDay) { 173 if (this.query.endDay) {
712 if (new Date(val).getTime() > new Date(this.query.endDay).getTime()) { 174 if (new Date(val).getTime() > new Date(this.query.endDay).getTime()) {
@@ -716,67 +178,21 @@ export default { @@ -716,67 +178,21 @@ export default {
716 } 178 }
717 }, 179 },
718 handleChangeTimeEnd(val) { 180 handleChangeTimeEnd(val) {
719 - this.query.day = "";  
720 this.date = ""; 181 this.date = "";
721 - if (this.query.startDay) { 182 + if (this.query.startDay && val) {
722 if (new Date(val).getTime() < new Date(this.query.startDay).getTime()) { 183 if (new Date(val).getTime() < new Date(this.query.startDay).getTime()) {
723 this.$message.error("任务结束时间不能任务开始时间前面,请重新设置"); 184 this.$message.error("任务结束时间不能任务开始时间前面,请重新设置");
724 this.query.endDay = ""; 185 this.query.endDay = "";
725 } 186 }
726 } 187 }
727 }, 188 },
728 - changePage(page) {  
729 - this.page = page;  
730 - this._QueryData();  
731 - },  
732 - edit(item) {  
733 - this.$router.push({  
734 - path: "/examinationPaperEdit",  
735 - query: {  
736 - paperId: item.id,  
737 - title: item.title,  
738 - type: 2,  
739 - },  
740 - });  
741 - },  
742 - changeTab() {  
743 - this.tableMaxHeight = this.$refs.main.offsetHeight;  
744 - this.page = 1;  
745 - this._QueryData();  
746 - },  
747 - upSuccess(res) {  
748 - //导入成功  
749 - this.$message.success("导入成功");  
750 - this.diaUp = false;  
751 - this._QueryData();  
752 - },  
753 - async changeclass() {  
754 - await this._QuerySubjectList();  
755 - this.page = 1;  
756 - this._QueryData();  
757 - },  
758 - async changClazz() {  
759 - this.page = 1;  
760 - await this._QuerySubjectList();  
761 - await this._QueryData();  
762 - },  
763 - async _QueryClassList2() {  
764 - const fetchClassList =  
765 - this.role == "ROLE_BANZHUREN"  
766 - ? this.$request.cTClassList  
767 - : this.$request.tClassList;  
768 - const { data, status, info } = await fetchClassList({ status: 1 });  
769 - if (status === 0) {  
770 - this.gdClass = data?.list?.length || 0;  
771 - } else {  
772 - this.$message.error(info);  
773 - }  
774 - },  
775 async _QueryClassList() { 189 async _QueryClassList() {
776 const fetchClassList = 190 const fetchClassList =
777 this.role == "ROLE_BANZHUREN" 191 this.role == "ROLE_BANZHUREN"
778 - ? this.$request.cTClassList  
779 - : this.$request.tClassList; 192 + ? this.$request.cTClassList :
  193 + this.role == "ROLE_PERSONAL"
  194 + ? this.$request.pClassList
  195 + : this.$request.tClassList;
780 const { data, status, info } = await fetchClassList(); 196 const { data, status, info } = await fetchClassList();
781 if (status === 0) { 197 if (status === 0) {
782 this.classList = data.list.map((item) => { 198 this.classList = data.list.map((item) => {
@@ -785,7 +201,7 @@ export default { @@ -785,7 +201,7 @@ export default {
785 label: item.className, 201 label: item.className,
786 }; 202 };
787 }); 203 });
788 - this.query.classId = this.classList[0]?.value; 204 + this.classList.length ? this.query.classId.push(this.classList[0].value) : "";
789 } else { 205 } else {
790 this.$message.error(info); 206 this.$message.error(info);
791 } 207 }
@@ -793,275 +209,191 @@ export default { @@ -793,275 +209,191 @@ export default {
793 async _QuerySubjectList() { 209 async _QuerySubjectList() {
794 const fetchSubjectList = 210 const fetchSubjectList =
795 this.role == "ROLE_BANZHUREN" 211 this.role == "ROLE_BANZHUREN"
796 - ? this.$request.cTSubjectList  
797 - : this.$request.tSubjectList; 212 + ? this.$request.cTSubjectList :
  213 + this.role == "ROLE_PERSONAL"
  214 + ? this.$request.pSubjectList
  215 + : this.$request.tSubjectList;
798 216
  217 + const classIds = this.classList.map(item => item.value) || []
799 const { data, status, info } = await fetchSubjectList({ 218 const { data, status, info } = await fetchSubjectList({
800 - classId: this.query.classId, 219 + classIds: classIds,
801 }); 220 });
802 if (status === 0) { 221 if (status === 0) {
803 - this.subjectList =  
804 - data.subjectNames?.map((item) => {  
805 - return {  
806 - value: item,  
807 - label: item,  
808 - };  
809 - }) || [];  
810 - if (this.role == "ROLE_BANZHUREN") {  
811 - this.subjectList.unshift({  
812 - value: "全部",  
813 - label: "全部",  
814 - });  
815 - this.query.subjectNames.push(this.subjectList[0]?.value);  
816 - } else {  
817 - this.query.subjectNames = this.subjectList[0]?.value;  
818 - } 222 + this.subjectList = data.subjectNames || [];
  223 + // if (this.role == "ROLE_BANZHUREN") {
  224 + // this.query.subjectNames = this.subjectList
  225 + // } else {
  226 + this.subjectList.length ? this.query.subjectNames.push(this.subjectList[0]) : "";
  227 + // }
819 } else { 228 } else {
820 this.$message.error(info); 229 this.$message.error(info);
821 } 230 }
822 }, 231 },
823 - async _QueryData() {  
824 - if (!this.query.classId) {  
825 - return;  
826 - }  
827 - this.tableData = [];  
828 - if (this.tabIndex == 1) {  
829 - this.examReportList();  
830 - } else {  
831 - this.phaseExamReport();  
832 - }  
833 - },  
834 - //单卷测练  
835 - async examReportList() {  
836 - this.loading = true;  
837 - let query = {};  
838 - for (let key in this.query) {  
839 - if (this.query[key] != "") {  
840 - query[key] = this.query[key];  
841 - }  
842 - }  
843 - if (this.role != "ROLE_BANZHUREN") {  
844 - query.subjectNames = [query.subjectNames];  
845 - } else {  
846 - if (  
847 - query["subjectNames"] &&  
848 - query["subjectNames"].length == 1 &&  
849 - query["subjectNames"][0] == "全部"  
850 - ) {  
851 - query["subjectNames"] = this.subjectList.map((item) => {  
852 - return item.value;  
853 - });  
854 - query["subjectNames"].shift();  
855 - }  
856 - if (!query["subjectNames"]) {  
857 - this.$message.warning("请选择科目");  
858 - return;  
859 - }  
860 - }  
861 - const { data, status, info } = await this.$request.examReportList({  
862 - ...query,  
863 - page: this.page,  
864 - size: this.size,  
865 - });  
866 - this.loading = false;  
867 - if (status === 0) {  
868 - this.tableData = (data?.list && [...data?.list]) || [];  
869 - this.total = data?.count || 0;  
870 - } else {  
871 - this.$message.error(info);  
872 - }  
873 - },  
874 - //多卷测练  
875 - async phaseExamReport() {  
876 - this.loading = true;  
877 - let query = {};  
878 - for (let key in this.query) {  
879 - if (this.query[key] != "") {  
880 - if (key == "subjectNames" && this.role != "ROLE_BANZHUREN") {  
881 - query["subjectName"] = this.query[key];  
882 - } else {  
883 - query[key] = this.query[key];  
884 - }  
885 - }  
886 - }  
887 - if (this.role == "ROLE_BANZHUREN") {  
888 - if (  
889 - query["subjectNames"] &&  
890 - query["subjectNames"]?.length == 1 &&  
891 - query["subjectNames"][0] == "全部"  
892 - ) {  
893 - query["subjectNames"] = this.subjectList.map((item) => {  
894 - return item.value;  
895 - });  
896 - query["subjectNames"]?.shift();  
897 - }  
898 - }  
899 - const phaseExamReport =  
900 - this.role == "ROLE_BANZHUREN"  
901 - ? this.$request.cTPhaseExamReport  
902 - : this.$request.phaseExamReport;  
903 - const { data, status, info } = await phaseExamReport({  
904 - ...query,  
905 - });  
906 - this.loading = false;  
907 - if (status === 0) {  
908 - this.total = data.count;  
909 - if (this.role == "ROLE_BANZHUREN") {  
910 - let subjectName = [];  
911 - this.tableData = data?.list.map((item) => {  
912 - let params = {};  
913 - item.dataList.map((items, index) => {  
914 - if (!subjectName.includes(items.subjectName)) {  
915 - subjectName.push(items.subjectName);  
916 - }  
917 - params["examCount" + items.subjectName] = items.examCount;  
918 - params["participationCount" + items.subjectName] =  
919 - items.participationCount;  
920 - params["score" + items.subjectName] = items.score;  
921 - params["classRank" + items.subjectName] = items.classRank;  
922 - });  
923 - return {  
924 - ...item,  
925 - ...params,  
926 - };  
927 - });  
928 - this.answerList = [...subjectName];  
929 - } else {  
930 - let dataIdsList = [],  
931 - dataList = [];  
932 - data?.list.map((item) => {  
933 - item.examList.map((items) => {  
934 - if (!dataIdsList.includes(items.title)) {  
935 - dataIdsList.push(items.title);  
936 - dataList.push(items);  
937 - }  
938 - });  
939 - });  
940 - console.log(dataList);  
941 - this.tableData = data?.list.map((item) => {  
942 - let params = {};  
943 - dataIdsList.map((ids, index) => {  
944 - params["score" + index] = "--";  
945 - params["classRank" + index] = "--";  
946 - item.examList.map((items) => {  
947 - if (items.title == ids) {  
948 - params["score" + index] = items.score;  
949 - params["classRank" + index] = items.classRank;  
950 - }  
951 - });  
952 - });  
953 - return {  
954 - ...item,  
955 - ...params,  
956 - };  
957 - });  
958 - this.answerList = dataList;  
959 - }  
960 - } else {  
961 - this.$message.error(info);  
962 - } 232 +
  233 + //回主页
  234 + goHome() {
  235 + this.$router.push({
  236 + path: '/index'
  237 + })
963 }, 238 },
964 - async downExl() {  
965 - //报表到处  
966 - if (this.exportLoading == true) return;  
967 - let query = {};  
968 - for (let key in this.query) {  
969 - if (this.query[key] != "") {  
970 - if (key == "subjectNames" && this.role != "ROLE_BANZHUREN") {  
971 - query["subjectName"] = this.query[key];  
972 - } else {  
973 - query[key] = this.query[key];  
974 - }  
975 - }  
976 - }  
977 - if (this.role == "ROLE_BANZHUREN") {  
978 - if (  
979 - query["subjectNames"] &&  
980 - query["subjectNames"].length == 1 &&  
981 - query["subjectNames"][0] == "全部"  
982 - ) {  
983 - query["subjectNames"] = this.subjectList.map((item) => {  
984 - return item.value;  
985 - });  
986 - query["subjectNames"].shift();  
987 - }  
988 - if (!query["subjectNames"]) {  
989 - this.$message.warning("请选择科目");  
990 - return; 239 + //去列表
  240 + goList() {
  241 + this.$router.push({
  242 + path: '/testList',
  243 + query: {
  244 + params: JSON.stringify(this.query)
991 } 245 }
992 - }  
993 - const exportPhaseExamReport =  
994 - this.role == "ROLE_BANZHUREN"  
995 - ? this.$request.cTExportPhaseExamReport  
996 - : this.$request.exportPhaseExamReport;  
997 - this.exportLoading = true;  
998 - const data = await exportPhaseExamReport({ ...query });  
999 - this.exportLoading = false;  
1000 - if (data && !data.code) {  
1001 - let blob = new Blob([data], {  
1002 - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",  
1003 - });  
1004 - downloadFile("即时测-阶段测练报表.xlsx", blob);  
1005 - } else {  
1006 - this.$message.error(data.info);  
1007 - }  
1008 - },  
1009 - async downExcel() {  
1010 - //模板下载  
1011 - this.loadingDown = true;  
1012 - let data = await this.$request.subjectiveScoreTemplate({  
1013 - examId: this.examId,  
1014 - });  
1015 - this.loadingDown = false;  
1016 - if (data && !data.code) {  
1017 - let blob = new Blob([data], {  
1018 - type: "application/vnd.ms-excel;charset=utf-8",  
1019 - });  
1020 - downloadFile(`主观题模版.xlsx`, blob);  
1021 - } else {  
1022 - this.$message.error(data.info);  
1023 - }  
1024 - }, 246 + })
  247 + }
1025 }, 248 },
1026 }; 249 };
1027 </script> 250 </script>
1028 -  
1029 <style> 251 <style>
1030 div::-webkit-scrollbar { 252 div::-webkit-scrollbar {
1031 width: 3px; 253 width: 3px;
1032 height: 10px; 254 height: 10px;
1033 } 255 }
  256 +
1034 div::-webkit-scrollbar-thumb { 257 div::-webkit-scrollbar-thumb {
1035 border-radius: 10px; 258 border-radius: 10px;
1036 background-color: #ccc; 259 background-color: #ccc;
1037 } 260 }
1038 </style> 261 </style>
1039 <style lang="scss" scoped> 262 <style lang="scss" scoped>
1040 -.page-container {  
1041 - position: relative; 263 +.main {
1042 height: 100%; 264 height: 100%;
1043 - &.active {  
1044 - overflow: hidden;  
1045 - } 265 + background: rgba($color: #000000, $alpha: .3);
  266 + display: flex;
  267 + justify-content: center;
1046 } 268 }
1047 -.table-box {  
1048 - margin: 0 20px;  
1049 - padding: 16px;  
1050 - background: #f8f8f8;  
1051 - border-radius: 5px;  
1052 - :deep(.fa-arrow-right) {  
1053 - padding-left: 2px; 269 +
  270 +.sel-dia {
  271 + margin-top: 100px;
  272 + width: 750px;
  273 + background: #fff;
  274 + border-radius: 10px;
  275 + overflow: hidden;
  276 + height: 460px;
  277 + display: flex;
  278 + flex-direction: column;
  279 +
  280 + .tit {
  281 + text-align: center;
  282 + position: relative;
  283 + padding: 20px 0 12px;
  284 + font-size: 18px;
  285 + font-weight: 500;
  286 + flex-shrink: 0;
  287 +
  288 + .el-icon-close {
  289 + position: absolute;
  290 + top: 0;
  291 + right: 0;
  292 + width: 30px;
  293 + height: 30px;
  294 + text-align: center;
  295 + line-height: 28px;
  296 + background: #e2e2e2;
  297 + border-radius: 0 0 0 24px;
  298 + box-sizing: border-box;
  299 + padding-left: 6px;
  300 + font-size: 18px;
  301 + cursor: pointer;
  302 +
  303 + &:hover {
  304 + color: #f30;
  305 + }
  306 + }
1054 } 307 }
1055 - :deep(.fa-file-text) {  
1056 - padding-left: 2px; 308 +
  309 + .select-box {
  310 + flex: 1;
  311 + overflow-y: auto;
  312 + padding: 0 30px;
  313 +
  314 + .sel-item {
  315 + display: flex;
  316 + align-items: center;
  317 + margin-bottom: 12px;
  318 +
  319 + .sel-label {
  320 + width: 60px;
  321 + margin-right: 10px;
  322 + flex-shrink: 0;
  323 + font-size: 15px;
  324 + font-weight: 500;
  325 + }
  326 +
  327 + :deep(.el-input__inner) {
  328 + height: 36px;
  329 + line-height: 36px;
  330 + border-radius: 18px;
  331 + }
  332 +
  333 + :deep(.el-input__suffix) {
  334 + .el-input__icon {
  335 + line-height: 36px;
  336 + }
  337 + }
  338 +
  339 + :deep(.el-input__inner) {
  340 + height: 36px;
  341 + line-height: 36px;
  342 + border-radius: 18px;
  343 +
  344 + .el-input__icon {
  345 + line-height: 36px;
  346 + }
  347 + }
  348 +
  349 + .el-date-editor.el-input,
  350 + .el-date-editor.el-input__inner {
  351 + width: 160px;
  352 + height: 36px;
  353 + line-height: 36px;
  354 +
  355 + :deep(.el-input__icon) {
  356 + line-height: 36px;
  357 + }
  358 + }
  359 + }
  360 +
  361 + .sel-item2 {
  362 + align-items: flex-start;
  363 + line-height: 20px;
  364 + padding-top: 10px;
  365 +
  366 + .p-all {
  367 + padding-bottom: 6px;
  368 + }
  369 + }
  370 +
  371 + .p1 {
  372 + .s1 {
  373 + margin-left: 20px;
  374 + cursor: pointer;
  375 + color: #7f7f7f;
  376 +
  377 + &:hover {
  378 + color: #409eff;
  379 + }
  380 +
  381 + &.active {
  382 + color: #667ffd;
  383 + }
  384 + }
  385 + }
  386 + }
  387 +
  388 + .foot-box {
  389 + flex-shrink: 0;
  390 + padding: 12px 0 20px;
  391 + display: flex;
  392 + justify-content: center;
  393 +
  394 + .el-button {
  395 + margin: 0 30px;
  396 + }
1057 } 397 }
1058 -}  
1059 -.down {  
1060 - padding-top: 16px;  
1061 -}  
1062 -.click-b {  
1063 - cursor: pointer;  
1064 - color: #409eff;  
1065 - text-decoration: underline;  
1066 } 398 }
1067 </style> 399 </style>
1068 \ No newline at end of file 400 \ No newline at end of file
src/views/basic/test/list.vue 0 → 100644
  1 +<template>
  2 + <div ref="main" class="page-container">
  3 + <back-box v-show="!isDetail">
  4 + <template slot="title">
  5 + <span>即时测-数据报表</span>
  6 + </template>
  7 + <template slot="btns">
  8 + <el-tooltip v-if="!code && gdClass" effect="dark" content="已归档试卷" placement="bottom">
  9 + <el-button type="primary" icon="fa fa-archive" size="mini" plain circle @click="toArchiving"></el-button>
  10 + </el-tooltip>
  11 + </template>
  12 + </back-box>
  13 + <div v-show="!isDetail" class="table-box" v-loading="loading">
  14 + <div v-if="!isMultipleClass">
  15 + <p class="btn-box">
  16 + <el-button type="primary" round @click="linkToDetail2">查看汇总报表</el-button>
  17 + </p>
  18 + <el-table :data="tableData" :max-height="tableMaxHeight" border style="width: 100%"
  19 + @selection-change="handleSelectionChange">
  20 + <el-table-column type="selection" width="40"></el-table-column>
  21 + <el-table-column prop="subjectName" label="科目" align="center"></el-table-column>
  22 + <el-table-column prop="className" label="班级" align="center"></el-table-column>
  23 + <el-table-column prop="title" label="试卷名称" align="center"></el-table-column>
  24 + <el-table-column prop="score" label="卷面分" align="center"></el-table-column>
  25 + <el-table-column label="测验人数/班级人数" align="center">
  26 + <template slot-scope="scoped">{{ `${scoped.row.answeredNum}/${scoped.row.classPersonNum}` }}</template>
  27 + </el-table-column>
  28 + <el-table-column prop="examStartTime" label="测验开始时间" align="center"></el-table-column>
  29 + <el-table-column label="操作" align="center">
  30 + <template slot-scope="scoped">
  31 + <el-tooltip v-if="scoped.row.answerNum != 0 || scoped.row.recordStatus != 0
  32 + " effect="dark" content="详情" placement="top">
  33 + <el-button type="primary" circle size="mini" icon="fa fa-arrow-right"
  34 + @click="linkTo(scoped.row)"></el-button>
  35 + </el-tooltip>
  36 + <template v-if="scoped.row.answerNum == 0">
  37 + <el-tooltip v-if="role != 'ROLE_BANZHUREN'" effect="dark" content="设置答案" placement="top">
  38 + <el-button type="primary" circle size="mini" icon="fa fa-file-text"
  39 + @click="edit(scoped.row)"></el-button>
  40 + </el-tooltip>
  41 + <template v-else>未设置答案</template>
  42 + </template>
  43 + <!-- <el-tooltip v-else effect="dark" content="答卷录分" placement="top">
  44 + <el-button type="primary" circle size="mini" @click="openScoreSet(scoped.row)">分</el-button>
  45 + </el-tooltip> -->
  46 + <el-tooltip effect="dark" content="答卷录分" placement="top">
  47 + <el-button type="primary" circle size="mini" @click="openScoreSet(scoped.row)">分</el-button>
  48 + </el-tooltip>
  49 + </template>
  50 + </el-table-column>
  51 + </el-table>
  52 + <div class="pagination-box">
  53 + <el-pagination small="" layout="total,prev, pager, next" :hide-on-single-page="true" :total="total"
  54 + @current-change="changePage" :current-page="page" :page-size="size">
  55 + </el-pagination>
  56 + </div>
  57 + <ScoreSet v-show="diaScoreSet" :role="role" :id="examId" :title="examTitlt" :examScore="examScore"
  58 + @closeScoreSet="closeScoreSet" />
  59 + </div>
  60 + <div v-else>
  61 + <el-table :data="tableData" :max-height="tableMaxHeight" border style="width: 100%">
  62 + <el-table-column prop="subjectName" label="科目" align="center"></el-table-column>
  63 + <el-table-column prop="classList" label="班级" align="center">
  64 + <template slot-scope="scoped"><span v-for="(item, index) in scoped.row.classList">{{
  65 + `${index == 0 ? '' : '/'}` + item.className
  66 + }}</span></template>
  67 + </el-table-column>
  68 + <el-table-column prop="title" label="试卷名称" align="center"></el-table-column>
  69 + <el-table-column prop="score" label="卷面分" align="center"></el-table-column>
  70 + <el-table-column label="操作" align="center">
  71 + <template slot-scope="scoped">
  72 + <el-button type="primary" circle size="mini" icon="el-icon-arrow-right"
  73 + @click="linkContrast(scoped.row)"></el-button>
  74 + </template>
  75 + </el-table-column>
  76 + </el-table>
  77 + <div class="pagination-box">
  78 + <el-pagination small="" layout="total,prev, pager, next" :hide-on-single-page="true" :total="total"
  79 + @current-change="changePage" :current-page="page" :page-size="size">
  80 + </el-pagination>
  81 + </div>
  82 + </div>
  83 + </div>
  84 + <router-view v-show="isDetail"></router-view>
  85 + </div>
  86 +</template>
  87 +
  88 +<script>
  89 +import ScoreSet from "./components/scoreSet.vue"
  90 +export default {
  91 + components: {
  92 + ScoreSet
  93 + },
  94 + data() {
  95 + return {
  96 + code: "",
  97 + gdClass: 0, //已归档班级数量
  98 + tableMaxHeight: null,
  99 + role: "",
  100 + loading: false,
  101 + diaScoreSet: false,
  102 + examId: "",//当前操作试卷
  103 + examTitlt: "",//当前操作试卷名称
  104 + examScore: 0,//当前操作试卷卷面总分
  105 + query: {
  106 + //搜索条件
  107 + classId: [],
  108 + subjectNames: [],
  109 + startDay: "",
  110 + endDay: "",
  111 + },
  112 + multipleSelection: [],
  113 + tableData: [],
  114 + page: 1,
  115 + size: 20,
  116 + total: 0,
  117 + isMultipleClass: false,
  118 + };
  119 + },
  120 + computed: {
  121 + isDetail: function () {
  122 + let bol = (this.$route.name == "即时测报表分析") ? true : false
  123 + return bol
  124 + }
  125 + },
  126 + async created() {
  127 + this.code = localStorage.getItem("csCode") || "";
  128 +
  129 + this.init()
  130 + },
  131 + mounted() {
  132 + this.tableMaxHeight = this.$refs.main.offsetHeight;
  133 + },
  134 + watch: {
  135 + "$route.query.params": function (nVal) {
  136 + let isFromTestDetail = sessionStorage.getItem("isFromTestDetail");
  137 + if (!isFromTestDetail && nVal) {
  138 + this.init()
  139 + }
  140 + }
  141 + },
  142 + methods: {
  143 + //初始化
  144 + init() {
  145 + const queryData = this.$route.query.params
  146 + queryData ? this.query = { ...this.query, ...JSON.parse(queryData) } : ''
  147 + console.log(this.query)
  148 + if (this.query.classId.length > 1) {
  149 + this.isMultipleClass = true
  150 + }
  151 + this.role =
  152 + this.$store.getters.info.showRole ||
  153 + this.$store.getters.info.permissions[0].role;
  154 + if (this.role != "ROLE_PERSONAL") {
  155 + this._QueryGdClass()
  156 + }
  157 + this.page = 1
  158 + this.total = 0
  159 + this.tableData = []
  160 + this._QueryData()
  161 + },
  162 + //归档列表
  163 + toArchiving() {
  164 + this.$router.push({
  165 + path: "/testArchiving",
  166 + });
  167 + },
  168 + //跳转单卷分析
  169 + linkTo(obj) {
  170 + //去详情
  171 + this.$router.push({
  172 + path: "/testAnalysis",
  173 + query: {
  174 + id: obj.id,
  175 + title: obj.title,
  176 + score: obj.examPaperScore || 0,
  177 + type: 1,
  178 + subject: obj.subjectName
  179 + },
  180 + });
  181 + },
  182 + //汇总跳转-多卷
  183 + linkToDetail2() {
  184 + if (this.multipleSelection.length == 0) {
  185 + this.$message.warning("请选择试卷!")
  186 + return
  187 + };
  188 + let subjectArr = []
  189 + const ids = this.multipleSelection.map(item => {
  190 + subjectArr.push(item.subjectName)
  191 + return item.id
  192 + })
  193 + subjectArr = [...new Set(subjectArr)]
  194 + console.log(subjectArr)
  195 + if (ids.length == 1) {
  196 + this.$router.push({
  197 + path: "/testAnalysis",
  198 + query: {
  199 + id: ids[0],
  200 + title: this.multipleSelection[0].title,
  201 + score: this.multipleSelection[0].examPaperScore || 0,
  202 + type: 1,
  203 + subjectName: subjectArr.join()
  204 + },
  205 + });
  206 + } else {
  207 + //去详情
  208 + this.$router.push({
  209 + path: "/testAnalysis",
  210 + query: {
  211 + ids: ids.join(),
  212 + classId: this.query.classId[0],
  213 + type: subjectArr.length == 1 ? 2 : 3,
  214 + subjectName: subjectArr.join()
  215 + },
  216 + });
  217 + }
  218 + },
  219 + // 多班对比
  220 + linkContrast(obj) {
  221 + this.$router.push({
  222 + path: "/testAnalysis",
  223 + query: {
  224 + ids: obj.classList.map(item => item.classId).join(),
  225 + subjectName: obj.subjectName,
  226 + title: obj.title,
  227 + type: 4
  228 + },
  229 + });
  230 + },
  231 + handleSelectionChange(val) {
  232 + this.multipleSelection = val;
  233 + },
  234 + //打开答卷录分
  235 + openScoreSet(obj) {
  236 + this.examId = obj.id;
  237 + this.examTitlt = obj.title;
  238 + this.examScore = obj.examScore;
  239 + this.diaScoreSet = true;
  240 + },
  241 + //关闭设置分数
  242 + closeScoreSet() {
  243 + this.diaScoreSet = false
  244 + },
  245 + //修改答案
  246 + edit(item) {
  247 + this.$router.push({
  248 + path: "/examinationPaperEdit",
  249 + query: {
  250 + paperId: item.id,
  251 + title: item.title,
  252 + type: 2,
  253 + },
  254 + });
  255 + },
  256 +
  257 + async _QueryGdClass() {
  258 + const fetchClassList =
  259 + this.role == "ROLE_BANZHUREN"
  260 + ? this.$request.cTClassList
  261 + : this.$request.tClassList;
  262 + const { data, status, info } = await fetchClassList({ status: 1 });
  263 + if (status === 0) {
  264 + this.gdClass = data?.list?.length || 0;
  265 + } else {
  266 + this.$message.error(info);
  267 + }
  268 + },
  269 + changePage(page) {
  270 + this.page = page;
  271 + this._QueryData();
  272 + },
  273 + async _QueryData() {
  274 + this.loading = true;
  275 + let query = {};
  276 + for (let key in this.query) {
  277 + if (this.query[key] != "") {
  278 + query[key] = this.query[key];
  279 + }
  280 + }
  281 + const examReportList = this.role == "ROLE_PERSONAL" ?
  282 + this.$request.pExamReportList : this.$request.examReportList
  283 + const { data, status, info } = await examReportList({
  284 + ...query,
  285 + page: this.page,
  286 + size: this.size,
  287 + });
  288 + this.loading = false;
  289 + if (status === 0) {
  290 + this.tableData = (data?.list && [...data?.list]) || [];
  291 + this.total = data?.count || 0;
  292 + } else {
  293 + this.$message.error(info);
  294 + }
  295 + },
  296 + },
  297 +};
  298 +</script>
  299 +
  300 +<style>
  301 +div::-webkit-scrollbar {
  302 + width: 3px;
  303 + height: 10px;
  304 +}
  305 +
  306 +div::-webkit-scrollbar-thumb {
  307 + border-radius: 10px;
  308 + background-color: #ccc;
  309 +}
  310 +</style>
  311 +<style lang="scss" scoped>
  312 +.page-container {
  313 + position: relative;
  314 + height: 100%;
  315 +
  316 + &.active {
  317 + overflow: hidden;
  318 + }
  319 +}
  320 +
  321 +.table-box {
  322 + margin: 20px;
  323 + border-radius: 5px;
  324 +
  325 + :deep(.fa-arrow-right) {
  326 + padding-left: 2px;
  327 + }
  328 +
  329 + :deep(.fa-file-text) {
  330 + padding-left: 2px;
  331 + }
  332 +}
  333 +
  334 +.down {
  335 + padding-top: 16px;
  336 +}
  337 +
  338 +.click-b {
  339 + cursor: pointer;
  340 + color: #409eff;
  341 + text-decoration: underline;
  342 +}
  343 +
  344 +.btn-box {
  345 + text-align: right;
  346 + padding: 0 12px 16px;
  347 +}
  348 +</style>
0 \ No newline at end of file 349 \ No newline at end of file