Commit 6bca489df6140d21609dd2d04323ddc06147d429

Authored by LH_PC
1 parent f45b3c05

云平台二期UI

Showing 42 changed files with 3994 additions and 1427 deletions
.vs/Ezquiz_Platform/FileContentIndex/55df62fa-5432-4cfd-bb10-cbdb5e263ba4.vsidx deleted
No preview for this file type
.vs/slnx.sqlite
No preview for this file type
src/App.vue
... ... @@ -18,70 +18,73 @@ export default {
18 18 const $app = this.$refs.app;
19 19 // 设置 屏幕 百分比 尺寸 适配
20 20 const standardScale = "100%" / "100%";
21   - var minHeight = 1080;
22 21 window.addEventListener(
23 22 "resize",
24 23 _.debounce(function () {
  24 +
25 25 const docHeight = document.body.clientHeight;
  26 +
26 27 const docWidth = document.body.clientWidth;
27   -
  28 +
28 29 if (docWidth < 1700) {
  30 +
29 31 const currentScale = docHeight / docWidth;
  32 +
30 33 let [scale, translate] = [0, 0];
  34 +
31 35 if (currentScale < standardScale) {
32 36 // 以高度计算
33 37 scale = docHeight / 1080;
  38 +
34 39 const shouleWidth = 1920 * scale;
35 40  
36 41 const offsetWidth = docWidth - shouleWidth;
  42 +
37 43 translate =
38 44 offsetWidth > 0 ? `translate(${offsetWidth / 2}px, 0)` : "";
  45 +
39 46 } else {
40 47 // 以宽度计算
41 48 scale = docWidth / 1920;
  49 +
42 50 const shouleHeight = 1080 * scale;
  51 +
43 52 const offsetHeight = docHeight - shouleHeight;
  53 +
44 54 translate =
45 55 offsetHeight > 0 ? `translate(0, ${offsetHeight / 2}px)` : "";
46   - }
47   -
48   - if (docHeight <= 600) {
49   - $app.style.cssText = `
50   - transform: scale(${scale}) ${translate};
51   - transform-origin: top left;
52   - min-width: 1920px;
53   - min-height:500px;
54   - `;
55   - }
  56 + }
  57 +
56 58 if (docHeight <= 700) {
  59 +
57 60 $app.style.cssText = `
58   - transform: scale(${scale}) ${translate};
59   - transform-origin: top left;
60   - min-width: 1920px;
61   - min-height:900px;
62   - `;
  61 + transform: scale(${scale}) ${translate};
  62 + transform-origin: top left;
  63 + min-width: 1920px;
  64 + min-height: 850px;
  65 + `;
63 66 }
64 67 else if (docHeight <= 750) {
  68 +
65 69 $app.style.cssText = `
66   - transform: scale(${scale}) ${translate};
67   - transform-origin: top left;
68   - min-width: 1920px;
69   - min-height:920px;
70   - `;
  70 + transform: scale(${scale}) ${translate};
  71 + transform-origin: top left;
  72 + min-width: 1920px;
  73 + min-height:920px;
  74 + `;
71 75 }
72 76 else {
73 77 $app.style.cssText = `
74   - transform: scale(${scale}) ${translate};
75   - transform-origin: top left;
76   - min-width: 1920px;
77   - min-height:1080px;
78   - `;
  78 + transform: scale(${scale}) ${translate};
  79 + transform-origin: top left;
  80 + min-width: 1920px;
  81 + min-height:1080px;
  82 + `;
79 83 }
80 84  
81 85 } else {
82 86 $app.style.cssText = '';
83 87 }
84   -
85 88 }),
86 89 300
87 90 );
... ... @@ -103,8 +106,7 @@ export default {
103 106 body {
104 107 margin: 0px;
105 108 padding: 0px;
106   - font-family: Microsoft YaHei, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, SimSun, sans-serif;
107   - font-size: 14px;
  109 + font-family: Microsoft YaHei, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, SimSun, sans-serif;
108 110 -webkit-font-smoothing: antialiased;
109 111 }
110 112  
... ...
src/api/apis/apis.js
... ... @@ -23,8 +23,14 @@ const downService = (url, data) =&gt; {
23 23 responseType: 'arraybuffer',
24 24 });
25 25 }
26   -export default {
27   - // 年级组长-成绩测验单
  26 +export default {
  27 + // 知识点
  28 + gKnowledge(section, subject) {
  29 + return defaltService(setUpUrls.gtestExamReport, {
  30 + ...subject, ...section
  31 + })
  32 + },
  33 + // 年级组长-成绩测验单
28 34 gTestExamReport(data) {
29 35 return defaltService(setUpUrls.gtestExamReport, data)
30 36 },
... ... @@ -60,7 +66,7 @@ export default {
60 66 gExportPhaseInteractiveReport(data) {
61 67 return downService(setUpUrls.gExportPhaseInteractiveReport, data)
62 68 },
63   -
  69 +
64 70 // 年级组长-首页统计数据
65 71 gIndex(data) {
66 72 return defaltService(setUpUrls.gIndex, data)
... ... @@ -146,8 +152,27 @@ export default {
146 152 return defaltService(setUpUrls.tClassList, data)
147 153 },
148 154 //任课老师-查询管理的班级
149   - tClassFromGrade(data) {
150   - return defaltGetService(setUpUrls.tClassFromGrade + "?classId=" + data)
  155 + tClassFromGrade(classId = null, subjectName = null) {
  156 + var requestParams = [];
  157 + if (classId) {
  158 + requestParams.push("classId=" + classId);
  159 + }
  160 + if (subjectName) {
  161 + requestParams.push("subjectName=" + subjectName);
  162 + }
  163 + var requestUrl = setUpUrls.tClassFromGrade + (requestParams.length >= 1 ? "?" + requestParams.join("&") : "");
  164 + return defaltGetService(requestUrl)
  165 + },
  166 + tClassGrade(grade = null, subjectName = null) {
  167 + var requestParams = [];
  168 + if (grade) {
  169 + requestParams.push("grade=" + grade);
  170 + }
  171 + if (subjectName) {
  172 + requestParams.push("subjectName=" + subjectName);
  173 + }
  174 + var requestUrl = setUpUrls.tClassGrade + (requestParams.length >= 1 ? "?" + requestParams.join("&") : "");
  175 + return defaltGetService(requestUrl)
151 176 },
152 177 tPaperDetail(data) {
153 178 return defaltService(setUpUrls.tPaperDetail, data)
... ... @@ -168,6 +193,18 @@ export default {
168 193 tClassdiffExamReport(data) {
169 194 return defaltService(setUpUrls.tclassdiffExamReport, data)
170 195 },
  196 + tgexportPhaseExamReport(data) {
  197 + return downService(setUpUrls.gExportPhaseExamReport, data)
  198 + },
  199 + tgexportPhaseExamReport2(data) {
  200 + return downService(setUpUrls.gexportPhaseExamReport2, data)
  201 + },
  202 + tgexportPhaseExamReport3(data) {
  203 + return downService(setUpUrls.gexportPhaseExamReport3, data)
  204 + },
  205 + tgexportPhaseExamReport4(data) {
  206 + return downService(setUpUrls.gexportPhaseExamReport4, data)
  207 + },
171 208 //任课老师-查询管理班级授课科目
172 209 tListExamReport(data) {
173 210 return defaltService(setUpUrls.tListExamReport, data)
... ... @@ -926,8 +963,12 @@ export default {
926 963 // 查询即时测多班默认等级列表
927 964 defaultLevels(data) {
928 965 return defaltService(setUpUrls.defaultLevels, data)
  966 + }, // 查询即时测多班默认等级列表
  967 + gdefaultLevels(data) {
  968 + return defaltService(setUpUrls.gdefaultLevels, data)
929 969 },
930 970  
  971 +
931 972 // 删除随堂问报表
932 973 deletePaperReport(data) {
933 974 return defaltService(setUpUrls.deletePaperReport, data)
... ...
src/api/urls/apis.js
1 1  
2 2 export default {
  3 + // 年级组长-查询报表列表
  4 + gKnowledge: "/api_html/knowledge/list",
3 5 // 年级组长-查询报表列表
4 6 gListExamReport: "/api_html/grade/manager/listExamReport",
5 7 // 年级组长-查询管理的班级
... ... @@ -8,6 +10,9 @@ export default {
8 10 gExportPhaseAnswerReport: "/api_html/grade/manager/exportPhaseAnswerReport",
9 11 // 年级组长-导出阶段测练
10 12 gExportPhaseExamReport: "/api_html/grade/manager/exportPhaseExamReport",
  13 + gexportPhaseExamReport2: "/api_html/grade/manager/exportPhaseExamReport2",
  14 + gexportPhaseExamReport3: "/api_html/grade/manager/exportPhaseExamReport3",
  15 + gexportPhaseExamReport4: "/api_html/grade/manager/exportPhaseExamReport4",
11 16 // 年级组长-导出阶段问答
12 17 gExportPhaseInteractiveReport: "/api_html/grade/manager/exportPhaseInteractiveReport",
13 18 // 年级组长-成绩测验单
... ... @@ -63,19 +68,21 @@ export default {
63 68 // 任课老师-班级情况对比
64 69 tclassdiffExamReport: "/api_html/teaching/classdiffExamReport",
65 70 tClassFromGrade: "/api_html/teaching/grade/classList",
  71 + tClassGrade:'/api_html/teaching/grade',
66 72 //任课老师-测验成绩单
67 73 tTestExamReport: "/api_html/teaching/testExamReport",
68 74 //任课老师-查询答题卡详情
69 75 tPaperDetail: "/api_html/teaching/paperDetail",
70 76 //任课老师-查询管理班级授课科目
71 77 tSubjectList: "/api_html/teaching/subjectList",
72   - tListExamReport: "/api_html/teaching/listExamReport",
  78 + tListExamReport: "/api_html/teaching/listExamReport",
73 79 //任课老师-分页查询课时报表列表
74 80 periodReportList: "/api_html/teaching/periodReportList",
75 81 //任课老师-查询阶段问答报表
76 82 phaseAnswerReport: "/api_html/teaching/phaseAnswerReport",
77 83 //任课老师-查询阶段互动报表
78 84 phaseInteractiveReport: "/api_html/teaching/phaseInteractiveReport",
  85 + exportPhaseExamReport: "/api_html/teaching/exportPhaseExamReport",
79 86 //任课老师-查询课时题目列表
80 87 periodQuestionList: "/api_html/teaching/periodQuestionList",
81 88 //任课老师-设置课时报表答案
... ... @@ -116,8 +123,7 @@ export default {
116 123 exportPhaseInteractiveReport: "/api_html/teaching/exportPhaseInteractiveReport",
117 124 //任课老师-导出单课时报表
118 125 exportPeriodReport: "/api_html/teaching/exportPeriodReport",
119   - //任课老师-导出阶段测练报表
120   - exportPhaseExamReport: "/api_html/teaching/exportPhaseExamReport",
  126 +
121 127 //任课老师-导出单卷测练报表
122 128 exportExamReport: "/api_html/teaching/exportExamReport",
123 129 //任课老师-查询学生列表
... ... @@ -475,6 +481,7 @@ export default {
475 481 exportExamMultiReport: "/api_html/teaching/exportExamMultiReport",
476 482 //查询即时测多班默认等级列表
477 483 defaultLevels: "/api_html/teaching/defaultLevels",
  484 + gdefaultLevels: "/api_html/grade/manager/defaultLevels",
478 485 //教学班模版下载
479 486 tClassAndStudentTemplate: "/api_html/school/manager/tClassAndStudentTemplate",
480 487 //教学班导出
... ...
src/assets/css/index.scss
... ... @@ -27,12 +27,29 @@
27 27 }
28 28 }
29 29  
  30 +.lowLevelClass {
  31 + color: white;
  32 + background: #FFA41C;
  33 + background-size: 200% 200%;
  34 + height: 100%;
  35 + width: 100%;
  36 +}
  37 +
  38 +.overflowText {
  39 + white-space: nowrap;
  40 + width: calc(100% - 5px); //文字宽度
  41 + overflow: hidden; //超出宽度隐藏
  42 + white-space: nowrap; //强制文字在一行
  43 + text-overflow: ellipsis; //文字溢出显示省略号
  44 +}
  45 +
30 46 .green-el-button {
31 47 background-color: rgba(65, 204, 149, 1);
32 48 color: white;
33 49 border-color: rgba(65, 204, 149, 1);
34 50  
35   - :focus,:hover {
  51 + :focus,
  52 + :hover {
36 53 background-color: rgba(65, 204, 149, 1);
37 54 color: white;
38 55 border-color: rgba(65, 204, 149, 1);
... ... @@ -56,7 +73,7 @@
56 73 flex-wrap: nowrap;
57 74  
58 75 .sel {
59   - width: 8%;
  76 + width: 10%;
60 77 min-width: 160px;
61 78 margin-right: 20px;
62 79 }
... ... @@ -78,7 +95,7 @@
78 95 }
79 96  
80 97 .input-with-select {
81   - width: 200px;
  98 + width: 230px;
82 99 height: 36px;
83 100 margin-right: 50px;
84 101 border-radius: 20px;
... ... @@ -290,6 +307,31 @@ ul {
290 307 }
291 308 }
292 309  
  310 +
  311 +.parent-number {
  312 + position: relative;
  313 +}
  314 +
  315 +.parent-number::after {
  316 + content: '%';
  317 + display: inline-block;
  318 + height: 20px;
  319 + line-height: 20px;
  320 + width: 20px;
  321 + text-align: center;
  322 + position: absolute;
  323 + right: 52px;
  324 + top: 50%;
  325 + transform: translateY(-50%);
  326 +}
  327 +
  328 +.parent-number .el-input__inner {
  329 + // 不加这行的话,当文本框里数值很大时,会和单位重叠
  330 + padding-left: 30px;
  331 + padding-right: 48px;
  332 +}
  333 +
  334 +
293 335 // 默认标题
294 336 .default-title {
295 337 height: 36px;
... ... @@ -302,6 +344,7 @@ ul {
302 344 text-transform: none;
303 345 }
304 346  
  347 +
305 348 // 默认实体
306 349 .default-body {
307 350 font-size: 14px;
... ... @@ -329,6 +372,9 @@ ul {
329 372 padding: 0px !important;
330 373  
331 374 .default-table {
  375 + width: 100% !important;
  376 + height: 100% !important;
  377 +
332 378 th {
333 379 font-weight: 400;
334 380 font-size: 14px;
... ... @@ -336,11 +382,14 @@ ul {
336 382 text-align: left;
337 383 font-style: normal;
338 384 text-transform: none;
339   - border:1px solid #ebeef5;
  385 + border: 1px solid #ebeef5;
340 386 }
341 387  
342   - tr,td {
343   - height: 40px; border:1px solid #ebeef5;
  388 + tr,
  389 + td {
  390 + height: 40px;
  391 + padding: 5px 0px !important;
  392 + border: 1px solid #ebeef5;
344 393 }
345 394 }
346 395  
... ... @@ -379,8 +428,8 @@ ul {
379 428 padding: 14px 20px !important;
380 429  
381 430 * {
382   - height: 32px;
383   - line-height: 32px;
  431 + height: 40px;
  432 + line-height: 40px;
384 433 }
385 434  
386 435 .filter-input,
... ... @@ -395,10 +444,14 @@ ul {
395 444  
396 445 input {
397 446 // border: 1px solid #DCDFE6;
398   - height: 31px;
  447 + height: calc(100% - 10px);
399 448 }
400 449 }
401 450  
  451 + .el-select__tags .el-tag {
  452 + height: 24px !important;
  453 + }
  454 +
402 455 .el-button {
403 456 width: auto;
404 457 line-height: 0px;
... ... @@ -409,4 +462,59 @@ ul {
409 462 background-color: rgb(107, 126, 245);
410 463 }
411 464 }
  465 +}
  466 +
  467 +@media screen and (max-width: 1921px) and (max-height: 1081px) {
  468 + * :not(.p1, .fa, .el-button, .el-icon-upload, h1, h2, h3, h4, h5, h6) {
  469 + font-size: 18px !important;
  470 +
  471 + .default-title {
  472 + font-size: 24px !important;
  473 + }
  474 +
  475 + .el-button * {
  476 + font-size: 16px !important;
  477 + }
  478 +
  479 + .el-select-dropdown__item * {
  480 + font-size: 16px !important;
  481 + }
  482 +
  483 + .el-form :not(h1, h2, h3, h4, h5, h6),
  484 + .el-dropdown-menu__item,
  485 + .el-cascader-node__label {
  486 + font-size: 16px !important;
  487 + }
  488 +
  489 + }
  490 +}
  491 +
  492 +@media screen and (min-width: 1921px) and (min-height: 1081px) {
  493 + * :not(.p1, .fa, .el-button, .el-icon-upload, h1, h2, h3, h4, h5, h6) {
  494 +
  495 + font-size: 14px !important;
  496 +
  497 + .default-body .default-filter * {
  498 + line-height: 38px !important;
  499 + }
  500 +
  501 + .card-content {
  502 + width: 48% !important;
  503 + }
  504 +
  505 + .default-title {
  506 + font-size: 24px !important;
  507 + }
  508 +
  509 + .el-select-dropdown__item * {
  510 + font-size: 12px !important;
  511 + }
  512 +
  513 + .el-form :not(h1, h2, h3, h4, h5, h6),
  514 + .el-dropdown-menu__item,
  515 + .el-cascader-node__label {
  516 + font-size: 12px !important;
  517 + }
  518 +
  519 + }
412 520 }
413 521 \ No newline at end of file
... ...
src/assets/images/example.jpg deleted

519 KB

src/components/backBox.vue
1 1 <template>
2   - <div class="back">
  2 + <div class="back default-title">
3 3 <div class="back-l" @click="back">
4   - <i class="fa fa-mail-reply-all"></i>
  4 + <i class="fa fa-mail-reply-all "></i>
5 5 <slot name="title"></slot>
6 6 </div>
7 7 <div class="back-r">
... ... @@ -55,7 +55,6 @@ export default {
55 55 align-items: center;
56 56 cursor: pointer;
57 57 flex-shrink: 0;
58   - font-size: 18px;
59 58 font-weight: 500;
60 59 }
61 60  
... ... @@ -66,7 +65,6 @@ export default {
66 65 }
67 66  
68 67 .fa-mail-reply-all {
69   - font-size: 28px;
70 68 color: #b3b3b3;
71 69 margin-right: 12px;
72 70 }
... ...
src/components/charts/lineChart.vue
... ... @@ -3,6 +3,7 @@
3 3 </template>
4 4  
5 5 <script>
  6 +import 'echarts/lib/component/dataZoom'
6 7 export default {
7 8 name: "lineChart",
8 9 props: {
... ... @@ -11,7 +12,7 @@ export default {
11 12 xAxis: Array,
12 13 colors: Array,
13 14 formatterYAxis: true,
14   - tooltipFormatter:false
  15 + tooltipFormatter: false
15 16 },
16 17 watch: {
17 18 params: {
... ... @@ -19,6 +20,7 @@ export default {
19 20 if (val.length) {
20 21 this.initData();
21 22 }
  23 + console.log(val)
22 24 },
23 25 deep: true,
24 26 },
... ... @@ -33,6 +35,43 @@ export default {
33 35 this.initData();
34 36 },
35 37 methods: {
  38 + extension(chart) {
  39 + // 注意这里,是以X轴显示内容过长为例,如果是y轴的话,需要把params.componentType == 'xAxis'改为yAxis
  40 + // 判断是否创建过div框,如果创建过就不再创建了
  41 + // 该div用来盛放文本显示内容的,方便对其悬浮位置进行处理
  42 + var elementDiv = document.getElementById('extension')
  43 + if (!elementDiv) {
  44 + var div = document.createElement('div')
  45 + div.setAttribute('id', 'extension')
  46 + div.style.display = 'block'
  47 + document.querySelector('html').appendChild(div)
  48 + }
  49 + chart.on('mouseover', function (params) {
  50 + if (params.componentType == 'xAxis') {
  51 + var elementDiv = document.querySelector('#extension')
  52 + //设置悬浮文本的位置以及样式
  53 + var elementStyle =
  54 + 'position: absolute;z-index: 99999;color: #fff;padding: 5px;display: inline;border-radius: 4px;background-color: #303133;box-shadow: rgba(0, 0, 0, 0.3) 2px 2px 8px'
  55 + elementDiv.style.cssText = elementStyle
  56 + elementDiv.innerHTML = params.value
  57 + document.querySelector('html').onmousemove = function (event) {
  58 + var elementDiv = document.querySelector('#extension')
  59 + var xx = event.pageX - 10
  60 + var yy = event.pageY + 15
  61 + elementDiv.style.top = yy + 'px'
  62 + elementDiv.style.left = xx + 'px'
  63 + }
  64 + }
  65 + })
  66 + chart.on('mouseout', function (params) {
  67 + //注意这里,我是以X轴显示内容过长为例,如果是y轴的话,需要改为yAxis
  68 + if (params.componentType == 'xAxis') {
  69 + var elementDiv = document.querySelector('#extension')
  70 +
  71 + elementDiv.style.cssText = 'display:none'
  72 + }
  73 + })
  74 + },
36 75 setOption() {
37 76 const that = this;
38 77 const options = {
... ... @@ -43,10 +82,27 @@ export default {
43 82 confine: true,
44 83 formatter(v) {
45 84 let html = `<p>${v.seriesName}</p>`
46   - html += `${v.marker} ${v.name}:${Number(v.value)}${that.tooltipFormatter?'%':''}`
  85 + html += `${v.marker} ${v.name}:${Number(v.value)}${that.tooltipFormatter ? '%' : ''}`
47 86 return html
48 87 },
49 88 },
  89 + dataZoom: [{
  90 + type: 'slider',//给x轴设置滚动条
  91 + show: true, //flase直接隐藏图形
  92 + xAxisIndex: [0],
  93 + bottom: 0,
  94 + height: 20,
  95 + showDetail: false,
  96 + startValue: 0,//滚动条的起始位置
  97 + endValue: 9 //滚动条的截止位置(按比例分割你的柱状图x轴长度)
  98 + },
  99 + {
  100 + type: 'inside',//设置鼠标滚轮缩放
  101 + show: true,
  102 + xAxisIndex: [0],
  103 + startValue: 0,
  104 + endValue: 9
  105 + }],
50 106 legend: {
51 107 show: true,
52 108 top: 0,
... ... @@ -54,18 +110,37 @@ export default {
54 110 itemHeight: 15,
55 111 icon: "circle"
56 112 },
  113 + grid: {
  114 + top: '3%',
  115 + right: '3%',
  116 + bottom: '3%',
  117 + left: '0%',
  118 + // 包含文本
  119 + containLabel: true,
  120 + // 是否显示网格线
  121 + show: true,
  122 + // 边框颜色
  123 + borderColor: 'rgba(0, 240, 255, 0.3)',
  124 + },
57 125 xAxis: {
58 126 type: "category",
59 127 data: this.xAxis,
60 128 axisLine: { show: true, lineStyle: { color: "#e2e2e2" } },
61 129 axisTick: {
  130 + alignWithLabel: false,
62 131 show: false,
63 132 },
  133 + triggerEvent: true,
64 134 axisLabel: {
65 135 color: "#333",
66 136 interval: 0,
67 137 width: Math.ceil(600 / this.xAxis.length),
68   - overflow: "breakAll"
  138 + formatter: function (value) {
  139 + if (value.length > 3) {
  140 + return `${value.slice(0, 3)}...`
  141 + }
  142 + return value
  143 + }
69 144 },
70 145 },
71 146 yAxis: {
... ... @@ -100,7 +175,7 @@ export default {
100 175 data: item.value,
101 176 };
102 177 }),
103   - };
  178 + };
104 179 return options;
105 180 },
106 181 initData() {
... ... @@ -112,6 +187,7 @@ export default {
112 187 this.chart?.clear();
113 188 this.chart.setOption(options, true);
114 189 this.chart.off("click");
  190 + this.extension(this.chart)
115 191 this.chart.on("click", "series", (params) => {
116 192 // this.$emit("clickPieChart", params);
117 193 });
... ...
src/components/charts/pieChart.vue
... ... @@ -99,7 +99,7 @@ export default {
99 99 };
100 100 </script>
101 101  
102   -<style lang="scss" scoped>
  102 +<style scoped>
103 103 .chart {
104 104 height: 100%;
105 105 }
... ...
src/components/lang/langSelect.vue
... ... @@ -40,12 +40,12 @@ export default {
40 40 }
41 41 </script>
42 42 <style>
43   - .international .el-dropdown-link { cursor: pointer; color: #666666; font-size: 14px; }
44   - .el-icon-arrow-down { font-size: 14px; }
  43 + .international .el-dropdown-link { cursor: pointer; color: #666666; }
  44 +
45 45 </style>
46 46 <style scoped>
47 47 .international-icon {
48   - font-size: 20px;
  48 +
49 49 cursor: pointer;
50 50 vertical-align: -5px !important;
51 51 }
... ...
src/components/setAnswer.vue
... ... @@ -82,8 +82,7 @@
82 82 <el-dialog :close-on-click-modal="false"
83 83 title="批量设置答案"
84 84 :visible.sync="diaSetAns"
85   - width="400" :append-to-body="true"
86   - :modal-append-to-body="false"
  85 + width="400" :append-to-body="true"
87 86 >
88 87 <div class="qs-options set-questions">
89 88 <p>{{ setSubPro(formAns.qusType) }}:</p>
... ...
src/config/index.js
... ... @@ -7,6 +7,7 @@ const modeUrl = {
7 7 },
8 8 // 生产环境
9 9 production: {
  10 + baseURL: "/api/",
10 11 authBaseURL: "",
11 12 $cdn:""
12 13 },
... ...
src/store/index.js
... ... @@ -56,7 +56,7 @@ const store = new Vuex.Store({
56 56 }
57 57  
58 58 let aRouters = addrouterList.filter((item) => {
59   -
  59 +
60 60 let path = item.children[0]?.path.replace("/", "");
61 61 if (routers?.includes(path) == true) return item;
62 62 else if (item.demoRoles?.includes(state.info.showRole) == true) return item;
... ... @@ -66,9 +66,9 @@ const store = new Vuex.Store({
66 66 return itemFilter.demoRoles?.includes(state.info.showRole) == true
67 67 });
68 68 if (item.children.length >= 1) return item;
69   - }
70   - return null;
71   - });
  69 + }
  70 + return null;
  71 + });
72 72 state.addRouters = aRouters; // 保存动态路由用来addRouter
73 73 state.routers = defaultRouter.concat(aRouters); // 所有有权限的路由表,用来生成菜单列表
74 74 localStorage.setItem("addRouters", JSON.stringify(routers));
... ... @@ -85,7 +85,8 @@ const store = new Vuex.Store({
85 85 },
86 86 setClasses(state, data) {
87 87 state.classes = data;
88   - localStorage.setItem("classes", data);
  88 + console.log(state)
  89 + localStorage.setItem('store', "classes", data);
89 90 },
90 91 setRefreshTestList(state, data) {
91 92 state.refreshTestList = data;
... ...
src/utils/index.js
... ... @@ -106,6 +106,32 @@ export function deepClone(obj) {
106 106 return result;
107 107 }
108 108  
  109 +export function getKnowledge(knowledge) {
  110 +
  111 + if (!knowledge) return "";
  112 +
  113 + var splitPoints = s.Split(',');
  114 +
  115 + var result = "";
  116 +
  117 + splitPoints.forEach(split => {
  118 +
  119 + var ss = split.Split('#').filter(dd => dd.length >= 1);
  120 +
  121 + if (ss.length > 0) {
  122 + result += ss[ss.Length - 1] + ";";
  123 + }
  124 + })
  125 +
  126 + if (result.length > 1) result = result.substring(0, result.length - 1);
  127 +
  128 + if (result.length == 1) {
  129 + return "";
  130 + }
  131 +
  132 + return result;
  133 +}
  134 +
109 135 // // 3DES加密
110 136 // export function desEncrypt (str, key = encryptKey, iv = encryptIV) {
111 137 // var cryptoKey = CryptoJS.enc.Utf8.parse(key)
... ... @@ -840,6 +866,7 @@ export function tablePrint(id, title, type = null) {
840 866 .tit{text-align:center;font-size:20px;color:#333;line-height:24px;font-weight:700;padding:10px 0;margin:0;}
841 867 .table-box,.el-table,.el-table__body-wrapper,.el-table--border{max-height:99999999px!important;height:auto;width:auto!important;max-width:1400px;margin: 0 auto;}
842 868 .el-table{width:100%}
  869 + .print-hidden{display:none;}
843 870 .el-table,.el-table__body-wrapper{max-height:auto}
844 871 .el-table .el-table__cell{padding:12px 0}
845 872 .el-table thead tr:first-child th.el-table__cell{border-top: 1px solid #ccc}
... ...
src/views/basic/askTestQuestion/components/askBzrMulti.vue
... ... @@ -50,7 +50,7 @@
50 50 }}</template>
51 51 </el-table-column>
52 52 </el-table-column>
53   - <el-table-column label="查看雷达图">
  53 + <el-table-column label="查看雷达图" fixed="right" width="100" align="center">
54 54 <template slot-scope="scoped">
55 55 <el-button type="text" @click="openRandarChart(scoped.row)">查看</el-button>
56 56 </template>
... ... @@ -63,32 +63,27 @@
63 63 <el-table class="default-table" :data="interactionList">
64 64 <el-table-column prop="studentCode" label="学号"></el-table-column>
65 65 <el-table-column prop="studentName" label="姓名"></el-table-column>
  66 + <el-table-column prop="interactionsNum全部科目" label="参与分"></el-table-column>
  67 + <el-table-column prop="interactionsCorrectNum全部科目" label="对错分"></el-table-column>
66 68 <el-table-column v-for="(item, index) in interactionOptions" :key="index" :label="item">
67   - <el-table-column v-if="index == 0" label="参与分" :prop="'interactionsNum' + item">
  69 +
  70 + <el-table-column label="互动数" :prop="'answerTimes' + item">
68 71 <template slot-scope="scoped">{{
69   - scoped.row["interactionsNum" + item] ||
70   - Number(scoped.row["interactionsNum" + item]) === 0
71   - ? scoped.row["interactionsNum" + item]
  72 + scoped.row["answerTimes" + item] ||
  73 + Number(scoped.row["answerTimes" + item]) === 0
  74 + ? scoped.row["answerTimes" + item]
72 75 : "-"
73 76 }}</template>
74 77 </el-table-column>
75   - <el-table-column v-else label="互动数" :prop="'interactionsNum' + item">
  78 + <el-table-column label="参与数" :prop="'interactionsNum' + item">
76 79 <template slot-scope="scoped">{{
77 80 scoped.row["interactionsNum" + item] ||
78 81 Number(scoped.row["interactionsNum" + item]) === 0
79 82 ? scoped.row["interactionsNum" + item]
80 83 : "-"
81   - }}</template>
82   - </el-table-column>
83   - <el-table-column v-if="index == 0" label="对错分" :prop="'interactionsCorrectNum' + item">
84   - <template slot-scope="scoped">{{
85   - scoped.row["interactionsCorrectNum" + item] ||
86   - Number(scoped.row["interactionsCorrectNum" + item]) === 0
87   - ? scoped.row["interactionsCorrectNum" + item]
88   - : "-"
89 84 }}</template>
90 85 </el-table-column>
91   - <el-table-column v-else label="参与数" :prop="'interactionsCorrectNum' + item">
  86 + <el-table-column label="答对数" :prop="'interactionsCorrectNum' + item">
92 87 <template slot-scope="scoped">{{
93 88 scoped.row["interactionsCorrectNum" + item] ||
94 89 Number(scoped.row["interactionsCorrectNum" + item]) === 0
... ... @@ -101,18 +96,16 @@
101 96 </el-row>
102 97 </div>
103 98 </div>
104   -
105   - <el-dialog :append-to-body="true" class="chart-dia" @close="radarChart.visible=false" :visible="radarChart.visible"
106   - :title="radarChart.title" width="800" >
  99 + <el-dialog :append-to-body="true" class="chart-dia" :visible.sync="redarVisible" :title="radarChart.title"
  100 + width="800">
107 101 <div class="chart-box">
108   - <RadarChart id="askRadarChart" :params="radarChart" :tooltipFormatter="true" />
  102 + <RadarChart id="radarChart" :params="radarChart" />
109 103 </div>
110 104 </el-dialog>
111 105 </div>
112 106 </template>
113 107 <script>
114   -import { formatDate } from "utils";
115   -import { downloadFile, tablePrint } from "@/utils";
  108 +import { downloadFile, tablePrint, formatDate } from "@/utils";
116 109 import RadarChart from "@/components/charts/radarChart";
117 110 export default {
118 111 name: "askbzrMutli",
... ... @@ -148,6 +141,7 @@ export default {
148 141 interactionList: [],
149 142 interactionOptions: [],
150 143 interactionSubjects: [],
  144 + redarVisible: false,
151 145 radarChart: {
152 146 title: "",
153 147 indicator: [
... ... @@ -174,7 +168,25 @@ export default {
174 168 await this._changeType();
175 169 },
176 170 methods: {
177   - _import() { },
  171 + async _import() {
  172 +
  173 + var importReport = this.currentType == '学生多科互动表现' ? this.$request.cTExportPhaseInteractiveReport : this.$request.cTExportPhaseAnswerReport;
  174 +
  175 + const data = await importReport({
  176 + periodIds: this.$props.askReportIds,
  177 + classIds: [this.$props.queryParams.class],
  178 + subjectNames: [...this.$props.queryParams.subjects],
  179 + });
  180 +
  181 + if (data) {
  182 + let blob = new Blob([data], {
  183 + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  184 + });
  185 + downloadFile(`随堂问-多科汇总分析报表.xlsx`, blob);
  186 + } else {
  187 + this.$message.error("下载失败");
  188 + }
  189 + },
178 190 _print() {
179 191  
180 192 tablePrint("print-content", this.currentType);
... ... @@ -227,7 +239,6 @@ export default {
227 239 return aTime;
228 240 },
229 241 async _multipleSubjectAnswers() {
230   -
231 242 const answersRequest =
232 243 this.role == "ROLE_PERSONAL"
233 244 ? this.$request.pPhaseAnswerReport
... ... @@ -236,10 +247,9 @@ export default {
236 247 let query = {
237 248 periodIds: this.$props.askReportIds,
238 249 classIds: [this.$props.queryParams.class],
239   - subjectNames: [this.$props.queryParams.subjectNames],
  250 + subjectNames: [...this.$props.queryParams.subjects],
240 251 };
241 252  
242   -
243 253 let answersResponse = await answersRequest({
244 254 ...query
245 255 });
... ... @@ -297,6 +307,7 @@ export default {
297 307 let query = {
298 308 periodIds: this.$props.askReportIds,
299 309 classIds: [this.$props.queryParams.class],
  310 + subjectNames: [...this.$props.queryParams.subjects],
300 311 };
301 312  
302 313 let interactionReponse = await interactionRequest({
... ... @@ -312,23 +323,25 @@ export default {
312 323  
313 324 this.interactionList = interactionReponse.data?.list?.map((item) => {
314 325 let params = {};
315   - item.dataList?.map((items, index) => {
316   - if (!subjectName.includes(items.subjectName)) {
  326 + item.dataList?.filter((items, index) => {
  327 + if (!subjectName.includes(items.subjectName) && items.subjectName != '全部科目') {
317 328 subjectName.push(items.subjectName);
318 329 }
  330 + params["answerTimes" + items.subjectName] =
  331 + items.answerTimes;
319 332 params["interactionsNum" + items.subjectName] =
320 333 items.interactionsNum;
321 334 params["interactionsCorrectNum" + items.subjectName] =
322 335 items.interactionsCorrectNum;
323 336 });
  337 +
324 338 return {
325 339 ...item,
326 340 ...params,
327 341 };
328 342 });
329   -
  343 + console.log(this.interactionList)
330 344 this.interactionOptions = [...subjectName];
331   - console.log(this.interactionOptions)
332 345 },
333 346 openRandarChart(obj) {
334 347 this.radarChart = {
... ... @@ -345,7 +358,7 @@ export default {
345 358 ],
346 359 seriesData: [],
347 360 };
348   - this.radarChart.title = obj.studentName + "-多科-多课时作答表现图";
  361 + this.radarChart.title = obj.studentName + "-多科阶段作答表现图";
349 362 let dataList = obj.dataList.slice(1, obj.dataList.length);
350 363 let subjectList = dataList.map((item) => item.subjectName);
351 364 subjectList.map((item, index) => {
... ... @@ -377,7 +390,7 @@ export default {
377 390 },
378 391 ];
379 392  
380   - this.radarChart.visible = true;
  393 + this.redarVisible = true;
381 394 }
382 395 }
383 396 };
... ...
src/views/basic/askTestQuestion/components/askListReport.vue
... ... @@ -3,11 +3,23 @@
3 3 <el-table class="default-table" :data="$props.datas" border>
4 4 <el-table-column prop="subjectName" label="科目" width="180" />
5 5 <el-table-column prop="title" label="课时名称" />
6   - <el-table-column prop="participationRate" label="总参与度" width="180" />
7   - <el-table-column prop="answerCorrectRate" label="已答正确率" width="180" />
8   - <el-table-column prop="classCorrectRate" label="班级正确率" width="180" />
  6 + <el-table-column prop="participationRate" label="总参与度" width="180" >
  7 + <template slot-scope="scoped">
  8 + {{ scoped.row.participationRate }}%
  9 + </template>
  10 + </el-table-column>
  11 + <el-table-column prop="answerCorrectRate" label="已答正确率" width="180" >
  12 + <template slot-scope="scoped">
  13 + {{ scoped.row.answerCorrectRate }}%
  14 + </template>
  15 + </el-table-column>
  16 + <el-table-column prop="classCorrectRate" label="班级正确率" width="180" >
  17 + <template slot-scope="scoped">
  18 + {{ scoped.row.classCorrectRate }}%
  19 + </template>
  20 + </el-table-column>
9 21 <el-table-column prop="questionNum" label="题目总数" width="180" />
10   - <el-table-column prop="startTime" label="上课时间" width="180" />
  22 + <el-table-column prop="startTime" label="上课时间" width="220" />
11 23 <el-table-column label="操作" width="200">
12 24 <template slot-scope="scoped">
13 25 <template v-if="scoped.row.answerNum == 0">
... ... @@ -42,9 +54,10 @@ export default {
42 54 id: dataRow.id,
43 55 });
44 56 if (status != 0) {
  57 + this.$message.success("删除成功!");
45 58 this.$message.error(info);
46 59 }
47   - this.$emit("resfer");
  60 + this.$emit("opration");
48 61 },
49 62 _linkToDetail(dataRow) {
50 63 this.$router.push({
... ...
src/views/basic/askTestQuestion/components/askSummaryReport.vue
... ... @@ -63,15 +63,15 @@
63 63 </div>
64 64 <div class="row-line">
65 65 <span class="line-subfix">总参与度:</span>
66   - <span class="line-value">{{ detail.participationRate }}</span>
  66 + <span class="line-value">{{ detail.participationRate ? detail.participationRate : 0 }}%</span>
67 67 </div>
68 68 <div class="row-line">
69 69 <span class="line-subfix">班级正确率:</span>
70   - <span class="line-value">{{ detail.classCorrectRate }}</span>
  70 + <span class="line-value">{{ detail.classCorrectRate ? detail.classCorrectRate : 0 }}%</span>
71 71 </div>
72 72 <div class="row-line">
73 73 <span class="line-subfix">已达正确率:</span>
74   - <span class="line-value">{{ detail.answerCorrectRate }}</span>
  74 + <span class="line-value">{{ detail.answerCorrectRate ? detail.answerCorrectRate : 0 }}%</span>
75 75 </div>
76 76 <div class="row-line">
77 77 <span class="line-subfix">反馈时长:</span>
... ... @@ -81,7 +81,7 @@
81 81 <el-row class="row-table">
82 82 <el-table class="default-table" :data="singleSubjectSummary" border>
83 83 <el-table-column prop="title" label="课时-题号" />
84   - <el-table-column label="题干" width="120">
  84 + <el-table-column label="题干" width="80">
85 85 <template slot-scope="scoped">
86 86 <el-button type="text" @click="openStem(scoped.row)">查看</el-button>
87 87 </template>
... ... @@ -91,18 +91,26 @@
91 91 </el-table-column>
92 92 <el-table-column prop="answeredNum" label="答题人数" width="100" />
93 93 <el-table-column prop="correctAnswerNum" label="答对人数" width="100" />
94   - <el-table-column prop="participationRate" label="班级参与度(单题)" width="150">
  94 + <el-table-column prop="participationRate" label="班级参与度(单题)" width="170">
95 95 <template slot-scope="scoped">{{ scoped.row.participationRate }}%</template>
96 96 </el-table-column>
97   - <el-table-column prop="classCorrectRate" label="班级正确率(单题)" width="150">
  97 + <el-table-column prop="classCorrectRate" label="班级正确率(单题)" width="170">
98 98 <template slot-scope="scoped">{{ scoped.row.classCorrectRate }}%</template>
99 99 </el-table-column>
100 100  
101   - <el-table-column prop="answerCorrectRate" label="已答正确率(单题)" width="150">
  101 + <el-table-column prop="answerCorrectRate" label="已答正确率(单题)" width="170">
102 102 <template slot-scope="scoped">{{ scoped.row.answerCorrectRate }}%</template>
103 103 </el-table-column>
104 104  
105   - <el-table-column prop="knowledge" label="知识点(单题)" width="150" />
  105 + <el-table-column prop="knowledge" label="知识点(单题)" width="150">
  106 + <template slot-scope="scoped">
  107 + <el-tooltip effect="dark" :content="scoped.row.knowledge" placement="left">
  108 + <span class="overflowText">
  109 + {{ scoped.row.knowledge }}
  110 + </span>
  111 + </el-tooltip>
  112 + </template>
  113 + </el-table-column>
106 114 <el-table-column prop="correctAnswer" label="正确答案(单题)" width="150">
107 115 <template slot-scope="scoped">
108 116 {{
... ... @@ -182,7 +190,7 @@
182 190 <el-table-column prop="correctRate" label="总正确率" width="120">
183 191 <template slot-scope="scoped">{{ scoped.row.correctRate }}%</template>
184 192 </el-table-column>
185   - <el-table-column prop="correctRateRank" label="总正确率排名" width="120" />
  193 + <el-table-column prop="correctRateRank" label="总正确率排名" width="140" />
186 194 <el-table-column prop="answerCorrectRate" label="已答正确率" width="120">
187 195 <template slot-scope="scoped">{{ scoped.row.answerCorrectRate }}%</template>
188 196 </el-table-column>
... ... @@ -203,20 +211,20 @@
203 211 <el-table-column prop="interactionsCorrectNum" label="对错得分" width="210" />
204 212 <el-table-column prop="rushAnswerTimes" label="抢答成功次数" width="210" />
205 213 <el-table-column prop="rushAnswerCorrectTimes" label="抢答答对次数" width="210" />
206   - <el-table-column prop="checkAnswerTimes" label="被抽打次数" width="210" />
207   - <el-table-column prop="checkAnswerCorrectTimes" label="抽打答对次数" width="210" />
  214 + <el-table-column prop="checkAnswerTimes" label="被抽答次数" width="210" />
  215 + <el-table-column prop="checkAnswerCorrectTimes" label="抽答答对次数" width="210" />
208 216 </el-table>
209 217 </el-row>
210 218 </div>
211 219 </div>
212   - <el-dialog :append-to-body="true" class="chart-dia" :visible.sync="lineChart.visible" :title="lineChart.title" width="800"
213   - >
  220 + <el-dialog :append-to-body="true" class="chart-dia" :visible.sync="lineChart.visible" :title="lineChart.title"
  221 + width="800">
214 222 <div class="chart-box">
215 223 <LineChart id="askLineChart" :params="lineChart.data" :xAxis="lineChart.xAxis"
216 224 :tooltipFormatter="true" />
217 225 </div>
218 226 </el-dialog>
219   - <el-dialog :append-to-body="true" class="stem" :visible.sync="stem.visible" :title="'题干'" width="800" >
  227 + <el-dialog :append-to-body="true" class="stem" :visible.sync="stem.visible" :title="'题干'" width="800">
220 228 <iframe v-if="stem && stem.src" :src="stem.src" style="width: 100%;min-height: 400px;" />
221 229 </el-dialog>
222 230 <ExportDia :exportStudent="exportStudent" :diaShow="diaShow" @cancel="cancel" @exportData="_exportData"
... ... @@ -224,7 +232,7 @@
224 232 </div>
225 233 </template>
226 234 <script>
227   -import { formatDate } from "utils";
  235 +import { formatDate,getKnowledge } from "utils";
228 236 import { downloadFile, tablePrint } from "@/utils";
229 237 import LineChart from "@/components/charts/lineChart";
230 238 export default {
... ... @@ -234,7 +242,8 @@ export default {
234 242 },
235 243 props: {
236 244 askReportIds: Array,
237   - queryParams: Object
  245 + queryParams: Object,
  246 + role: "",
238 247 },
239 248  
240 249 watch: {
... ... @@ -287,9 +296,9 @@ export default {
287 296 this.diaShow = true;
288 297 },
289 298 _print() {
290   - let title = this.detail.title || this.subjectNames.join();
291   -
292   - tablePrint("print-content", title + "_" + this.currentType);
  299 + let title = this.detail.title || this.subjectNames.join();
  300 +
  301 + tablePrint("print-content", title + "_" + this.currentType);
293 302 },
294 303 cancel() {
295 304 this.diaShow = false;
... ... @@ -333,7 +342,7 @@ export default {
333 342 } else {
334 343 this.$message.error("下载失败");
335 344 }
336   - },
  345 + },
337 346 async refresh() {
338 347 await this._changeType();
339 348 await this._detail();
... ... @@ -366,21 +375,30 @@ export default {
366 375 return tit;
367 376 },
368 377 setDuration(times) {
  378 +
  379 + if (!Number(times)) return "0分0秒";
369 380 let m = parseInt(times / 1000 / 60);
370 381 let s = parseInt((times / 1000) % 60);
371 382 let ms = times;
372 383 let aTime;
  384 +
373 385 if (times == 0) {
374 386 aTime = `0`;
375 387 } else {
376 388 if (m == 0 && s == 0) {
377 389 aTime = `${ms}毫秒`;
378   - } else if (m == 0 && s != 0) {
  390 + } else if (m == 0) {
379 391 aTime = `${s}秒`;
380   - } else if (m != 0 && s != 0) {
381   - aTime = `${m}分${s}秒`;
  392 + } else {
  393 + if (s == 0) {
  394 + aTime = `${m}分`;
  395 + }
  396 + else {
  397 + aTime = `${m}分${s}秒`;
  398 + }
382 399 }
383 400 }
  401 + // c=(aTime);
384 402 return aTime;
385 403 },
386 404 async _detail() {
... ... @@ -495,7 +513,8 @@ export default {
495 513 this.total = interactiveListReponse.data.count;
496 514 },
497 515 openLineChart(chartRow) {
498   - this.lineChart.title = `${chartRow.studentName}-${this.currentType}`;
  516 + var subejct = this.$props.role == 'ROLE_BANZHUREN' ? this.$props.queryParams.subjects[0] : this.$props.queryParams.subject;
  517 + this.lineChart.title = `${chartRow.studentName}-${subejct}-多课时作答表现图`;
499 518 this.lineChart.visible = true;
500 519 let participationRate = [];
501 520 let correctRate = [];
... ... @@ -519,8 +538,7 @@ export default {
519 538 name: "已答正确率",
520 539 value: answerCorrectRate,
521 540 },
522   - ];
523   - console.log(this.lineChart)
  541 + ];
524 542 },
525 543 openStem(stemRow) {
526 544 this.stem.src = stemRow.screenshot ?? "";
... ... @@ -553,7 +571,7 @@ export default {
553 571 }
554 572  
555 573 .row-line {
556   - width: calc(20% - 2px);
  574 + width: calc(20% - 4px);
557 575 border: 1px solid #ebeef5;
558 576 background: #f5f7fa;
559 577 display: inline-block;
... ...
src/views/basic/askTestQuestion/components/testBzrMulti.vue
... ... @@ -9,21 +9,14 @@
9 9 </div>
10 10 </el-row>
11 11 <el-row class="row-table">
12   - <el-table class="default-table" :data="$props.list">
13   - <el-table-column width="48">
14   - <template slot="header">
15   - <el-checkbox v-model="checkedAll" @change="_checkAll"></el-checkbox>
16   - </template>
17   - <template slot-scope="scope">
18   - <el-checkbox v-model="multipleSelection" :label="scope.row.id"
19   - :disabled="_checkboxDisabled(scope.row)"><span></span></el-checkbox>
20   - </template>
21   - </el-table-column>
22   - <el-table-column prop="subjectName" label="科目"></el-table-column>
23   - <el-table-column prop="className" label="班级"></el-table-column>
  12 + <el-table class="default-table" :data="$props.list" @selection-change="_tableSelectedChange">
  13 + <el-table-column type="selection" width="48" :selectable="_checkboxDisabled" />
  14 +
  15 + <el-table-column prop="subjectName" label="科目" width="100"></el-table-column>
  16 + <el-table-column prop="className" label="班级" width="100"></el-table-column>
24 17 <el-table-column prop="title" label="试卷名称"></el-table-column>
25   - <el-table-column prop="examPaperScore" label="卷面分"></el-table-column>
26   - <el-table-column label="测验人数/班级人数">
  18 + <el-table-column prop="examPaperScore" label="卷面分" width="100"></el-table-column>
  19 + <el-table-column label="测验人数/班级人数" width="200">
27 20 <template slot-scope="scoped">
28 21 {{ `${scoped.row.answeredNum}/${scoped.row.classPersonNum}` }}
29 22 </template>
... ... @@ -44,7 +37,7 @@
44 37 </div>
45 38 </el-row>
46 39 <el-row class="row-table">
47   - <el-table :maxHeight="660" :data="selectedList" style="width: 100%" class="default-table">
  40 + <el-table :data="selectedList" style="width: 100%" class="default-table">
48 41 <el-table-column prop="studentCode" label="学号" fixed></el-table-column>
49 42  
50 43 <el-table-column prop="studentName" label="姓名" fixed>
... ... @@ -106,10 +99,10 @@
106 99 </el-container>
107 100  
108 101 </div>
109   - <el-dialog class="chart-dia" :visible.sync="radarChart.visible" :title="radarChart.title" width="800"
  102 + <el-dialog class="chart-dia" :visible.sync="redarVisible" :title="radarChart.title" width="800"
110 103 :append-to-body="true">
111 104 <div class="chart-box">
112   - <RadarChart id="askRadarChart" :params="radarChart" :tooltipFormatter="true" />
  105 + <RadarChart id="testRadarChart" :params="radarChart" />
113 106 </div>
114 107 </el-dialog>
115 108 </div>
... ... @@ -151,6 +144,7 @@ export default {
151 144 answerList: [],
152 145 multipleSelection: [],
153 146 multipleSelectionObj: {},
  147 + redarVisible: false,
154 148 radarChart: {
155 149 title: "",
156 150 indicator: [
... ... @@ -177,16 +171,53 @@ export default {
177 171 },
178 172 methods: {
179 173 _print() {
  174 + tablePrint("print-content", this.currentType);
  175 + },
  176 + _checkAll() {
  177 + // this.multipleSelection = [...]
  178 + },
  179 + _tableSelectedChange(values) {
180 180  
  181 + this.multipleSelection = values.map(items => items.id);
  182 + },
  183 + async _import() {
181 184  
182   - tablePrint("print-content", this.currentType);
  185 + var testReport = this.$request.cTExportPhaseExamReport;
  186 +
  187 + var classIds = [];
  188 + var subjects = [];
  189 + var ids = [];
  190 +
  191 + this.$props.list?.map((item) => {
  192 + if (this.multipleSelection.includes(item.id)) {
  193 + subjects.push(item.subjectName);
  194 + classIds.push(item.classId);
  195 + }
  196 + });
  197 +
  198 + ids = [...this.multipleSelection];
  199 +
  200 +
  201 + const data = await testReport({
  202 + classIds: classIds,
  203 + examIds: ids,
  204 + subjectNames: subjects
  205 + });
  206 +
  207 + if (data) {
  208 + let blob = new Blob([data], {
  209 + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  210 + });
  211 + downloadFile(`即时测-多科汇总分析报表.xlsx`, blob);
  212 + } else {
  213 + this.$message.error("下载失败");
  214 + }
183 215 },
184   - _checkAll() { },
185 216 _checkboxDisabled(obj) {
186 217 if (obj.examStartTime) {
187   - return false;
188   - } else {
189 218 return true;
  219 + } else {
  220 + return false;
190 221 }
191 222 },
192 223 async refresh() {
... ... @@ -245,28 +276,36 @@ export default {
245 276 this.exportStudent = [];
246 277 },
247 278 openRandarChart(obj) {
  279 +
  280 + let max = 0;
  281 +
  282 + const dataList = obj.dataList.slice(1, obj.dataList.length);
  283 + let subjectList = dataList.map((item) => {
  284 + let score = Number(item.highestScore || item.score);
  285 + max = score > max ? score : max;
  286 + return item.subjectName;
  287 + });
  288 + max += 10;
  289 + max = max > 150 ? 150 : max;
248 290 this.radarChart = {
249 291 indicator: [
250 292 {
251 293 name: "",
252   - max: 100,
  294 + max: max,
253 295 axisLabel: {
254 296 show: true,
255 297 showMaxLabel: true,
256   - formatter: "{value}%",
257 298 },
258 299 },
259 300 ],
260 301 seriesData: [],
261 302 };
262   - this.radarChart.title = obj.studentName + "-多科-多课时作答表现图";
263   - let dataList = obj.dataList.slice(1, obj.dataList.length);
264   - let subjectList = dataList.map((item) => item.subjectName);
265 303 subjectList.map((item, index) => {
266 304 if (index < 1) {
267 305 this.radarChart.indicator[index].name = item;
  306 + this.radarChart.indicator[index].max = max;
268 307 } else {
269   - this.radarChart.indicator.push({ name: item, max: 100 });
  308 + this.radarChart.indicator.push({ name: item, max: max });
270 309 }
271 310 });
272 311 // 为了美观
... ... @@ -274,31 +313,36 @@ export default {
274 313 let num = this.radarChart.indicator.length;
275 314 for (let i = 0; i < 6; i++) {
276 315 if (i >= num) {
277   - this.radarChart.indicator.push({ name: "", max: 100 });
  316 + this.radarChart.indicator.push({ name: "", max: max });
278 317 }
279 318 }
280 319 }
281   - let participationRate = dataList.map((item) => item.participationRate);
282   - let correctRate = dataList.map((item) => item.correctRate);
283 320 this.radarChart.seriesData = [
284 321 {
285   - value: participationRate,
286   - name: "参与度",
  322 + value: dataList.map((item) => item.highestScore),
  323 + name: "班级最高分",
287 324 },
288 325 {
289   - value: correctRate,
290   - name: "正确率",
  326 + value: dataList.map((item) => item.avgScore),
  327 + name: "班平均分",
291 328 },
292   - ];
  329 + {
  330 + value: dataList.map((item) => item.score),
  331 + name: "本人得分",
  332 + },
  333 + ];
293 334  
294   - this.radarChart.visible = true;
  335 + this.radarChart.title = obj.studentName + "-多科阶段作答表现图";
  336 + console.log(this.radarChart)
  337 + this.redarVisible = true;
295 338 },
296 339 async _loadData() {
  340 +
297 341 var classIds = [];
298 342 var subjects = [];
299 343 var ids = [];
300   -
301 344 this.$props.list?.map((item) => {
  345 +
302 346 if (this.multipleSelection.includes(item.id)) {
303 347 subjects.push(item.subjectName);
304 348 classIds.push(item.classId);
... ... @@ -326,6 +370,7 @@ export default {
326 370 if (!subjectName.includes(items.subjectName)) {
327 371 subjectName.push(items.subjectName);
328 372 }
  373 + console.log(items)
329 374 params["examCount" + items.subjectName] = items.examCount;
330 375 params["participationCount" + items.subjectName] =
331 376 items.participationCount;
... ...
src/views/basic/askTestQuestion/components/testListReport.vue
1 1 <template>
2 2 <div ref="main">
3   - <el-table class="default-table" :data="tableData">
  3 + <el-table v-if="$props.datas" class="default-table" :data="$props.datas">
4 4 <el-table-column prop="subjectName" label="科目" width="180" />
5   - <el-table-column prop="className" label="班级" width="180" />
  5 + <el-table-column prop="className" label="班级" width="130" />
6 6 <el-table-column prop="title" label="报表名称" />
7   - <el-table-column prop="examPaperScore" label="卷面分" width="180" />
  7 + <el-table-column prop="examPaperScore" label="卷面分" width="130" />
8 8 <el-table-column prop="classCorrectRate" label="测验人数/班级人数" width="180">
9 9 <template slot-scope="scoped">{{ `${scoped.row.answeredNum}/${scoped.row.classPersonNum}` }}</template>
10 10 </el-table-column>
11   - <el-table-column prop="questionNum" label="测验时长" width="180" />
12   - <el-table-column prop="createdTime" label="测验开始时间" width="180" />
  11 + <el-table-column prop="questionNum" label="测验时长" width="130" />
  12 + <el-table-column prop="createdTime" label="测验开始时间" width="210" />
13 13 <el-table-column label="操作" width="240">
14 14 <template slot-scope="scoped">
15   - <el-tooltip v-if="scoped.row.answerNum != 0 ||
  15 + <el-button style="margin-right: 10px;" v-if="scoped.row.answerNum != 0 ||
16 16 (scoped.row.recordStatus != 0 &&
17 17 scoped.row.subjectiveScore == scoped.row.examPaperScore)
18   - " effect="dark" content="详情" style="margin-right: 10px;" placement="top">
19   - <el-button type="text" @click="_linkToDetail(scoped.row)">查看</el-button>
20   - </el-tooltip>
21   - <el-popconfirm style="margin-right: 10px;" title="确定删除这张答题卡吗?" @confirm="_removeReport(scoped.row)">
  18 + " type="text" @click="_linkToDetail(scoped.row)">查看</el-button>
  19 + <el-popconfirm style="margin-right: 10px;" title="确定删除这次记录吗?" @confirm="_removeReport(scoped.row)">
22 20 <el-button style="color:red; " slot="reference" class="delete" type="text">
23 21 删除
24 22 </el-button>
25 23 </el-popconfirm>
26   - <template v-if="scoped.row.answerNum == 0 &&
27   - scoped.row.subjectiveScore != scoped.row.examPaperScore
28   - ">
29   - <el-tooltip v-if="role != 'ROLE_BANZHUREN'" effect="dark" content="设置答案" placement="top">
30   - <el-button type="text" icon="fa fa-file-text" @click="edit(scoped.row)"></el-button>
31   - </el-tooltip>
32   - <template v-else>未设置答案</template>
  24 + <template
  25 + v-if="scoped.row.answerNum == 0 && scoped.row.subjectiveScore != scoped.row.examPaperScore">
  26 + <el-button style="margin-right: 10px;" v-if="role != 'ROLE_BANZHUREN'" type="text"
  27 + @click="edit(scoped.row)">设置答案</el-button>
  28 + <template v-else> <span style="margin-right: 10px;">未设置答案</span> </template>
33 29 </template>
34 30 <template v-if="role != 'ROLE_BANZHUREN' && scoped.row.examPaperId != 0">
35 31 <template>
36 32 <el-popover placement="bottom" ref="popoverRef">
37   - <div style="display: flex" v-loading="scoped.row.showSelect == 0 ||
38   - scoped.row.showSelect == 1
39   - ? false
40   - : true
41   - ">
42   - <el-button v-if="scoped.row.showSelect == 0" size="mini"
  33 + <div style="display: flex">
  34 + <el-button v-if="scoped.row.showSelect == 0"
43 35 @click="openScoreSet(scoped.row, 1)">录入总得分</el-button>
44   - <el-button type="primary" size="mini"
45   - @click="openScoreSet(scoped.row, 2)">录入小题分</el-button>
  36 + <el-button type="primary" @click="openScoreSet(scoped.row, 2)">录入小题分</el-button>
46 37 </div>
47   - <el-button slot="reference" type="text"
  38 + <el-button style="margin-right: 10px;" slot="reference" type="text"
48 39 @click="queryStatus(scoped.row)">录入分数</el-button>
49 40 </el-popover>
50 41 </template>
... ... @@ -62,12 +53,17 @@ import ScoreSet from &quot;../../test/components/scoreSet.vue&quot;;
62 53 export default {
63 54 name: "testListReport",
64 55 props: {
65   - datas: Array,
  56 + datas: Array || null,
66 57 },
67 58 components: {
68 59 ScoreSet
69 60 },
70 61 watch: {
  62 + 'diaScoreSet'(value) {
  63 + if (value == false) {
  64 + // this.$emit('opration');
  65 + }
  66 + },
71 67 '$props.datas'(value) {
72 68 if (this.role == "ROLE_BANZHUREN") {
73 69 this.isMultipleClass = false;
... ... @@ -84,12 +80,13 @@ export default {
84 80 return item;
85 81 }) || [];
86 82 }
87   - },
  83 + }
88 84 },
89 85 created() {
90 86 this.role =
91 87 this.$store.getters.info.showRole ||
92 88 this.$store.getters.info.permissions[0].role;
  89 +
93 90 },
94 91 methods: {
95 92 _linkToDetail(dataRow) {
... ... @@ -113,13 +110,12 @@ export default {
113 110 this.diaScoreSet = true;
114 111 },
115 112 async _removeReport(obj, index) {
116   - this.tableData[index].loading = true;
117 113 const { data, status, info } = await this.$request.deleteReport({
118 114 id: obj.id,
119 115 });
120 116 if (status === 0) {
121 117 this.$message.success("删除成功!");
122   - this._QueryData();
  118 + this.$emit('opration');
123 119 } else {
124 120 this.$message.error(info);
125 121 }
... ... @@ -143,7 +139,7 @@ export default {
143 139 },
144 140 //修改分数成功
145 141 SuccessScoreSet() {
146   - this._QueryData();
  142 + this.$emit('opration');
147 143 this.closeScoreSet();
148 144 },
149 145 //修改答案
... ...
src/views/basic/askTestQuestion/components/testMultiClassReport.vue
... ... @@ -8,19 +8,19 @@
8 8 </el-row>
9 9 <el-row class="row-type" style="margin-top: 10px;">
10 10 <el-table v-if="$props.params" class="default-table" :data="listReport">
11   - <el-table-column prop="subjectName" label="科目" width="180" />
12   - <el-table-column prop="paperName" label="试卷名称" width="240" />
  11 + <el-table-column prop="subjectName" label="科目" width="100" />
  12 + <el-table-column prop="paperName" label="试卷名称" />
13 13 <el-table-column prop="classCorrectRate" label="已考班级">
14 14 <template slot-scope="scoped">
15 15 <el-checkbox-group v-model="scoped.row.checkedClassList">
16   - <el-checkbox v-for="(item, index) in scoped.row.classInfos" :label="item.classId">
  16 + <el-checkbox :key="index" v-for="(item, index) in scoped.row.classInfos" :label="item.classId">
17 17 {{ item.className }}
18 18 </el-checkbox>
19 19 </el-checkbox-group>
20 20 </template>
21 21 </el-table-column>
22   - <el-table-column prop="score" label="卷面分" width="180" />
23   - <el-table-column label="操作" width="240">
  22 + <el-table-column prop="score" label="卷面分" width="100" />
  23 + <el-table-column label="操作" width="100">
24 24 <template slot-scope="scoped">
25 25 <el-button type="text" @click="_linkToDetail(scoped.row)">查看</el-button>
26 26 </template>
... ... @@ -48,9 +48,7 @@ export default {
48 48 }
49 49 },
50 50 methods: {
51   - _linkToDetail(dataRow) {
52   -
53   - console.log(dataRow)
  51 + _linkToDetail(dataRow) {
54 52 this.$router.push({
55 53 path: "/testReportDetail",
56 54 query: {
... ... @@ -59,15 +57,16 @@ export default {
59 57 id: dataRow.paperId,
60 58 title: dataRow.paperName,
61 59 subjectName: dataRow.subjectName,
  60 + diffType: this.currentType,
62 61 },
63 62 });
64 63 },
65 64 async _loadDatas() {
66   -
  65 +
67 66 var dataRequestParams = {
68 67 classIds: this.$props.params.class ? [this.$props.params.class] :
69 68 this.$props.params.classIds ? [...this.$props.params.classIds] : null,
70   - diffType: this.currentType == "任课班级对比" ? "0" : "1",
  69 + diffType: this.currentType == "任课班级对比" ? "1" : "0",
71 70 end: this.$props.params.dataRange ? this.$props.params.dataRange[1] : null,
72 71 start: this.$props.params.dataRange ? this.$props.params.dataRange[0] : null,
73 72 subjects: this.$props.params.subject ? [this.$props.params.subject] :
... ...
src/views/basic/askTestQuestion/components/testSummaryReport.vue
... ... @@ -9,14 +9,28 @@
9 9 <div id="print-content">
10 10 <el-row class="row-table">
11 11 <el-table border class="default-table" :data="stageReport" style="width: 100%">
12   - <el-table-column prop="studentCode" label="学号" align="center" fixed></el-table-column>
13   - <el-table-column prop="studentName" label="姓名" fixed align="center">
  12 + <el-table-column prop="studentCode" label="学号" fixed></el-table-column>
  13 + <el-table-column prop="studentName" label="姓名" fixed>
14 14 <template slot-scope="scoped">
15 15 {{ scoped.row.studentName }}
16   - </template></el-table-column>
17   - <el-table-column v-if="answerList" align="center" v-for="(item, index) in answerList" :key="index"
  16 + </template>
  17 + </el-table-column>
  18 + <el-table-column v-if="answerList" v-for="(item, index) in answerList" :key="index"
18 19 :label="item.title">
19   - <el-table-column :prop="'score' + index" :label="index == 0 ? '总分' : '总分'" align="center"
  20 + <template slot='header' slot-scope="scope" label="use show-overflow-tooltip"
  21 + show-overflow-tooltip>
  22 + <el-tooltip v-if="item.title != '阶段汇总'" effect="dark" :content="item.title"
  23 + placement="left">
  24 + <span class="overflowText overClick" @click="_headerClick(item)"
  25 + style="color:rgb(121,138,245);width: 100%;height: 100%;">
  26 + {{ item.title }}
  27 + </span>
  28 + </el-tooltip>
  29 + <span v-else>
  30 + {{ item.title }}
  31 + </span>
  32 + </template>
  33 + <el-table-column :prop="'score' + index" :label="index == 0 ? '总分' : '总分'"
20 34 :class-name="index % 2 == 0 ? 'bg' : ''">
21 35 <template slot-scope="scoped">
22 36 {{
... ... @@ -27,7 +41,7 @@
27 41 }}
28 42 </template>
29 43 </el-table-column>
30   - <el-table-column :prop="'classRank' + index" label="排名" align="center"
  44 + <el-table-column :prop="'classRank' + index" label="排名"
31 45 :class-name="index % 2 == 0 ? 'bg' : ''">
32 46 <template slot-scope="scoped">{{
33 47 scoped.row["classRank" + index] ||
... ... @@ -37,7 +51,7 @@
37 51 }}</template>
38 52 </el-table-column>
39 53 </el-table-column>
40   - <el-table-column label="查看折线图" align="center">
  54 + <el-table-column label="查看折线图" fixed="right" align="center" width="120">
41 55 <template slot-scope="scoped">
42 56 <el-button type="text" @click="_openLineChart(scoped.row)">查看</el-button>
43 57 </template>
... ... @@ -49,8 +63,7 @@
49 63 <el-dialog class="chart-dia" :visible.sync="lineChart.visible" :title="lineChart.title" width="800"
50 64 :append-to-body="true">
51 65 <div class="chart-box">
52   - <LineChart id="askLineChart" :params="lineChart.data" :xAxis="lineChart.xAxis"
53   - :tooltipFormatter="true" />
  66 + <LineChart id="askLineChart" :params="lineChart.data" :xAxis="lineChart.xAxis" />
54 67 </div>
55 68 </el-dialog>
56 69 <ExportDia :exportStudent="exportStudent" :diaShow="diaShow" @cancel="cancel" @exportData="exportData"
... ... @@ -68,7 +81,8 @@ export default {
68 81 },
69 82 props: {
70 83 testReportIds: Array,
71   - queryParams: Object
  84 + queryParams: Object,
  85 + role: "",
72 86 },
73 87 async created() {
74 88 await this._phaseExamReport();
... ... @@ -101,6 +115,9 @@ export default {
101 115 };
102 116 },
103 117 methods: {
  118 + _headerClick(currentItem) {
  119 + this.$emit("headerClick", currentItem);
  120 + },
104 121 async _export() {
105 122 this.diaShow = true;
106 123 },
... ... @@ -116,7 +133,9 @@ export default {
116 133 let query = {
117 134 examIds: this.$props.testReportIds,
118 135 classIds: [this.$props.queryParams.class],
119   - subjectName: [this.$props.queryParams.subject]
  136 + subjectName: [this.$props.queryParams.subject],
  137 + startDay: this.$props.queryParams.dateRange[0] ?? null,
  138 + endDay: this.$props.queryParams.dateRange[1] ?? null,
120 139 };
121 140  
122 141 const { data, status, info } = await phaseExamReport({
... ... @@ -139,6 +158,7 @@ export default {
139 158 }
140 159 });
141 160 });
  161 + console.log('lsit', data?.list)
142 162 this.stageReport = data?.list.map((item) => {
143 163 let params = {};
144 164 dataIdsList.map((ids, index) => {
... ... @@ -177,21 +197,26 @@ export default {
177 197 ? this.$request.pExportPhaseExamReport
178 198 : this.$request.exportPhaseExamReport;
179 199  
  200 +
180 201 const data = await exportPhaseExamReport({
181 202 examIds: this.$props.testReportIds,
182 203 classIds: [this.$props.queryParams.class],
183 204 subjectName: [this.$props.queryParams.subject],
  205 + startDay: this.$props.queryParams?.dateRange[0] ?? null,
  206 + endDay: this.$props.queryParams?.dateRange[1] ?? null,
184 207 ...query
185 208 });
186 209  
  210 +
187 211 if (data) {
  212 +
188 213 this.cancel();
189 214  
190 215 let blob = new Blob([data], {
191 216 type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
192 217 });
193 218  
194   - let name = `即时测-单科多卷报表.xlsx`;
  219 + let name = `即时测-${this.$props.queryParams.subject}-单科多卷报表.xlsx`;
195 220  
196 221 downloadFile(this.status ? "即时测-已归档单课时报表.xlsx" : name, blob);
197 222 } else {
... ... @@ -202,8 +227,9 @@ export default {
202 227 tablePrint("print-content", "即时测-已归档单课时报表");
203 228 },
204 229 _titleClick() { },
205   - _openLineChart(chartRow) {
206   - this.lineChart.title = `${chartRow.studentName}-${chartRow.subjectName}-多课时作答表现图`;
  230 + _openLineChart(chartRow) {
  231 + var subejct = this.$props.role == 'ROLE_BANZHUREN' ? this.$props.queryParams.subjects[0] : this.$props.queryParams.subject;
  232 + this.lineChart.title = `${chartRow.studentName}-${subejct}-即时测-多卷作答表现图`;
207 233 this.lineChart.visible = true;
208 234 let score = [];
209 235 let classRank = [];
... ... @@ -262,7 +288,6 @@ export default {
262 288  
263 289 .chart-dia {
264 290 .chart-box {
265   - width: 100%;
266 291 height: 300px;
267 292 }
268 293  
... ... @@ -270,4 +295,8 @@ export default {
270 295 padding: 0 0 20px 0;
271 296 }
272 297 }
  298 +
  299 +.overClick:hover {
  300 + cursor: pointer;
  301 +}
273 302 </style>
... ...
src/views/basic/askTestQuestion/detail.vue
... ... @@ -17,7 +17,20 @@
17 17 <el-option v-for="(item, index) in types" :lable="item.name" :key="index" :value="item.name" />
18 18 </el-select>
19 19 <div style="float: right;">
20   - <el-button type="primary" @click="_export" class="opration-btn"
  20 + <span v-if="(dataType == '2' && currentType == '测验成绩单') ||
  21 + (dataType == '2' && currentType == '试题分析') ||
  22 + (dataType == '3' && currentType == '学生成绩排名榜')">
  23 + 单题低分率:
  24 + <el-input-number class="parent-number" v-model="lowLevel" :min="1" :max="100" label="低分率">
  25 + </el-input-number>
  26 + </span>
  27 +
  28 + <el-button v-if="(dataType == '3' && currentType == '班级对比情况表') ||
  29 + (dataType == '3' && currentType == '学生成绩排名榜')" @click="_studentLevelSet"
  30 + class="green-el-button">
  31 + 设置学生成绩等级
  32 + </el-button>
  33 + <el-button type="primary" style="margin-left:10px;" @click="_export" class="opration-btn"
21 34 icon="el-icon-upload2">导出报表</el-button>
22 35 <el-button type="primary" @click="_print" class="opration-btn"
23 36 icon="el-icon-printer">打印报表</el-button>
... ... @@ -26,6 +39,16 @@
26 39 </div>
27 40 <el-main>
28 41 <div style=" padding: 20px;" id="print-content">
  42 + <div style="margin-bottom:20px;background:#ffb3b3;padding:10px 20px;" class="tips"
  43 + v-if="paperModifyLog.modifiedTime && !status">
  44 + <p class="tips-p">
  45 + <i class="fa fa-bell-o"></i>
  46 + {{ `${paperModifyLog.modifiedTime} ${paperModifyLog.realName}` }}修改了答案,是否重新记分?
  47 + <el-button type="danger" round @click="_reScore" size="mini">重新计分</el-button>
  48 + <el-button type="danger" round plain size="mini"
  49 + @click="paperModifyLog.modifiedTime = ''">暂时不计</el-button>
  50 + </p>
  51 + </div>
29 52 <div v-if="dataType == '1' && currentType == '试题分析'">
30 53 <el-row class="row-subfix">
31 54 <div class="row-line">
... ... @@ -78,15 +101,15 @@
78 101 </div>
79 102 <div class="row-line">
80 103 <span class="line-subfix">总参与度:</span>
81   - <span class="line-value">{{ detail.participationRate }}</span>
  104 + <span class="line-value">{{ detail.participationRate }}%</span>
82 105 </div>
83 106 <div class="row-line">
84 107 <span class="line-subfix">班级正确率:</span>
85   - <span class="line-value">{{ detail.classCorrectRate }}</span>
  108 + <span class="line-value">{{ detail.classCorrectRate }}%</span>
86 109 </div>
87 110 <div class="row-line">
88 111 <span class="line-subfix">已达正确率:</span>
89   - <span class="line-value">{{ detail.answerCorrectRate }}</span>
  112 + <span class="line-value">{{ detail.answerCorrectRate }}%</span>
90 113 </div>
91 114 <div class="row-line">
92 115 <span class="line-subfix">反馈时长:</span>
... ... @@ -96,7 +119,7 @@
96 119 <el-row class="row-table">
97 120 <el-table class="default-table" :data="askItemAnalysis">
98 121 <el-table-column prop="title" label="课时-题号" />
99   - <el-table-column label="题干" width="120">
  122 + <el-table-column label="题干" width="80">
100 123 <template slot-scope="scoped">
101 124 <el-button type="text" size="mini" @click="openStem(scoped.row)">查看</el-button>
102 125 </template>
... ... @@ -106,14 +129,14 @@
106 129 </el-table-column>
107 130 <el-table-column prop="answeredNum" label="答题人数" width="100" />
108 131 <el-table-column prop="correctAnswerNum" label="答对人数" width="100" />
109   - <el-table-column prop="participationRate" label="班级参与度(单题)" width="150">
  132 + <el-table-column prop="participationRate" label="班级参与度(单题)" width="170">
110 133 <template slot-scope="scoped">{{ scoped.row.participationRate }}%</template>
111 134 </el-table-column>
112   - <el-table-column prop="classCorrectRate" label="班级正确率(单题)" width="150">
  135 + <el-table-column prop="classCorrectRate" label="班级正确率(单题)" width="170">
113 136 <template slot-scope="scoped">{{ scoped.row.classCorrectRate }}%</template>
114 137 </el-table-column>
115 138  
116   - <el-table-column prop="answerCorrectRate" label="已答正确率(单题)" width="150">
  139 + <el-table-column prop="answerCorrectRate" label="已答正确率(单题)" width="170">
117 140 <template slot-scope="scoped">{{ scoped.row.answerCorrectRate }}%</template>
118 141 </el-table-column>
119 142  
... ... @@ -142,6 +165,8 @@
142 165 <div v-if="dataType == '1' && currentType == '学生作答表现'">
143 166 <el-row class="row-table" style="margin-top:0px;">
144 167 <el-table class="default-table" :data="askPeriodQuestionItems">
  168 + <el-table-column prop="studentCode" label="学号"></el-table-column>
  169 + <el-table-column prop="studentName" label="姓名"></el-table-column>
145 170 <el-table-column prop="answerTimes" label="答题次数"></el-table-column>
146 171 <el-table-column prop="consumingDuration" label="答题耗时"><template slot-scope="scoped">{{
147 172 setDuration(scoped.row.consumingDuration)
... ... @@ -259,16 +284,109 @@
259 284 :key="index" v-for="(item, index) in studentHeader" />
260 285 </el-table>
261 286 </el-row>
262   - <el-row class="row-subfix">
263   - <el-table class="default-table" style="margin-top: 10px" :data="questionList">
264   - <el-table-column :width="item.label == '题号&答案' ? 80 : 0" :prop="item.prop"
265   - :label="item.label" :key="index" v-for="(item, index) in questionHeaders" />
  287 + <el-row class="row-subfix" style="margin-top:10px">
  288 + <el-table class="default-table" v-if="question4List && question4List.length >= 1"
  289 + :data="question4List">
  290 + <el-table-column prop="column0" width="100" label="题号&答案" />
  291 + <el-table-column prop="column1" label="得分率">
  292 + <template slot-scope="scoped">
  293 + <div
  294 + :class="Number(scoped.row.column1?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  295 + {{ scoped.row.column1 }}
  296 + </div>
  297 + </template>
  298 + </el-table-column>
  299 + <el-table-column prop="column2" label="选项1" />
  300 + <el-table-column prop="column3" label="选项2" />
  301 + <el-table-column prop="column4" label="选项3" />
  302 + <el-table-column prop="column5" label="选项4" />
  303 + <el-table-column prop="column6" width="100" label="题号&答案" />
  304 + <el-table-column prop="column7" label="得分率">
  305 + <template slot-scope="scoped">
  306 + <div
  307 + :class="Number(scoped.row.column7?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  308 + {{ scoped.row.column7 }}
  309 + </div>
  310 + </template>
  311 + </el-table-column>
  312 + <el-table-column prop="column8" label="选项1" />
  313 + <el-table-column prop="column9" label="选项2" />
  314 + <el-table-column prop="column10" label="选项3" />
  315 + <el-table-column prop="column11" label="选项4" />
  316 + <el-table-column prop="column12" width="100" label="题号&答案" />
  317 + <el-table-column prop="column13" label="得分率">
  318 + <template slot-scope="scoped">
  319 + <div
  320 + :class="Number(scoped.row.column13?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  321 + {{ scoped.row.column13 }}
  322 + </div>
  323 + </template>
  324 + </el-table-column>
  325 + <el-table-column prop="column14" label="选项1" />
  326 + <el-table-column prop="column15" label="选项2" />
  327 + <el-table-column prop="column16" label="选项3" />
  328 + <el-table-column prop="column17" label="选项4" />
266 329 </el-table>
267 330 </el-row>
268   - <el-row class="row-subfix" v-if="questionOtherList && questionOtherList.length >= 1">
269   - <el-table class="default-table" style="margin-top: 10px" :data="questionOtherList">
270   - <el-table-column :prop="item.prop" :label="item.label" :key="index"
271   - v-for="(item, index) in questionOtherHeaders" />
  331 + <el-row class="row-subfix" style="margin-top:10px">
  332 + <el-table class="default-table" v-if="question7List && question7List.length >= 1"
  333 + :data="question7List">
  334 + <el-table-column prop="column0" width="100" label="题号&答案" />
  335 + <el-table-column prop="column1" label="得分率">
  336 + <template slot-scope="scoped">
  337 + <div
  338 + :class="Number(scoped.row.column1?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  339 + {{ scoped.row?.column1 }}
  340 + </div>
  341 + </template>
  342 + </el-table-column>
  343 + <el-table-column prop="column2" label="选项1" />
  344 + <el-table-column prop="column3" label="选项2" />
  345 + <el-table-column prop="column4" label="选项3" />
  346 + <el-table-column prop="column5" label="选项4" />
  347 + <el-table-column prop="column6" label="选项5" />
  348 + <el-table-column prop="column7" label="选项6" />
  349 + <el-table-column prop="column8" label="选项7" />
  350 + <el-table-column prop="column9" width="100" label="题号&答案" />
  351 + <el-table-column prop="column10" label="得分率">
  352 + <template slot-scope="scoped">
  353 + <div
  354 + :class="Number(scoped.row.column10?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  355 + {{ scoped.row?.column10 }}
  356 + </div>
  357 + </template>
  358 + </el-table-column>
  359 + <el-table-column prop="column11" label="选项1" />
  360 + <el-table-column prop="column12" label="选项2" />
  361 + <el-table-column prop="column13" label="选项3" />
  362 + <el-table-column prop="column14" label="选项4" />
  363 + <el-table-column prop="column15" label="选项5" />
  364 + <el-table-column prop="column16" label="选项6" />
  365 + <el-table-column prop="column17" label="选项7" />
  366 + </el-table>
  367 + </el-row>
  368 + <el-row class="row-subfix">
  369 + <el-table class="default-table" v-if="question10List && question10List.length >= 1"
  370 + :data="question10List">
  371 + <el-table-column prop="column0" width="100" label="题号&答案" />
  372 + <el-table-column prop="column1" label="得分率">
  373 + <template slot-scope="scoped">
  374 + <div
  375 + :class="Number(scoped.row.column1?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  376 + {{ scoped.row?.column1 }}
  377 + </div>
  378 + </template>
  379 + </el-table-column>
  380 + <el-table-column prop="column2" label="选项1" />
  381 + <el-table-column prop="column3" label="选项2" />
  382 + <el-table-column prop="column4" label="选项3" />
  383 + <el-table-column prop="column5" label="选项4" />
  384 + <el-table-column prop="column6" label="选项5" />
  385 + <el-table-column prop="column7" label="选项6" />
  386 + <el-table-column prop="column8" label="选项7" />
  387 + <el-table-column prop="column9" label="选项8" />
  388 + <el-table-column prop="column10" label="选项9" />
  389 + <el-table-column prop="column11" label="选项10" />
272 390 </el-table>
273 391 </el-row>
274 392 <el-row class="row-subfix">
... ... @@ -278,10 +396,10 @@
278 396 <el-table-column prop="student" label="答错学生">
279 397 <template slot-scope="scoped">
280 398 <span>总计 <span style="color:red;">
281   - {{ scoped.row.details.filter(item => !item.isRight).length }}</span> 人
  399 + {{ scoped.row.missPeopleNumber }}</span> 人
282 400 </span>
283 401 <span style="margin: 10px 0;"
284   - v-for="(item, index) in scoped.row.details.filter(item => !item.isRight)">
  402 + v-for="(item, index) in scoped.row.details.filter(item => !item.right)">
285 403 选{{ item.option }}:{{ item.students.join("/") }}
286 404 </span>
287 405 <span></span>
... ... @@ -291,21 +409,37 @@
291 409 </el-row>
292 410 </div>
293 411 <div v-if="dataType == '2' && currentType == '试题分析'">
294   - <el-table class="default-table" :data="testQuestions">
  412 + <el-table class="default-table" :data="testQuestions" :span-method="singgleSpanMethod">
295 413 <el-table-column prop="questionIndex" label="题号" width="60"></el-table-column>
296 414 <el-table-column prop="questionType" label="题型" width="100">
297 415 <template slot-scope="scope">
298 416 {{ setSubPro(scope.row.questionType) }}
299 417 </template>
300 418 </el-table-column>
301   - <el-table-column prop="score" width="100" label="知识点"></el-table-column>
  419 + <el-table-column prop="knowledge" width="100" label="知识点"></el-table-column>
302 420 <el-table-column prop="score" width="100" label="满分值"></el-table-column>
303 421 <el-table-column width="110" prop="highestScore" label="班最高分"></el-table-column>
304 422 <el-table-column width="110" prop="lowestScore" label="班最低分"></el-table-column>
305   - <el-table-column width="110" prop="avgScore" label="班平均分"></el-table-column>
306   - <el-table-column prop="classScoringRate" width="120" label="班级得分率"><template
307   - slot-scope="scoped">{{ scoped.row.classScoringRate
308   - }}%</template></el-table-column>
  423 + <el-table-column width="110" prop="avgScore" label="班平均分">
  424 + <template slot-scope="scoped">
  425 + <div v-if="scoped.row.type != 'colspan'">
  426 + {{ scoped.row.avgScore }}
  427 + </div>
  428 + <div :class="scoped.row.avgScore <= lowLevel ? 'lowLevelClass' : ''" v-else>
  429 + {{ Number(scoped.row.avgScore).toFixed(2) }}%
  430 + </div>
  431 + </template>
  432 + </el-table-column>
  433 + <el-table-column prop="classScoringRate" width="120" label="已考得分率">
  434 + <template slot-scope="scoped">
  435 + <div v-if="scoped.row.type == 'colspan'">
  436 + {{ scoped.row.classScoringRate }}
  437 + </div>
  438 + <div :class="scoped.row.classScoringRate <= lowLevel ? 'lowLevelClass' : ''" v-else>
  439 + {{ Number(scoped.row.classScoringRate).toFixed(2) }}%
  440 + </div>
  441 + </template>
  442 + </el-table-column>
309 443 <el-table-column prop="correctAnswer" label="答案"><template slot-scope="scoped">{{
310 444 scoped.row.correctAnswer == 1
311 445 ? "✓"
... ... @@ -318,20 +452,18 @@
318 452 :prop="'count' + index" width="120"><template slot-scope="scope">
319 453 <p class="persent">
320 454 {{
321   - scope.row.questionType == "5"
322   - ? ""
323   - : scope.row["option" + index]
  455 + scope.row["option" + index] == "?" ? "未答" : scope.row.questionType == "5" ? "" :
  456 + scope.row["option" + index]
324 457 ? `${scope.row["option" + index]}(${scope.row["persent" + index]
325 458 })`
326   - : ""
327   - }}
  459 + : "" }}
328 460 </p>
329 461 </template>
330 462 </el-table-column>
331 463 </el-table>
332 464 </div>
333   - <div v-if="dataType == '2' && currentType == '成绩排名'">
334   - <el-table class="default-table" :data="testStudents">
  465 + <div v-if="dataType == '2' && currentType == '成绩排名'" ref="studentRank">
  466 + <el-table :key="studentRank.length" class="default-table" :data="studentRank">
335 467 <el-table-column prop="studentCode" label="学号" width="120"></el-table-column>
336 468 <el-table-column prop="studentName" label="姓名"></el-table-column>
337 469 <el-table-column prop="examScore" label="总分"></el-table-column>
... ... @@ -359,8 +491,8 @@
359 491 </el-table-column>
360 492 </el-table>
361 493 </div>
362   - <div v-if="dataType == '2' && currentType == '小题分报表'">
363   - <el-table class="default-table" :data="testStudents">
  494 + <div v-if="dataType == '2' && currentType == '小题分报表'" ref="studentQuestions">
  495 + <el-table :key="studentQuestions.length" class="default-table" :data="studentQuestions">
364 496 <el-table-column prop="studentCode" label="学号" width="120"></el-table-column>
365 497 <el-table-column prop="studentName" label="姓名"></el-table-column>
366 498 <el-table-column prop="examScore" label="总分"></el-table-column>
... ... @@ -368,21 +500,21 @@
368 500 <el-table-column prop="objectiveExamScore" label="客观题分"></el-table-column>
369 501 <el-table-column prop="subjectiveExamScore" label="主观题分"></el-table-column>
370 502 </el-table-column>
371   - <el-table-column v-for="(item, index) in testStudentOptions" :key="index" :label="'Q' + item.id"
372   - :prop="'score' + item.id">
  503 + <el-table-column v-for="(item, index) in studentQuestionOptions" :key="index"
  504 + :label="'Q' + item.id" :prop="'score' + item.id">
373 505 </el-table-column>
374 506 </el-table>
375 507 </div>
376   - <div v-if="dataType == '2' && currentType == '作答明细'">
377   - <el-table class="default-table" :data="testStudents">
  508 + <div v-if="dataType == '2' && currentType == '作答明细'" ref="studentAnsered">
  509 + <el-table :key="studentAnsered.length" class="default-table" :data="studentAnsered">
378 510 <el-table-column prop="studentCode" width="120" label="学号"></el-table-column>
379 511 <el-table-column prop="studentName" label="姓名"></el-table-column>
380 512 <el-table-column prop="className" label="班级"></el-table-column>
381 513 <el-table-column prop="examScore" label="总分"></el-table-column>
382   - <el-table-column v-for="(item, index) in testStudentOptions" :key="index"
  514 + <el-table-column v-for="(item, index) in studentAnseredOptions" :key="index"
383 515 :label="'Q' + item.id">
384 516 <template slot-scope="scope">
385   - <span v-if="testStudents[index]?.questionType == 5">*</span>
  517 + <span v-if="studentAnsered[index]?.questionType == 5">*</span>
386 518 <span v-else-if="scope.row['answer' + item.id]"
387 519 :class="scope.row['isRight' + item.id] ? '' : 'error'">
388 520 {{ scope.row["answer" + item.id] }}
... ... @@ -403,7 +535,8 @@
403 535 </el-table-column>
404 536 <el-table-column prop="title" label="参与度" width="120">
405 537 <template slot-scope="scoped">
406   - {{ scoped.row.testCount / scoped.row.classCount }}
  538 + {{ Number(scoped.row.testCount * 100 / scoped.row.classCount).toFixed(2) }}%
  539 +
407 540 </template>
408 541 </el-table-column>
409 542 <el-table-column prop="avg" label="班平均分" width="120" />
... ... @@ -411,40 +544,54 @@
411 544 <el-table-column prop="low" label="班最低分" width="120" />
412 545 <el-table-column prop="front20" label="前20名均分" width="120" />
413 546 <el-table-column prop="last20" label="后20名均分" width="120" />
414   - <el-table-column prop="excellenRate" label="优秀数(率)" width="120">
  547 + <el-table-column v-for="(item, index) in defaultLevels.levels" :key="index"
  548 + :label="item[0] ? item[0] + '数(率)' : ''">
415 549 <template slot-scope="scoped">
416   - {{ scoped.row.excellenRate }}%
417   - </template>
418   - </el-table-column>
419   - <el-table-column prop="goodRate" label="良好数(率)" width="120">
420   - <template slot-scope="scoped">
421   - {{ scoped.row.goodRate }}%
422   - </template>
423   - </el-table-column>
424   - <el-table-column prop="passRate" label="合格数(率)" width="120">
425   - <template slot-scope="scoped">
426   - {{ scoped.row.passRate }}%
427   - </template>
428   - </el-table-column>
429   - <el-table-column prop="failedRate" label="不合格数(率)" width="120">
430   - <template slot-scope="scoped">
431   - {{ scoped.row.passRate }}%
  550 + {{ scoped.row.leverValues[item[0]] }}
432 551 </template>
433 552 </el-table-column>
434 553 </el-table>
435 554 </div>
436 555 <div v-if="dataType == '3' && currentType == '试题分析'">
437   - <el-table class="default-table" :data="testPaperExamReport">
  556 + <el-table class="default-table" :data="testPaperExamReport" :span-method="arraySpanMethod">
438 557 <el-table-column prop="questionIndex" label="题号" width="120" />
439 558 <el-table-column prop="questionType" label="题型" width="100">
440 559 <template slot-scope="scope">
441 560 {{ setSubPro(scope.row.questionType) }}
442 561 </template>
443 562 </el-table-column>
444   - <el-table-column prop="score" label="知识点" />
  563 + <el-table-column prop="knowledge" label="知识点">
  564 + <template slot-scope="scoped">
  565 + <el-tooltip effect="dark" :content="scoped.row.knowledge" placement="left">
  566 + <span class="overflowText">
  567 + {{ scoped.row.knowledge }}
  568 + </span>
  569 + </el-tooltip>
  570 + </template>
  571 + </el-table-column>
445 572 <el-table-column prop="score" label="满分值" width="120" />
446   - <el-table-column prop="avgScore" label="年级平均分" width="120" />
447   - <el-table-column prop="gradeScoringRate" label="年级得分率" width="120" />
  573 + <el-table-column prop="avgScore" label="年级平均分" width="120">
  574 + <template slot-scope="scoped">
  575 + <div v-if="scoped.row.type == 'colspan'"
  576 + :class="scoped.row.avgScore <= lowLevel ? 'lowLevelClass' : ''">
  577 + {{ Number(scoped.row.avgScore).toFixed(2) }} %
  578 + </div>
  579 + <div v-else>
  580 + {{ scoped.row.avgScore }}
  581 + </div>
  582 + </template>
  583 + </el-table-column>
  584 + <el-table-column prop="gradeScoringRate" label="年级得分率" width="120">
  585 + <template slot-scope="scoped">
  586 + <div v-if="scoped.row.type == 'colspan'">
  587 + {{ scoped.row.gradeScoringRate }}
  588 + </div>
  589 + <div v-else="scoped.row.gradeScoringRate"
  590 + :class="scoped.row.gradeScoringRate <= lowLevel ? 'lowLevelClass' : ''">
  591 + {{ Number(scoped.row.gradeScoringRate).toFixed(2) }} %
  592 + </div>
  593 + </template>
  594 + </el-table-column>
448 595 <el-table-column prop="correctAnswer" label="答案" width="120" />
449 596 <el-table-column v-for="(item, index) in testPaperExamReportOptions" :key="index"
450 597 :label="item.title" :prop="'count' + index" width="120">
... ... @@ -470,13 +617,89 @@
470 617 <el-table-column prop="name" label="姓名" />
471 618 <el-table-column prop="className" label="班级" />
472 619 <el-table-column prop="exam" label="分数" />
473   - <el-table-column prop="title" label="成绩等级" />
  620 + <el-table-column prop="lever" label="成绩等级" />
474 621 </el-table>
475 622 </div>
476 623 </div>
477 624 </el-main>
478 625 <el-dialog class="stem" :visible.sync="stem.visible" :title="'题干'" width="800" :append-to-body="true">
479   - <iframe v-if="stem&&stem.src" :src="stem.src" style="width: 100%;min-height: 400px;" />
  626 + <iframe v-if="stem && stem.src" :src="stem.src" style="width: 100%;min-height: 400px;" />
  627 + </el-dialog>
  628 + <el-dialog :append-to-body="true" :close-on-click-modal="false" title="学生等级设置"
  629 + :visible.sync="studentLevelDialog" width="900px" @closed="_studentLevelClose">
  630 + <el-container class="default-body" style="background: transparent !important;">
  631 + <el-main>
  632 + <div class="default-main">
  633 + <el-form class="use-form">
  634 + <el-form-item class="use-form-item-box">
  635 + <el-form-item label="等级设置模式" class="use-form-item">
  636 + <el-select size="small" v-model="fromData.levelType">
  637 + <el-option label="按分数比例" :value="0"></el-option>
  638 + <el-option label="按已考人数比例" :value="1"></el-option>
  639 + </el-select>
  640 + </el-form-item>
  641 + </el-form-item>
  642 + <el-form-item>
  643 + <div class="dia-tab-box">
  644 + <p class="dia-tab-tit">
  645 + <span class="item1 boxitem">序号</span>
  646 + <span class="item2 boxitem"><i>*</i>等级名称</span>
  647 + <span class="item3 boxitem"><i>*</i>等级最高</span>
  648 + <span class="item3 boxitem"><i>*</i>等级最低</span>
  649 + <span class="item boxitem">操作</span>
  650 + </p>
  651 + <div class="dia-tab-item" v-for="(item, index) in fromData.levels" :key="index">
  652 + <span class="item1 boxitem">{{ index + 1 }}</span>
  653 + <p class="item2 boxitem">
  654 + <el-input class="score-ipt" v-model="item[0]" :maxlength="12"
  655 + @keydown.native="keydownRange($event)"></el-input>
  656 + </p>
  657 + <p class="item3 boxitem">
  658 + <el-input class="score-ipt" type="number" v-model="item[1]" :min="item[2]"
  659 + :max="index == 0 ? 100 : fromData.levels[index - 1][2]"
  660 + @keydown.native="keydownRange($event)"></el-input>
  661 + <span class="descption">
  662 + %
  663 + <template v-if="fromData.levelType == 0">
  664 + (
  665 + {{ index != 0 ? "不含" : "" }}
  666 + {{ Number(((item[1] / 100) * examPaperScore).toFixed(1)) }}分
  667 + )
  668 + </template>
  669 + <template v-else>{{ index != 0 ? "不含" : "" }}</template>
  670 + </span>
  671 + </p>
  672 + <p class="item3 boxitem">
  673 + <el-input class="score-ipt" type="number" v-model="item[2]" :min="0"
  674 + :max="item[1]" @keydown.native="keydownRange($event)"></el-input>
  675 + <span class="descption">
  676 + %
  677 + <template v-if="fromData.levelType == 0">
  678 + ({{ Number(((item[2] / 100) * examPaperScore).toFixed(1)) }}分)
  679 + </template>
  680 + </span>
  681 + </p>
  682 + <p class="item boxitem">
  683 + <el-link type="danger" :underline="false"
  684 + @click="fromData.levels.splice(index, 1)">删除</el-link>
  685 + </p>
  686 + </div>
  687 + <div class="add">
  688 + <p @click="fromData.levels.push(['', '', ''])">
  689 + <el-button size="mini" icon="el-icon-plus" circle
  690 + type="primary"></el-button>添加一行
  691 + </p>
  692 + </div>
  693 + </div>
  694 + </el-form-item>
  695 + </el-form>
  696 + </div>
  697 + </el-main>
  698 + </el-container>
  699 + <div class="dialog-footer" slot="footer" align="right">
  700 + <el-button type="info" :size="'small'" @click="studentLevelDialog = false">取 消</el-button>
  701 + <el-button type="primary" class="green-el-button" :size="'small'" @click="_savefrom">保存</el-button>
  702 + </div>
480 703 </el-dialog>
481 704 </el-container>
482 705 </template>
... ... @@ -484,6 +707,7 @@
484 707 import { formatDate, downloadFile, tablePrint } from "utils";
485 708 export default {
486 709 name: "reportDetail",
  710 + components: { testScoreSet: () => import("./components/testScoreSet.vue"), },
487 711 async created() {
488 712 this.role =
489 713  
... ... @@ -506,9 +730,36 @@ export default {
506 730 this.currentType = this.types[0]?.name ?? ""
507 731  
508 732 await this._changeType();
  733 +
  734 + await this._queryDefaultLevels();
  735 +
  736 + if (this.dataType == '2') {
  737 + await this._examDetail();
  738 + }
509 739 },
510 740 data() {
511 741 return {
  742 + status: 0,
  743 + //导出相关
  744 + paperModifyLog: {},
  745 + diaShow: false,
  746 + exportStudent: [],
  747 + showSelect: true, //是否显示录总分
  748 + showAllSetScore: false, //当前操作试卷可录总分分状态
  749 + showSetScore: false, //当前操作试卷可录小题分状态
  750 + lowLevel: 20,
  751 + defaultLevels: [],
  752 + examPaperScore: 100, //卷面最高分
  753 + fromData: {
  754 + levelType: 0,
  755 + levels: [
  756 + ["优秀", 100, 90],
  757 + ["良好", 89.9, 70],
  758 + ["合格", 69.9, 60],
  759 + ["不合格", 59.9, 0],
  760 + ],
  761 + },
  762 + studentLevelDialog: false,
512 763 titleInfo: [],
513 764 studentList: [],
514 765 studentHeader: [],
... ... @@ -538,10 +789,9 @@ export default {
538 789 label: "主观分",
539 790 },
540 791 ],
541   - questionList: [],
542   - questionHeaders: [],
543   - questionOtherList: [],
544   - questionOtherHeaders: [],
  792 + question4List: [],
  793 + question7List: [],
  794 + question10List: [],
545 795 questionTotal: [],
546 796 dataType: null,
547 797 classIds: [],
... ... @@ -579,6 +829,11 @@ export default {
579 829 testStudents: [],
580 830 // 报表学生选项
581 831 testStudentOptions: [],
  832 + studentAnsered: [],
  833 + studentAnseredOptions: [],
  834 + studentRank: [],
  835 + studentQuestions: [],
  836 + studentQuestionOptions: [],
582 837 // 报表题目详情
583 838 testQuestions: [],
584 839 // 报表题目选项
... ... @@ -599,7 +854,7 @@ export default {
599 854 tit = "主观题";
600 855 break;
601 856 default:
602   - tit = "其他";
  857 + tit = type;
603 858 }
604 859 return tit;
605 860 },
... ... @@ -662,9 +917,11 @@ export default {
662 917 detail: {},
663 918 currentType: null,
664 919 classdiffExamReport: [],
  920 + classdiffLevelOptions: [],
665 921 testPaperExamReport: [],
666 922 testStudentExamReport: [],
667 923 testPaperExamReportOptions: [],
  924 + diffType: 0,
668 925 //题干数据对象
669 926 stem: {
670 927 visible: false,
... ... @@ -673,12 +930,171 @@ export default {
673 930 }
674 931 },
675 932 methods: {
  933 + async _examDetail() {
  934 + const examDetail =
  935 + this.role == "ROLE_PERSONAL"
  936 + ? this.$request.pExamDetail
  937 + : this.$request.examDetail;
  938 +
  939 + let { data, info, status } = await examDetail({
  940 + examId: this.ids[0],
  941 + });
  942 + console.log('detail', data, data.paperModifyLog)
  943 + if (status === 0) {
  944 + if (data.paperModifyLog) {
  945 + this.paperModifyLog = { ...data?.paperModifyLog };
  946 + }
  947 + } else {
  948 + this.$message.error(info);
  949 + }
  950 + },
  951 + async _reScore() {
  952 + //重新记分
  953 + let { data, info, status } = await this.$request.reScore({
  954 + examId: this.ids[0],
  955 + });
  956 + if (status === 0) {
  957 + this.$message.success(info);
  958 + await this._changeType();
  959 + this.paperModifyLog.modifiedTime = "";
  960 + this.paperModifyLog.realName = "";
  961 + } else {
  962 + this.$message.error(info);
  963 + }
  964 + },
  965 + _closeScoreSet() {
  966 + this.scoreSet.diaScoreSet = false;
  967 + },
  968 + _successScoreSet() {
  969 + this._changeType();
  970 + this._closeScoreSet();
  971 + },
  972 + async _queryDefaultLevels() {
  973 +
  974 + const { data, info, status } = await this.$request.defaultLevels();
  975 +
  976 + if (status != 0) {
  977 + this.$message.error(info);
  978 + return;
  979 + }
  980 +
  981 + this.defaultLevels = { ...data } || {
  982 + levelType: 0,
  983 + levels: [
  984 + ["优秀", 100, 90],
  985 + ["良好", 89.9, 70],
  986 + ["合格", 69.9, 60],
  987 + ["不合格", 59.9, 0],
  988 + ],
  989 + };
  990 +
  991 + this.defaultLevels.type = 0
  992 +
  993 + this.fromData.levelType = this.defaultLevels.levelType;
  994 +
  995 + this.fromData.levels = [...this.defaultLevels.levels];
  996 +
  997 + sessionStorage.setItem(
  998 + "levelFromData",
  999 + JSON.stringify(this.defaultLevels)
  1000 + );
  1001 + },
  1002 + singgleSpanMethod({ row, column, rowIndex, columnIndex }) {
  1003 + if (rowIndex == this.testQuestions?.length - 3) {
  1004 + if (columnIndex == 0) {
  1005 + return [3, 1];
  1006 + }
  1007 + // else if (columnIndex == 6) {
  1008 + // return [3, 1];
  1009 + // }
  1010 + // else if (columnIndex == 7) {
  1011 + // return [3, 5];
  1012 + // }
  1013 + else {
  1014 + return [1, 1]
  1015 + }
  1016 + }
  1017 + else {
  1018 + return [1, 1]
  1019 + }
  1020 + },
  1021 + arraySpanMethod({ row, column, rowIndex, columnIndex }) {
  1022 + if (rowIndex == this.testPaperExamReport?.length - 3) {
  1023 + if (columnIndex == 0) {
  1024 + return [3, 1];
  1025 + }
  1026 + else if (columnIndex == 6) {
  1027 + return [3, 1];
  1028 + }
  1029 + else if (columnIndex == 7) {
  1030 + return [3, 5];
  1031 + }
  1032 + else {
  1033 + return [1, 1]
  1034 + }
  1035 + }
  1036 + else {
  1037 + return [1, 1]
  1038 + }
  1039 +
  1040 + },
  1041 + async _savefrom() {
  1042 + for (let i = 0; i < this.fromData.levels.length; i++) {
  1043 + if (this.fromData.levels[i].includes("")) {
  1044 + this.$message.warning("请补全编号" + (i + 1) + "设置信息!");
  1045 + return;
  1046 + }
  1047 + }
  1048 + if (this.fromData.levels.length == 0) {
  1049 + this.$message.warning("请添加等级设置!");
  1050 + return;
  1051 + }
  1052 + let nums = [];
  1053 + let ERR_OK = false;
  1054 + this.fromData.levels.map((item) => {
  1055 + nums.push(Number(item[1]));
  1056 + nums.push(Number(item[2]));
  1057 + });
  1058 + for (let i = 0; i < nums.length; i++) {
  1059 + if (nums[i + 1] && nums[i + 1] > nums[i]) {
  1060 + ERR_OK = true;
  1061 + this.$message.warning("高等级比例不能低于低等级比例!请检查");
  1062 + break;
  1063 + }
  1064 + }
  1065 + if (ERR_OK) return;
  1066 + this.tableData = [];
  1067 + this.tableData2 = [];
  1068 + this.defaultLevels.type = this.fromData.type;
  1069 + this.defaultLevels.levelType = this.fromData.levelType;
  1070 + this.defaultLevels.levels = [...this.fromData.levels];
  1071 + sessionStorage.setItem("levelFromData", JSON.stringify(this.fromData));
  1072 + this.studentLevelDialog = false;
  1073 + await this._changeType();
  1074 + },
  1075 + _studentLevelClose() {
  1076 + let levelFromData = sessionStorage.getItem("levelFromData");
  1077 + if (levelFromData) {
  1078 + levelFromData = JSON.parse(levelFromData);
  1079 + this.fromData.type = levelFromData.type;
  1080 + this.fromData.levelType = levelFromData.levelType;
  1081 + this.fromData.levels = [...levelFromData.levels];
  1082 + } else {
  1083 + this.fromData.type = 0;
  1084 + this.fromData.levelType = this.defaultLevels.levelType;
  1085 + this.fromData.levels = [...this.defaultLevels.levels];
  1086 + }
  1087 + },
  1088 + _studentLevelSet() {
  1089 + this.studentLevelDialog = true;
  1090 + },
676 1091 async _export() {
677 1092 if (this.dataType == "1") {
678 1093  
679 1094 let exportPeriodReport = "";
680 1095  
681 1096 var query = {};
  1097 +
682 1098 query.periodId = this.ids[0];
683 1099  
684 1100 exportPeriodReport =
... ... @@ -701,7 +1117,6 @@ export default {
701 1117 }
702 1118 }
703 1119 else if (this.dataType == "2") {
704   -
705 1120 const exportExamReport =
706 1121 this.role == "ROLE_PERSONAL"
707 1122 ? this.$request.pExportExamReport
... ... @@ -711,8 +1126,6 @@ export default {
711 1126 examId: this.ids[0]
712 1127 });
713 1128  
714   - this.exportLoading = false;
715   -
716 1129 if (!data.status) {
717 1130 let blob = new Blob([data], {
718 1131 type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
... ... @@ -727,6 +1140,37 @@ export default {
727 1140 this.$message.error(data.info);
728 1141 }
729 1142 }
  1143 + else if (this.dataType == '3') {
  1144 +
  1145 + let paramObj = JSON.parse(JSON.stringify(this.fromData))
  1146 +
  1147 + if (paramObj.levelType == 0) {
  1148 + paramObj.levels = paramObj.levels.map((item) => {
  1149 + item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);
  1150 + item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);
  1151 + return item;
  1152 + });
  1153 + }
  1154 +
  1155 + const data = await this.$request.exportExamMultiReport({
  1156 + examIds: this.classdiffExamReport?.map(item => item.examId) ?? [],
  1157 + levels: paramObj.levels,
  1158 + levelType: paramObj.levelType,
  1159 + });
  1160 +
  1161 +
  1162 + if (!data.status) {
  1163 + let blob = new Blob([data], {
  1164 + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  1165 + });
  1166 + downloadFile(
  1167 + '多班对比.xlsx',
  1168 + blob
  1169 + );
  1170 + } else {
  1171 + this.$message.error(data.info);
  1172 + }
  1173 + }
730 1174  
731 1175 },
732 1176 _print() {
... ... @@ -778,6 +1222,30 @@ export default {
778 1222 }
779 1223 },
780 1224 async _testPaperExamReport() {
  1225 + //主观
  1226 + var subjective = {
  1227 + sum: 0.0,
  1228 + avg: 0.0,
  1229 + rate: 0.0,
  1230 + number: 0
  1231 + };
  1232 +
  1233 + //客观
  1234 + var objective = {
  1235 + sum: 0.0,
  1236 + avg: 0.0,
  1237 + rate: 0.0,
  1238 + number: 0
  1239 + };
  1240 +
  1241 + //汇总
  1242 + var summary = {
  1243 + sum: 0.0,
  1244 + avg: 0.0,
  1245 + rate: 0.0,
  1246 + number: 0
  1247 + };
  1248 +
781 1249 const request = this.$request.tPaperExamReport;
782 1250  
783 1251 let response = await request({
... ... @@ -789,10 +1257,45 @@ export default {
789 1257 this.$message.error(response.info);
790 1258 return;
791 1259 }
  1260 +
  1261 + var maxOption = 0;
  1262 + response.data.forEach((item) =>{
  1263 + if(item.details){
  1264 + if(maxOption < item.details.length)
  1265 + {
  1266 + maxOption = item.details.length;
  1267 + }
  1268 + }
  1269 +
  1270 + })
  1271 +
  1272 + let optionsList = [];
792 1273  
793   - let optionsList = [{}, {}, {}, {}, {}];
  1274 + for(var io=0;io<maxOption;io++){
  1275 + optionsList.push({})
  1276 + }
  1277 +
  1278 + // let optionsList = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
794 1279  
795 1280 let tableData = response.data?.map((item) => {
  1281 +
  1282 + summary.sum += parseFloat(item.score);
  1283 + summary.avg += parseFloat(item.avgScore);
  1284 + summary.rate += parseFloat(item.gradeScoringRate);
  1285 + summary.number += 1;
  1286 + if (item.questionType == 5) {
  1287 + subjective.sum += parseFloat(item.score);
  1288 + subjective.rate += parseFloat(item.gradeScoringRate);
  1289 + subjective.avg += parseFloat(item.avgScore);
  1290 + subjective.number += 1;
  1291 + }
  1292 + else {
  1293 + objective.sum += parseFloat(item.score);
  1294 + objective.rate += parseFloat(item.gradeScoringRate);
  1295 + objective.avg += parseFloat(item.avgScore);
  1296 + objective.number += 1;
  1297 + }
  1298 +
796 1299 let params = {};
797 1300  
798 1301 const detail = item?.details ?? [];
... ... @@ -803,6 +1306,7 @@ export default {
803 1306 let defaultArr = detail?.filter((item) => {
804 1307 return item.option != "未答";
805 1308 });
  1309 +
806 1310 optionsList.map((items, index) => {
807 1311 if (index != 4) {
808 1312 params["count" + index] =
... ... @@ -830,6 +1334,8 @@ export default {
830 1334 }
831 1335 });
832 1336  
  1337 +
  1338 +
833 1339 return {
834 1340 ...item,
835 1341 ...params,
... ... @@ -842,13 +1348,48 @@ export default {
842 1348  
843 1349 this.testPaperExamReportOptions = [...optionsList];
844 1350  
  1351 + this.testPaperExamReport.push({
  1352 + questionIndex: "汇总",
  1353 + questionType: "客观题",
  1354 + score: objective.sum,
  1355 + avgScore: objective.avg == 0 ? 0 : Number(objective.avg).toFixed(2),
  1356 + gradeScoringRate: objective.avg == 0 ? 0 : Number(objective.avg * 100 / objective.sum).toFixed(2),
  1357 + correctAnswer: "备注"
  1358 + })
  1359 +
  1360 + this.testPaperExamReport.push({
  1361 + questionIndex: "主观题",
  1362 + type: "colspan",
  1363 + knowledge: subjective.sum,
  1364 + score: subjective.avg == 0 ? 0 : Number(subjective.avg).toFixed(2),
  1365 + avgScore: subjective.avg == 0 ? 0 : Number(subjective.avg * 100 / subjective.sum).toFixed(2)
  1366 + })
  1367 +
  1368 + this.testPaperExamReport.push({
  1369 + questionIndex: "合计",
  1370 + type: "colspan",
  1371 + knowledge: summary.sum,
  1372 + score: summary.avg == 0 ? 0 : Number(summary.avg).toFixed(2),
  1373 + avgScore: summary.avg == 0 ? 0 : Number(summary.avg * 100 / summary.sum).toFixed(2)
  1374 + })
845 1375 },
846 1376 async _testStudentExamReport() {
847 1377 const request = this.$request.tgStudentExamReport;
848 1378  
  1379 + let paramObj = JSON.parse(JSON.stringify(this.fromData))
  1380 + if (paramObj.levelType == 0) {
  1381 + paramObj.levels = paramObj.levels.map((item) => {
  1382 + item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);
  1383 + item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);
  1384 + return item;
  1385 + });
  1386 + }
  1387 +
  1388 +
849 1389 let response = await request({
850 1390 paperId: this.ids[0],
851 1391 classIds: this.classIds,
  1392 + reportRange: paramObj
852 1393 });
853 1394  
854 1395 if (response.status != 0) {
... ... @@ -859,25 +1400,45 @@ export default {
859 1400 this.testStudentExamReport = response.data;
860 1401 },
861 1402 async _classdiffExamReport() {
862   -
  1403 + this.classdiffExamReport = [];
  1404 + this.classdiffLevelOptions = [];
863 1405 const classDiffRequest = this.$request.tClassdiffExamReport;
864 1406  
  1407 + let paramObj = JSON.parse(JSON.stringify(this.fromData))
  1408 + if (paramObj.levelType == 0) {
  1409 + paramObj.levels = paramObj.levels.map((item) => {
  1410 + item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);
  1411 + item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);
  1412 + return item;
  1413 + });
  1414 + }
  1415 +
865 1416 let classDiffResponse = await classDiffRequest({
866 1417 paperId: this.ids[0],
867 1418 classIds: this.classIds,
  1419 + reportRange: paramObj
868 1420 });
869 1421  
870 1422 if (classDiffResponse.status != 0) {
871 1423 this.$message.error(classDiffResponse.info);
872 1424 return;
873 1425 }
  1426 +
874 1427 var index = 0;
875 1428  
876 1429 this.classdiffExamReport = classDiffResponse.data.map((item) => {
877 1430 item.index = index + 1;
878 1431 index += 1;
  1432 + var cols = 0;
  1433 + item.keys.forEach(toam => {
  1434 + this.classdiffLevelOptions.push(toam);
  1435 + item[toam] = item.leverValues[cols];
  1436 + cols += 1;
  1437 + })
879 1438 return item;
880 1439 });
  1440 +
  1441 + console.log(this.fromData)
881 1442 },
882 1443 openStem(stemRow) {
883 1444 this.stem.src = stemRow.screenshot ?? "";
... ... @@ -890,8 +1451,8 @@ export default {
890 1451 const request = this.$request.tTestExamReport;
891 1452  
892 1453 let response = await request({
893   - paperId: this.ids[0],
894   - classIds: this.classIds,
  1454 + examIds: [this.ids[0]],
  1455 + classIds: this.classIds
895 1456 });
896 1457  
897 1458 if (response.status != 0) {
... ... @@ -951,202 +1512,241 @@ export default {
951 1512  
952 1513 this.studentList = [...studentResults];
953 1514  
954   - var otherDatas = [];
  1515 + var show4Area = true; //显示4选项区域
955 1516  
956   - var questionHeaders = [];
  1517 + var show7Area = true; //显示7选项区域
957 1518  
958   - var questionResults = [];
  1519 + var show10Area = true; //显示10选项区域
959 1520  
960   - var questionOtherHeaders = [];
  1521 + var optionNumList = [];
961 1522  
962   - var questionOtherResults = [];
  1523 + var maxOptions = 4;
963 1524  
964   - var defaultQuestion = 6;
  1525 + var minOptions = 10; //最多10个选项
965 1526  
966   - var defaultCount = 3;
  1527 + var questionList = response.data.questionInfos;
967 1528  
968   - var defaultQuestionCount = 4;
  1529 + questionList = questionList.sort((prev, next) => { return prev.questionIndex - next.questionIndex });
969 1530  
970   - var maxQuestionCount = 4;
  1531 + for (var i = 0; i < questionList.length; i++) {
971 1532  
972   - var optionSt = 1;
  1533 + var correctAnswerValue = questionList[i].correctAnswer == "1" ? "✓" : questionList[i].correctAnswer == 2 ? "✗" : questionList[i].correctAnswer;
973 1534  
974   - for (var qheader = 0; qheader < defaultQuestion * defaultCount; qheader++) {
975   - if (qheader == 0 || qheader % 6 == 0) {
976   - questionHeaders.push({
977   - prop: "column_" + qheader,
978   - label: "题号&答案",
979   - });
980   - continue;
981   - } else if (qheader == 1 || (qheader - 1) % 6 == 0) {
982   - questionHeaders.push({
983   - prop: "column_" + qheader,
984   - label: "得分率",
985   - });
986   - optionSt = 1;
987   - continue;
988   - } else {
989   - questionHeaders.push({
990   - prop: "column_" + qheader,
991   - label: "选项" + optionSt,
992   - });
993   - optionSt += 1;
  1535 + var missCount = 0;
  1536 +
  1537 + var missI = questionList[i].details.filter(item => !item.right);
  1538 +
  1539 + missI.forEach(itemsa => {
  1540 + missCount = Number(missCount) + Number(itemsa.students?.length ?? 0)
  1541 + });
  1542 + this.questionTotal.push({
  1543 + quesion: "Q" + (questionList[i].questionIndex),
  1544 + anwser: correctAnswerValue ?? "-----",
  1545 + details: questionList[i].details,
  1546 + missPeopleNumber: missCount
  1547 + })
  1548 + if ((questionList[i].questionType == 2)) {
  1549 + //单选题可能有超过4个选项,多选题是固定的
  1550 + if (questionList[i].details?.length > maxOptions) {
  1551 + maxOptions = questionList[i].details.filter(iam => { return iam.option.indexOf('未答') < 0 })?.length;
  1552 + }
  1553 + //单选题可能有超过4个选项,多选题是固定的
  1554 + if (questionList[i].details?.length < minOptions) {
  1555 + minOptions = questionList[i].details.filter(iam => { return iam.option.indexOf('未答') < 0 })?.length;
  1556 + }
  1557 +
  1558 + optionNumList.push(questionList[i].details.filter(iam => { return iam.option.indexOf('未答') < 0 })?.length);
  1559 + }
  1560 +
  1561 + if (questionList[i].questionType == 4) {
  1562 + minOptions = 2;
  1563 + optionNumList.push(2);
994 1564 }
995 1565 }
996 1566  
997   - var noPassIndex = 0;
  1567 + show4Area = minOptions <= 4;
998 1568  
999   - this.questionHeaders = questionHeaders;
  1569 + show7Area = optionNumList.filter(o => o > 4 && o <= 7);
1000 1570  
1001   - var itema = null;
  1571 + show10Area = optionNumList.filter(o => o > 7);
1002 1572  
1003   - response.data.questionInfos = [...response.data.questionInfos]
1004 1573  
1005   - for (var qIndex = 0; qIndex < response.data.questionInfos.length; qIndex++) {
  1574 + var currentRow = {};
1006 1575  
1007   - var currentData = response.data.questionInfos[qIndex];
  1576 + if (show4Area) {
1008 1577  
1009   - var filterDetail = currentData.details.filter(fl => fl.option != '未答');
  1578 + var areaList = [];
1010 1579  
1011   - var correctAnswerValue = currentData.correctAnswer == "1" ? "✓" : currentData.correctAnswer == 2 ? "✗" : currentData.correctAnswer;
  1580 + var quesRow = Math.ceil(questionList?.length * 1.00 / 3);
1012 1581  
1013   - this.questionTotal.push({
1014   - quesion: "Q" + (qIndex + 1),
1015   - anwser: correctAnswerValue ?? "-----",
1016   - details: currentData.details
1017   - })
1018   -
1019   - if (filterDetail.length > defaultQuestionCount || filterDetail.length > maxQuestionCount) {
1020   - currentData.index = qIndex;
1021   - otherDatas.push(currentData);
1022   - if (filterDetail.length > maxQuestionCount) {
1023   - maxQuestionCount = filterDetail.length;
1024   - }
1025   - continue;
  1582 + for (var irow = 0; irow < quesRow; irow++) {
  1583 + areaList.push({});
1026 1584 }
1027   - else {
1028   - if (noPassIndex > defaultCount) {
1029   - questionResults.push(itema)
1030   - itema = null;
1031   - noPassIndex = 0;
1032   - }
1033   - var stPass = noPassIndex * defaultQuestion;
1034   - if (!itema) itema = {}
1035 1585  
1036   - var correctAnswerValue = currentData.correctAnswer == "1" ? "✓" : currentData.correctAnswer == 2 ? "✗" : currentData.correctAnswer;
  1586 + for (var i = 0; i < questionList?.length; i++) {
  1587 +
  1588 + var col = parseInt(i / quesRow);
1037 1589  
1038   - itema["column_" + (stPass)] = (qIndex + 1) + "" + correctAnswerValue;
1039   - itema["column_" + (stPass + 1)] = (currentData.gradeScoringRate * 100) + "%";
  1590 + var row = parseInt(i % quesRow);
1040 1591  
1041   - var value = "------";
  1592 + var question = questionList[i];
1042 1593  
1043   - for (var iOption = 0; iOption < defaultQuestion - 2; iOption++) {
1044   - var currentOption = filterDetail[iOption];
1045   - if (currentOption) {
1046   - var optionValue = currentOption.option == "1" ? "✓" : currentOption.option == 2 ? "✗" : currentOption.option;
  1594 + var currentRow = areaList[row];
1047 1595  
1048   - itema["column_" + (stPass + iOption + 2)] = optionValue + "(" + (currentOption.persent ?? "0%") + ")";
  1596 + var correctAnswerValue = question.correctAnswer == "1" ? "✓" : question.correctAnswer == "2" ? "✗" : question.correctAnswer;
  1597 +
  1598 + var details = question.details.filter(fl => {
  1599 + return fl.option.indexOf('未答') < 0;
  1600 + });
  1601 +
  1602 +
  1603 + for (var ilr = 0; ilr < 6; ilr++) {
  1604 +
  1605 + if (ilr == 0) {
  1606 + currentRow['column' + Number(6 * col + ilr)] = question.questionIndex + correctAnswerValue;
  1607 + }
  1608 + else if (ilr == 1) {
  1609 + currentRow['column' + Number(6 * col + ilr)] = (question.gradeScoringRate * 100).toFixed(2) + '%';
1049 1610 }
1050 1611 else {
1051   - itema["column_" + (stPass + iOption + 2)] = value
  1612 +
  1613 + var questionDetail = details[ilr - 2];
  1614 +
  1615 + var questionColumn = 'column' + Number(6 * col + ilr);
  1616 +
  1617 + if (details.length <= 4) {
  1618 +
  1619 + var questionOption = questionDetail ? (questionDetail.option == "1" ? "✓" : questionDetail.option == "2" ? "✗" : questionDetail.option) : "- -"
  1620 +
  1621 + if (questionOption != "- -") questionOption += "(" + questionDetail.persent + ")";
  1622 +
  1623 + currentRow[questionColumn] = questionOption;
  1624 + }
  1625 + else {
  1626 + currentRow[questionColumn] = "--";
  1627 + }
1052 1628 }
1053 1629 }
1054   -
1055   - noPassIndex += 1
1056 1630 }
1057 1631  
1058   - if (qIndex >= response.data.questionInfos.length - 1 && noPassIndex != 0) {
1059   - questionResults.push(itema)
1060   - itema = null;
1061   - }
  1632 + this.question4List = [...areaList]
  1633 +
1062 1634 }
1063 1635  
1064   - optionSt = 1;
1065 1636  
1066   - maxQuestionCount += 2;
  1637 + if (show7Area && show7Area.length > -1) {
1067 1638  
1068   - this.questionList = [...questionResults]
  1639 + var areaList = [];
1069 1640  
1070   - var otherCount = parseInt(defaultQuestion * defaultCount / maxQuestionCount);
  1641 + var quesRow = Math.ceil(show7Area.length * 1.00 / 2);
1071 1642  
1072   - itema = null;
  1643 + var num = 0;
1073 1644  
1074   - for (var qOHeader = 0; qOHeader < maxQuestionCount * otherCount; qOHeader++) {
1075   - if (qOHeader == 0 || qOHeader % (maxQuestionCount) == 0) {
1076   - questionOtherHeaders.push({
1077   - prop: "column_" + qOHeader,
1078   - label: "题号&答案",
1079   - });
1080   - continue;
1081   - } else if (qOHeader == 1 || (qOHeader - 1) % (maxQuestionCount) == 0) {
1082   - questionOtherHeaders.push({
1083   - prop: "column_" + qOHeader,
1084   - label: "得分率",
1085   - });
1086   - optionSt = 1;
1087   - continue;
1088   - } else {
1089   - questionOtherHeaders.push({
1090   - prop: "column_" + qOHeader,
1091   - label: "选项" + optionSt,
  1645 + for (var irow = 0; irow < quesRow; irow++) {
  1646 + areaList.push({});
  1647 + }
  1648 +
  1649 + for (var i = 0; i < questionList?.length; i++) {
  1650 +
  1651 + var question = questionList[i];
  1652 +
  1653 + var details = question.details.filter(fl => {
  1654 + return fl.option.indexOf('未答') < 0;
1092 1655 });
1093   - optionSt += 1;
  1656 +
  1657 + if (question.questionType == 2 && details.length > 4 && details.length <= 7) {
  1658 +
  1659 + var col = parseInt(num / quesRow);
  1660 +
  1661 + var row = parseInt(num % quesRow);
  1662 +
  1663 + var currentRow = areaList[row];
  1664 +
  1665 + var correctAnswerValue = question.correctAnswer == "1" ? "✓" : question.correctAnswer == 2 ? "✗" : question.correctAnswer;
  1666 +
  1667 + for (var ilr = 0; ilr < 9; ilr++) {
  1668 +
  1669 + if (ilr == 0) {
  1670 + currentRow['column' + Number(9 * col + ilr)] = question.questionIndex + correctAnswerValue;
  1671 + }
  1672 + else if (ilr == 1) {
  1673 +
  1674 + currentRow['column' + Number(9 * col + ilr)] = (question.gradeScoringRate * 100).toFixed(2) + '%';
  1675 + }
  1676 + else {
  1677 +
  1678 + var questionDetail = details[ilr - 2];
  1679 +
  1680 + var questionColumn = 'column' + Number(9 * col + ilr);
  1681 +
  1682 + currentRow[questionColumn] = questionDetail ? questionDetail.option + "(" + questionDetail.persent + ")" : "- -";
  1683 + }
  1684 + }
  1685 +
  1686 + num = num + 1;
  1687 + }
  1688 +
1094 1689 }
  1690 +
  1691 + this.question7List = [...areaList]
1095 1692 }
1096 1693  
1097   - this.questionOtherHeaders = questionOtherHeaders;
1098 1694  
1099   - noPassIndex = 0;
  1695 + if (show10Area && show10Area.length > -1) {
1100 1696  
1101   - for (var qOIndex = 0; qOIndex < otherDatas.length; qOIndex++) {
  1697 + var areaList = [];
1102 1698  
1103   - var currentData = otherDatas[qOIndex];
  1699 + var quesRow = show10Area.length;
1104 1700  
1105   - var filterDetail = currentData.details.filter(fl => fl.option != '未答');
  1701 + var num = 0;
1106 1702  
1107   - if (noPassIndex >= otherCount) {
1108   - questionOtherResults.push(itema)
1109   - itema = null;
1110   - noPassIndex = 0;
  1703 + for (var irow = 0; irow < quesRow; irow++) {
  1704 + areaList.push({});
1111 1705 }
1112 1706  
1113   - var stPass = noPassIndex * maxQuestionCount;
  1707 + for (var i = 0; i < questionList?.length; i++) {
1114 1708  
1115   - if (!itema) itema = {}
  1709 + var question = questionList[i];
1116 1710  
1117   - var correctAnswerValue = currentData.correctAnswer == "1" ? "✓" : currentData.correctAnswer == 2 ? "✗" : currentData.correctAnswer;
  1711 + var details = question.details.filter(fl => {
  1712 + return fl.option.indexOf('未答') < 0;
  1713 + });
1118 1714  
1119   - itema["column_" + (stPass)] = (Number(currentData.index) + 1) + "" + correctAnswerValue;
  1715 + if (question.questionType == 2 && details.length > 7) {
  1716 + var col = parseInt(num / quesRow);
1120 1717  
1121   - itema["column_" + (stPass + 1)] = (currentData.gradeScoringRate * 100) + "%";
  1718 + var row = num;
1122 1719  
1123   - var value = "------";
  1720 + var currentRow = areaList[row];
1124 1721  
1125   - for (var iOption = 0; iOption < maxQuestionCount - 2; iOption++) {
  1722 + var correctAnswerValue = question.correctAnswer == "1" ? "✓" : question.correctAnswer == 2 ? "✗" : question.correctAnswer;
1126 1723  
1127   - var currentOption = filterDetail[iOption];
  1724 + for (var ilr = 0; ilr < 12; ilr++) {
1128 1725  
1129   - if (currentOption) {
  1726 + if (ilr == 0) {
  1727 + currentRow['column' + Number(12 * col + ilr)] = question.questionIndex + correctAnswerValue;
  1728 + }
  1729 + else if (ilr == 1) {
  1730 + currentRow['column' + Number(12 * col + ilr)] = (question.gradeScoringRate * 100).toFixed(2) + '%';
  1731 + }
  1732 + else {
1130 1733  
1131   - var optionValue = currentOption.option == "1" ? "✓" : currentOption.option == 2 ? "✗" : currentOption.option;
  1734 + var questionDetail = details[ilr - 2];
1132 1735  
1133   - itema["column_" + (stPass + iOption + 2)] = optionValue + "(" + (currentOption.persent ?? "0%") + ")";
1134   - }
1135   - else {
1136   - itema["column_" + (stPass + iOption + 2)] = value
1137   - }
1138   - }
  1736 + var questionColumn = 'column' + Number(12 * col + ilr);
1139 1737  
1140   - noPassIndex += 1
  1738 + currentRow[questionColumn] = questionDetail ? questionDetail.option + "(" + questionDetail.persent + ")" : "- -";
  1739 + }
  1740 + }
1141 1741  
1142   - if (qOIndex >= otherDatas.length - 1 && noPassIndex != 0) {
  1742 + num = num + 1;
  1743 + }
1143 1744  
1144   - questionOtherResults.push(itema)
1145   - itema = null;
1146 1745 }
  1746 +
  1747 + this.question10List = [...areaList]
1147 1748 }
1148 1749  
1149   - this.questionOtherList = [...questionOtherResults]
1150 1750  
1151 1751 },
1152 1752 async _loadAskInteractives() {
... ... @@ -1301,6 +1901,14 @@ export default {
1301 1901 },
1302 1902 async _loadTestStudentReport() {
1303 1903  
  1904 + this.testStudents = [];
  1905 + this.testStudentOptions = [];
  1906 + this.studentAnsered = [];
  1907 + this.studentAnseredOptions = [];
  1908 + this.studentRank = [];
  1909 + this.studentQuestions = [];
  1910 + this.studentQuestionOptions = [];
  1911 +
1304 1912 const examStudentReport =
1305 1913 this.role == "ROLE_PERSONAL"
1306 1914 ? this.$request.pExamStudentReport
... ... @@ -1317,7 +1925,7 @@ export default {
1317 1925  
1318 1926 let optionsList = [];
1319 1927  
1320   - this.testStudents = data?.list.map((item) => {
  1928 + let rTestStudents = data?.list.map((item) => {
1321 1929 let params = {};
1322 1930 const detail = JSON.parse(item.detail);
1323 1931 if (detail.length) {
... ... @@ -1342,9 +1950,21 @@ export default {
1342 1950 };
1343 1951 });
1344 1952  
1345   - this.testStudentOptions = optionsList.sort((a, b) => {
  1953 + let rtestStudentOptions = optionsList.sort((a, b) => {
1346 1954 return a.id - b.id;
1347 1955 });
  1956 +
  1957 + if (this.currentType == "成绩排名") {
  1958 + this.studentRank = [...rTestStudents]
  1959 + }
  1960 + else if (this.currentType == "小题分报表") {
  1961 + this.studentQuestions = [...rTestStudents]
  1962 + this.studentQuestionOptions = [...rtestStudentOptions]
  1963 + }
  1964 + else if (this.currentType == "作答明细") {
  1965 + this.studentAnsered = [...rTestStudents]
  1966 + this.studentAnseredOptions = [...rtestStudentOptions]
  1967 + }
1348 1968 },
1349 1969 async _loadTestQuestionReport() {
1350 1970 //试题分析
... ... @@ -1365,11 +1985,62 @@ export default {
1365 1985 return;
1366 1986 }
1367 1987  
1368   - let optionsList = [{}, {}, {}, {}, {}];
  1988 + //主观
  1989 + var subjective = {
  1990 + sum: 0.0,
  1991 + avg: 0.0,
  1992 + rate: 0.0,
  1993 + number: 0,
  1994 + max: 0,
  1995 + min: 9999,
  1996 + answeredRate: 0
  1997 + };
  1998 +
  1999 + //客观
  2000 + var objective = {
  2001 + sum: 0.0,
  2002 + avg: 0.0,
  2003 + rate: 0.0,
  2004 + number: 0,
  2005 + max: 0,
  2006 + min: 9999,
  2007 + answeredRate: 0
  2008 + };
  2009 +
  2010 + //汇总
  2011 + var summary = {
  2012 + sum: 0.0,
  2013 + avg: 0.0,
  2014 + rate: 0.0,
  2015 + number: 0,
  2016 + max: 0,
  2017 + min: 9999,
  2018 + answeredRate: 0
  2019 + };
  2020 +
  2021 + var maxOption = 0;
  2022 +
  2023 + data?.list?.forEach((item) =>{
  2024 +
  2025 + const detail = JSON.parse(item.detail);
  2026 +
  2027 + if(maxOption < detail.length)
  2028 + {
  2029 + maxOption = detail.length;
  2030 + }
  2031 + })
  2032 +
  2033 + let optionsList = [];
  2034 +
  2035 + for(var io=0;io<maxOption;io++){
  2036 + optionsList.push({})
  2037 + }
1369 2038  
1370 2039 let tableData = data?.list?.map((item) => {
1371 2040 let params = {};
  2041 +
1372 2042 const detail = JSON.parse(item.detail);
  2043 +
1373 2044 let lastOPtion = detail?.find((item) => {
1374 2045 return item.option == "未答";
1375 2046 });
... ... @@ -1378,31 +2049,58 @@ export default {
1378 2049 });
1379 2050  
1380 2051 optionsList.map((items, index) => {
1381   - if (index != 4) {
1382   - params["count" + index] =
1383   - defaultArr[index]?.option != "未答"
1384   - ? defaultArr[index]?.count
1385   - : "";
1386   - params["persent" + index] =
1387   - defaultArr[index]?.option != "未答"
1388   - ? defaultArr[index]?.persent
1389   - : "";
1390   - params["option" + index] =
1391   - defaultArr[index]?.option != "未答"
1392   - ? defaultArr[index]?.option == 1
1393   - ? "✓"
1394   - : defaultArr[index]?.option == 2
1395   - ? "✗"
1396   - : defaultArr[index]?.option
1397   - : "";
1398   - items["title"] = "选项" + (index + 1);
1399   - } else {
1400   - items["title"] = "未答";
1401   - params["count" + index] = lastOPtion.count;
1402   - params["persent" + index] = lastOPtion.persent;
1403   - params["option" + index] = "?";
1404   - }
  2052 + params["count" + index] =
  2053 + defaultArr[index]?.option != "未答"
  2054 + ? defaultArr[index]?.count
  2055 + : "";
  2056 + params["persent" + index] =
  2057 + defaultArr[index]?.option != "未答"
  2058 + ? defaultArr[index]?.persent
  2059 + : "";
  2060 + params["option" + index] =
  2061 + defaultArr[index]?.option != "未答"
  2062 + ? defaultArr[index]?.option == 1
  2063 + ? "✓"
  2064 + : defaultArr[index]?.option == 2
  2065 + ? "✗"
  2066 + : defaultArr[index]?.option
  2067 + : "";
  2068 + items["title"] = "选项" + (index + 1);
  2069 + // if (index != 4) {
  2070 +
  2071 + // } else {
  2072 + // items["title"] = "未答";
  2073 + // params["count" + index] = lastOPtion.count;
  2074 + // params["persent" + index] = lastOPtion.persent;
  2075 + // params["option" + index] = "?";
  2076 + // }
1405 2077 });
  2078 +
  2079 + summary.sum += parseFloat(item.score);
  2080 + summary.avg += parseFloat(item.avgScore);
  2081 + summary.rate += parseFloat(item.classScoringRate);
  2082 + summary.number += 1;
  2083 + summary.max = item.highestScore > summary.max ? item.highestScore : summary.max;
  2084 + summary.min = item.lowestScore < summary.min ? item.lowestScore : summary.min;
  2085 +
  2086 + if (item.questionType == 5) {
  2087 + subjective.sum += parseFloat(item.score);
  2088 + subjective.avg += parseFloat(item.avgScore);
  2089 + subjective.rate += parseFloat(item.classScoringRate);
  2090 + subjective.number += 1;
  2091 + subjective.max = item.highestScore > summary.max ? item.highestScore : summary.max;
  2092 + subjective.min = item.lowestScore < summary.min ? item.lowestScore : summary.min;
  2093 + }
  2094 +
  2095 + else {
  2096 + objective.sum += parseFloat(item.score);
  2097 + objective.avg += parseFloat(item.avgScore);
  2098 + objective.rate += parseFloat(item.classScoringRate);
  2099 + objective.number += 1;
  2100 + objective.max = item.highestScore > summary.max ? item.highestScore : summary.max;
  2101 + objective.min = item.lowestScore < summary.min ? item.lowestScore : summary.min;
  2102 + }
  2103 +
1406 2104 return {
1407 2105 ...item,
1408 2106 ...params,
... ... @@ -1414,6 +2112,58 @@ export default {
1414 2112 });
1415 2113  
1416 2114 this.testQuestionOptions = [...optionsList];
  2115 +
  2116 + this.testQuestions.push({
  2117 + questionIndex: "汇总",
  2118 + questionType: "主观题",
  2119 + //满分值
  2120 + score: subjective.sum,
  2121 + //最高分
  2122 + highestScore: subjective.max,
  2123 + //最低分
  2124 + lowestScore: subjective.min == 9999 ? 0 : subjective.min,
  2125 + //平均分
  2126 + avgScore: subjective.avg == 0 ? 0 : Number(subjective.avg).toFixed(2),
  2127 + //已考得分率
  2128 + classScoringRate: subjective.sum == 0 ? 0 : Number(subjective.avg * 100 / subjective.sum).toFixed(2)
  2129 + })
  2130 +
  2131 + this.testQuestions.push({
  2132 + questionIndex: "客观题",
  2133 + type: "colspan",
  2134 + //满分值
  2135 + knowledge: objective.sum,
  2136 + //最高分
  2137 + score: objective.max,
  2138 + //最低分
  2139 + highestScore: objective.min == 9999 ? 0 : objective.min,
  2140 + //平均分
  2141 + lowestScore: objective.avg == 0 ? 0 : Number(objective.avg).toFixed(2),
  2142 + //已考得分率
  2143 + avgScore: objective.sum == 0 ? 0 : Number(objective.avg * 100 / objective.sum).toFixed(2)
  2144 + })
  2145 +
  2146 +
  2147 +
  2148 + this.testQuestions.push({
  2149 + questionIndex: "合计",
  2150 + type: "colspan",
  2151 + //满分值
  2152 + knowledge: summary.sum,
  2153 + //最高分
  2154 + score: summary.max,
  2155 + //最低分
  2156 + highestScore: summary.min == 9999 ? 0 : summary.min,
  2157 + //平均分
  2158 + lowestScore: summary.avg == 0 ? 0 : Number(summary.avg).toFixed(2),
  2159 + //已考得分率
  2160 + avgScore: summary.sum == 0 ? 0 : Number(summary.avg / summary.sum * 100).toFixed(2)
  2161 + })
  2162 + },
  2163 + keydownRange(event) {
  2164 + if (event.key == "-" || event.key == "e") {
  2165 + event.returnValue = "";
  2166 + }
1417 2167 }
1418 2168 }
1419 2169 }
... ... @@ -1425,7 +2175,7 @@ export default {
1425 2175  
1426 2176 .row-line {
1427 2177 overflow: hidden;
1428   - width: calc(20% - 2px);
  2178 + width: calc(20% - 4px);
1429 2179 border: 1px solid #ebeef5;
1430 2180 background: #f5f7fa;
1431 2181 display: inline-block;
... ... @@ -1445,4 +2195,69 @@ export default {
1445 2195 .red {
1446 2196 color: #f30;
1447 2197 }
  2198 +
  2199 +.dia-tab-box {
  2200 + font-size: 14px;
  2201 +
  2202 + .boxitem {
  2203 + border: 1px solid #DCDFE6;
  2204 + margin: 0px !important;
  2205 +
  2206 + * {
  2207 + border: none;
  2208 + }
  2209 + }
  2210 +
  2211 + .dia-tab-tit,
  2212 + .dia-tab-item {
  2213 +
  2214 +
  2215 + i {
  2216 + color: #f30;
  2217 + padding-right: 5px;
  2218 + }
  2219 +
  2220 + display: flex;
  2221 +
  2222 + .item {
  2223 + width: 80px;
  2224 + }
  2225 +
  2226 + .item1 {
  2227 + padding-left: 10px;
  2228 + width: 10%;
  2229 + }
  2230 +
  2231 + .item2 {
  2232 + width: 18%;
  2233 + }
  2234 +
  2235 + .item3 {
  2236 + padding-left: 12px;
  2237 + flex: 1;
  2238 + }
  2239 +
  2240 + .score-ipt {
  2241 + width: 100px;
  2242 + }
  2243 + }
  2244 +
  2245 + .dia-tab-tit {
  2246 + background: rgb(245, 247, 250) !important
  2247 + }
  2248 +
  2249 + .add {
  2250 + display: flex;
  2251 + justify-content: center;
  2252 + margin: 0 auto;
  2253 +
  2254 + p {
  2255 + cursor: pointer;
  2256 + }
  2257 +
  2258 + .el-button {
  2259 + margin-right: 6px;
  2260 + }
  2261 + }
  2262 +}
1448 2263 </style>
1449 2264 \ No newline at end of file
... ...
src/views/basic/askTestQuestion/gradeAnalysis.vue
... ... @@ -4,8 +4,8 @@
4 4 <div class="default-title">即时测报表</div>
5 5 </el-header>
6 6 <div class="default-filter">
7   - <el-input v-model="query.paper" placeholder="搜索试卷" suffix-icon="el-icon-search" class="filter-input"
8   - type="number" clearable />
  7 + <!-- <el-input v-model="query.paper" placeholder="搜索试卷" suffix-icon="el-icon-search" class="filter-input"
  8 + type="number" clearable /> -->
9 9 <el-select v-model="query.grade" class="filter-select" placeholder="选择年级">
10 10 <el-option v-for="item in classList" :key="item.grade" :label="item.gradeName" :value="item.grade" />
11 11 </el-select>
... ... @@ -107,16 +107,19 @@ export default {
107 107 this.$message.error('选择对象考试班级为空,请刷新列表');
108 108 return;
109 109 }
110   -
  110 +
111 111 var classListStr = JSON.stringify(currentRow.classInfos);
112 112  
113 113 var paperId = currentRow.paperId;
114 114  
115 115 var title = currentRow.paperName;
116   -
  116 +
117 117 let routerItem = {
118 118 path: "/testGradeReportDetail",
119   - query: { classListStr: classListStr, paperId: paperId, title: title },
  119 + query: {
  120 + classListStr: classListStr, paperId: paperId, title: title,
  121 + examIds: currentRow.examIds.join(",")
  122 + },
120 123 };
121 124  
122 125 this.$router.push(routerItem);
... ...
src/views/basic/askTestQuestion/gradeAnalysisDetail.vue
... ... @@ -11,33 +11,41 @@
11 11 </el-header>
12 12 <div class="default-filter">
13 13 已考班级:
  14 + <el-checkbox style="margin-right:15px;" class="_el-checkbox" :checked="checkAll"
  15 + @change="_handleCheckAllChange">全选</el-checkbox>
14 16 <el-checkbox-group style="display: inline-block" v-model="checkedClassInfos" @change="_handleCheckedClassChange">
15   - <el-checkbox class="_el-checkbox" v-model="checkAll" @change="_handleCheckAllChange">全选</el-checkbox>
16 17 <el-checkbox class="_el-checkbox" v-for="classItem in classInfos" :key="classItem.classId"
17   - :label="classItem.className">
  18 + :label="classItem.classId">
18 19 {{ classItem.className }}
19 20 </el-checkbox>
20 21 </el-checkbox-group>
  22 + <el-button type="primary" style='float: right;' @click="_anys">分析</el-button>
21 23 </div>
22 24 <el-main>
23   - <div style="position: relative">
  25 + <div style="position: relative" Id="print-content">
24 26 <el-tabs v-model="tabType" v-loading="queryLoading" type="card" class="default-tabs">
25 27 <el-tab-pane :name="'成绩测验单'" :label="`成绩测验单`" style="padding: 0 20px">
26 28 <div style="height: calc(100% - 80px);">
27   - <el-row class="row-subfix">
  29 + <el-row class="row-subfix print-hidden">
28 30 <div style="float: right;margin-bottom: 20px;">
29   - <el-button type="primary" class="opration-btn" icon="el-icon-upload2">导出报表</el-button>
30   - <el-button type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
  31 + 单题低分率:
  32 + <el-input-number class="parent-number" v-model="lowLevel" :min="1" :max="100" label="低分率">
  33 + </el-input-number>
  34 + <el-button style="margin-left:10px;" @click="_import" type="primary" class="opration-btn"
  35 + icon="el-icon-upload2">导出报表</el-button>
  36 + <el-button @click="_print" type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
31 37 </div>
32 38 </el-row>
33   - <el-row class="row-subfix" :key="index" v-for="(item, index) in titleInfo">
  39 + <el-row class="row-subfix" :key="index" v-for="(item, index) in testTranscript.titleInfo || []">
34 40 <div class="row-line">
35 41 <span class="line-subfix">班级:</span>
36 42 <span class="line-value">{{ item.className }}</span>
37 43 </div>
38 44 <div class="row-line">
39 45 <span class="line-subfix">试卷名称:</span>
40   - <span class="line-value">{{ item.paperName }}</span>
  46 + <el-tooltip effect="dark" :content="item.paperName" placement="left">
  47 + <span class="line-value">{{ item.paperName }}</span>
  48 + </el-tooltip>
41 49 </div>
42 50 <div class="row-line">
43 51 <span class="line-subfix">测验时间:</span>
... ... @@ -45,7 +53,7 @@
45 53 </div>
46 54 </el-row>
47 55 <el-row class="row-subfix">
48   - <el-table class="default-table" style="margin-top: 10px" :data="titleInfo">
  56 + <el-table class="default-table" style="margin-top: 10px" :data="testTranscript.titleInfo || []">
49 57 <el-table-column prop="testCount" label="测验人数" width="120" />
50 58 <el-table-column prop="avg" label="平均分" width="120" />
51 59 <el-table-column prop="hight" label="最高分" width="120" />
... ... @@ -58,34 +66,124 @@
58 66 </el-table>
59 67 </el-row>
60 68 <el-row class="row-subfix">
61   - <el-table class="default-table" style="margin-top: 10px" :data="studentList">
  69 + <el-table class="default-table" style="margin-top: 10px" :data="testTranscript.studentList || []">
62 70 <el-table-column :width="item.label == '学号' ? 120 : 0" :prop="item.prop" :label="item.label"
63   - :key="index" v-for="(item, index) in studentHeader" />
  71 + :key="index" v-for="(item, index) in testTranscript.studentHeader || []" />
64 72 </el-table>
65 73 </el-row>
66   - <el-row class="row-subfix">
67   - <el-table class="default-table" style="margin-top: 10px" :data="questionList">
68   - <el-table-column :width="item.label == '题号&答案' ? 80 : 0" :prop="item.prop" :label="item.label"
69   - :key="index" v-for="(item, index) in questionHeaders" />
  74 + <el-row class="row-subfix" style="margin-top:10px">
  75 + <el-table class="default-table"
  76 + v-if="testTranscript && testTranscript.question4List && testTranscript.question4List.length >= 1"
  77 + :data="testTranscript.question4List">
  78 + <el-table-column prop="column0" label="题号&答案" />
  79 + <el-table-column prop="column1" label="得分率">
  80 + <template slot-scope="scoped">
  81 + <div :class="Number(scoped.row.column1?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  82 + {{ scoped.row.column1 }}
  83 + </div>
  84 + </template>
  85 + </el-table-column>
  86 + <el-table-column prop="column2" label="选项1" />
  87 + <el-table-column prop="column3" label="选项2" />
  88 + <el-table-column prop="column4" label="选项3" />
  89 + <el-table-column prop="column5" label="选项4" />
  90 + <el-table-column prop="column6" label="题号&答案" />
  91 + <el-table-column prop="column7" label="得分率">
  92 + <template slot-scope="scoped">
  93 + <div :class="Number(scoped.row.column7?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  94 + {{ scoped.row.column7 }}
  95 + </div>
  96 + </template>
  97 + </el-table-column>
  98 + <el-table-column prop="column8" label="选项1" />
  99 + <el-table-column prop="column9" label="选项2" />
  100 + <el-table-column prop="column10" label="选项3" />
  101 + <el-table-column prop="column11" label="选项4" />
  102 + <el-table-column prop="column12" label="题号&答案" />
  103 + <el-table-column prop="column13" label="得分率">
  104 + <template slot-scope="scoped">
  105 + <div :class="Number(scoped.row.column13?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  106 + {{ scoped.row.column13 }}
  107 + </div>
  108 + </template>
  109 + </el-table-column>
  110 + <el-table-column prop="column14" label="选项1" />
  111 + <el-table-column prop="column15" label="选项2" />
  112 + <el-table-column prop="column16" label="选项3" />
  113 + <el-table-column prop="column17" label="选项4" />
  114 + </el-table>
  115 + </el-row>
  116 + <el-row class="row-subfix" style="margin-top:10px">
  117 + <el-table class="default-table"
  118 + v-if="testTranscript && testTranscript.question7List && testTranscript.question7List.length >= 1"
  119 + :data="testTranscript.question7List">
  120 + <el-table-column prop="column0" label="题号&答案" />
  121 + <el-table-column prop="column1" label="得分率">
  122 + <template slot-scope="scoped">
  123 + <div :class="Number(scoped.row.column1?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  124 + {{ scoped.row?.column1 }}
  125 + </div>
  126 + </template>
  127 + </el-table-column>
  128 + <el-table-column prop="column2" label="选项1" />
  129 + <el-table-column prop="column3" label="选项2" />
  130 + <el-table-column prop="column4" label="选项3" />
  131 + <el-table-column prop="column5" label="选项4" />
  132 + <el-table-column prop="column6" label="选项5" />
  133 + <el-table-column prop="column7" label="选项6" />
  134 + <el-table-column prop="column8" label="选项7" />
  135 + <el-table-column prop="column9" label="题号&答案" />
  136 + <el-table-column prop="column10" label="得分率">
  137 + <template slot-scope="scoped">
  138 + <div :class="Number(scoped.row.column10?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  139 + {{ scoped.row?.column10 }}
  140 + </div>
  141 + </template>
  142 + </el-table-column>
  143 + <el-table-column prop="column11" label="选项1" />
  144 + <el-table-column prop="column12" label="选项2" />
  145 + <el-table-column prop="column13" label="选项3" />
  146 + <el-table-column prop="column14" label="选项4" />
  147 + <el-table-column prop="column15" label="选项5" />
  148 + <el-table-column prop="column16" label="选项6" />
  149 + <el-table-column prop="column17" label="选项7" />
70 150 </el-table>
71 151 </el-row>
72   - <el-row class="row-subfix" v-if="questionOtherList && questionOtherList.length >= 1">
73   - <el-table class="default-table" style="margin-top: 10px" :data="questionOtherList">
74   - <el-table-column :prop="item.prop" :label="item.label" :key="index"
75   - v-for="(item, index) in questionOtherHeaders" />
  152 + <el-row class="row-subfix">
  153 + <el-table class="default-table"
  154 + v-if="testTranscript && testTranscript.question10List && testTranscript.question10List.length >= 1"
  155 + :data="testTranscript.question10List">
  156 + <el-table-column prop="column0" label="题号&答案" />
  157 + <el-table-column prop="column1" label="得分率">
  158 + <template slot-scope="scoped">
  159 + <div :class="Number(scoped.row.column1?.replace('%', '')) <= lowLevel ? 'lowLevelClass' : ''">
  160 + {{ scoped.row?.column1 }}
  161 + </div>
  162 + </template>
  163 + </el-table-column>
  164 + <el-table-column prop="column2" label="选项1" />
  165 + <el-table-column prop="column3" label="选项2" />
  166 + <el-table-column prop="column4" label="选项3" />
  167 + <el-table-column prop="column5" label="选项4" />
  168 + <el-table-column prop="column6" label="选项5" />
  169 + <el-table-column prop="column7" label="选项6" />
  170 + <el-table-column prop="column8" label="选项7" />
  171 + <el-table-column prop="column9" label="选项8" />
  172 + <el-table-column prop="column10" label="选项9" />
  173 + <el-table-column prop="column11" label="选项10" />
76 174 </el-table>
77 175 </el-row>
78 176 <el-row class="row-subfix">
79   - <el-table class="default-table" style="margin-top: 10px" :data="questionTotal">
  177 + <el-table class="default-table" style="margin-top: 10px" :data="testTranscript.questionTotal || []">
80 178 <el-table-column prop="quesion" label="题号" width="120" />
81 179 <el-table-column prop="anwser" label="答案" width="120" />
82 180 <el-table-column prop="student" label="答错学生">
83 181 <template slot-scope="scoped">
84 182 <span>总计 <span style="color:red;">
85   - {{ scoped.row.details.filter(item => !item.isRight).length }}</span> 人
  183 + {{ scoped.row.missPeopleNumber }}</span> 人
86 184 </span>
87 185 <span style="margin: 10px 0;"
88   - v-for="(item, index) in scoped.row.details.filter(item => !item.isRight)">
  186 + v-for="(item, index) in scoped.row.details.filter(item => !item.right)">
89 187 选{{ item.option }}:{{ item.students.join("/") }}
90 188 </span>
91 189 <span></span>
... ... @@ -94,35 +192,174 @@
94 192 </el-table>
95 193 </el-row>
96 194 </div>
97   - <div style="height: 80px;">
98   - <el-pagination background layout="prev, pager, next" :total="testTranscriptCount">
99   - </el-pagination>
100   - </div>
  195 + <div style="height: 80px; width:240px;margin:20px auto;" class="print-hidden">
  196 + <el-button type="default" :size="'small'" @click="_changePage('prev')">
  197 + 上一页</el-button>
  198 + {{ currentPage || 0 }}/{{ totalPage || 0 }}
  199 + <el-button type="default" style="margin-left:0px" :size="'small'"
  200 + @click="_changePage('next')">下一页</el-button>
  201 + </div>
  202 + <div style="display: none;">
  203 + <div id="test-print">
  204 + <div v-for="(testTranscript, index) in testTranscriptDatas">
  205 + <div style="margin-top:20px">
  206 + <el-row class="row-subfix" :key="index" v-for="(item, index) in testTranscript.titleInfo || []">
  207 + <div class="row-line">
  208 + <span class="line-subfix">班级:</span>
  209 + <span class="line-value">{{ item.className }}</span>
  210 + </div>
  211 + <div class="row-line">
  212 + <span class="line-subfix">试卷名称:</span>
  213 + <span class="line-value">{{ item.paperName }}</span>
  214 + </div>
  215 + <div class="row-line">
  216 + <span class="line-subfix">测验时间:</span>
  217 + <span class="line-value">{{ item.testTime }}</span>
  218 + </div>
  219 + </el-row>
  220 + <el-row class="row-subfix">
  221 + <el-table class="default-table" style="margin-top: 10px" :data="testTranscript.titleInfo || []">
  222 + <el-table-column prop="testCount" label="测验人数" width="120" />
  223 + <el-table-column prop="avg" label="平均分" width="120" />
  224 + <el-table-column prop="hight" label="最高分" width="120" />
  225 + <el-table-column prop="low" label="最低分" width="120" />
  226 + <el-table-column prop="title" label="缺考名单">
  227 + <template slot-scope="scoped">
  228 + {{ scoped.row.miss.join("/") }}
  229 + </template>
  230 + </el-table-column>
  231 + </el-table>
  232 + </el-row>
  233 + <el-row class="row-subfix">
  234 + <el-table class="default-table" style="margin-top: 10px" :data="testTranscript.studentList || []">
  235 + <el-table-column :width="item.label == '学号' ? 120 : 0" :prop="item.prop" :label="item.label"
  236 + :key="index" v-for="(item, index) in testTranscript.studentHeader || []" />
  237 + </el-table>
  238 + </el-row>
  239 + <el-row class="row-subfix" style="margin-top:10px">
  240 + <el-table class="default-table"
  241 + v-if="testTranscript && testTranscript.question4List && testTranscript.question4List.length >= 1"
  242 + :data="testTranscript.question4List">
  243 + <el-table-column prop="column0" label="题号&答案" />
  244 + <el-table-column prop="column1" label="得分率" />
  245 + <el-table-column prop="column2" label="选项1" />
  246 + <el-table-column prop="column3" label="选项2" />
  247 + <el-table-column prop="column4" label="选项3" />
  248 + <el-table-column prop="column5" label="选项4" />
  249 + <el-table-column prop="column6" label="题号&答案" />
  250 + <el-table-column prop="column7" label="得分率" />
  251 + <el-table-column prop="column8" label="选项1" />
  252 + <el-table-column prop="column9" label="选项2" />
  253 + <el-table-column prop="column10" label="选项3" />
  254 + <el-table-column prop="column11" label="选项4" />
  255 + <el-table-column prop="column12" label="题号&答案" />
  256 + <el-table-column prop="column13" label="得分率" />
  257 + <el-table-column prop="column14" label="选项1" />
  258 + <el-table-column prop="column15" label="选项2" />
  259 + <el-table-column prop="column16" label="选项3" />
  260 + <el-table-column prop="column17" label="选项4" />
  261 + </el-table>
  262 + </el-row>
  263 + <el-row class="row-subfix" style="margin-top:10px">
  264 + <el-table class="default-table"
  265 + v-if="testTranscript && testTranscript.question7List && testTranscript.question7List.length >= 1"
  266 + :data="testTranscript.question7List">
  267 + <el-table-column prop="column0" label="题号&答案" />
  268 + <el-table-column prop="column1" label="得分率" />
  269 + <el-table-column prop="column2" label="选项1" />
  270 + <el-table-column prop="column3" label="选项2" />
  271 + <el-table-column prop="column4" label="选项3" />
  272 + <el-table-column prop="column5" label="选项4" />
  273 + <el-table-column prop="column6" label="选项5" />
  274 + <el-table-column prop="column7" label="选项6" />
  275 + <el-table-column prop="column8" label="选项7" />
  276 + <el-table-column prop="column9" label="题号&答案" />
  277 + <el-table-column prop="column10" label="得分率" />
  278 + <el-table-column prop="column11" label="选项1" />
  279 + <el-table-column prop="column12" label="选项2" />
  280 + <el-table-column prop="column13" label="选项3" />
  281 + <el-table-column prop="column14" label="选项4" />
  282 + <el-table-column prop="column15" label="选项5" />
  283 + <el-table-column prop="column16" label="选项6" />
  284 + <el-table-column prop="column17" label="选项7" />
  285 + </el-table>
  286 + </el-row>
  287 + <el-row class="row-subfix">
  288 + <el-table class="default-table"
  289 + v-if="testTranscript && testTranscript.question10List && testTranscript.question10List.length >= 1"
  290 + :data="testTranscript.question10List">
  291 + <el-table-column prop="column0" label="题号&答案" />
  292 + <el-table-column prop="column1" label="得分率" />
  293 + <el-table-column prop="column2" label="选项1" />
  294 + <el-table-column prop="column3" label="选项2" />
  295 + <el-table-column prop="column4" label="选项3" />
  296 + <el-table-column prop="column5" label="选项4" />
  297 + <el-table-column prop="column6" label="选项5" />
  298 + <el-table-column prop="column7" label="选项6" />
  299 + <el-table-column prop="column8" label="选项7" />
  300 + <el-table-column prop="column9" label="选项8" />
  301 + <el-table-column prop="column10" label="选项9" />
  302 + <el-table-column prop="column11" label="选项10" />
  303 + </el-table>
  304 + </el-row>
  305 + <el-row class="row-subfix">
  306 + <el-table class="default-table" style="margin-top: 10px"
  307 + :data="testTranscript.questionTotal || []">
  308 + <el-table-column prop="quesion" label="题号" width="120" />
  309 + <el-table-column prop="anwser" label="答案" width="120" />
  310 + <el-table-column prop="student" label="答错学生">
  311 + <template slot-scope="scoped">
  312 + <span>总计 <span style="color:red;">
  313 + {{ scoped.row.missPeopleNumber }}</span> 人
  314 + </span>
  315 + <span style="margin: 10px 0;"
  316 + v-for="(item, index) in scoped.row.details.filter(item => !item.right)">
  317 + 选{{ item.option }}:{{ item.students.join("/") }}
  318 + </span>
  319 + <span></span>
  320 + </template>
  321 + </el-table-column>
  322 + </el-table>
  323 + </el-row>
  324 + </div>
  325 + </div>
  326 + </div>
  327 + </div>
  328 +
101 329 </el-tab-pane>
102 330 <el-tab-pane :name="'班级对比情况'" :label="`班级对比情况`" style="padding: 0 20px">
103 331 <div style="float: right;margin-bottom: 20px;">
104   - <el-button type="primary" class="opration-btn" icon="el-icon-upload2">导出报表</el-button>
105   - <el-button type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
  332 + <el-button @click="_studentLevelSet" class="green-el-button" type="primary">
  333 + 设置学生成绩等级
  334 + </el-button>
  335 + <el-button @click="_import" type="primary" class="opration-btn" icon="el-icon-upload2">导出报表</el-button>
  336 + <el-button @click="_print" type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
106 337 </div>
107 338 <el-table class="default-table" :data="classdiffExamReport">
108   - <el-table-column prop="index" label="序号" width="120" />
109   - <el-table-column prop="className" label="班级" width="120" />
110   - <el-table-column label="测验人数/班级人数">
  339 + <el-table-column prop="index" label="序号" width="60" />
  340 + <el-table-column prop="className" label="班级" width="80" />
  341 + <el-table-column label="测验人数/班级人数" width="180">
111 342 <template slot-scope="scoped">
112 343 {{ scoped.row.testCount }} / {{ scoped.row.classCount }}
113 344 </template>
114 345 </el-table-column>
115   - <el-table-column prop="title" label="参与度" width="120">
  346 + <el-table-column prop="title" label="参与度" width="100">
116 347 <template slot-scope="scoped">
117   - {{ scoped.row.testCount / scoped.row.classCount }}
  348 + {{ Number(scoped.row.testCount * 100 / scoped.row.classCount).toFixed(2) }}%
118 349 </template>
119 350 </el-table-column>
120   - <el-table-column prop="avg" label="班平均分" width="120" />
121   - <el-table-column prop="hight" label="班最高分" width="120" />
122   - <el-table-column prop="low" label="班最低分" width="120" />
  351 + <el-table-column prop="avg" label="班平均分" width="100" />
  352 + <el-table-column prop="hight" label="班最高分" width="100" />
  353 + <el-table-column prop="low" label="班最低分" width="100" />
123 354 <el-table-column prop="front20" label="前20名均分" width="120" />
124 355 <el-table-column prop="last20" label="后20名均分" width="120" />
125   - <el-table-column prop="excellenRate" label="优秀数(率)" width="120">
  356 + <el-table-column v-for="(item, index) in defaultLevels.levels" :key="index"
  357 + :label="item[0] ? item[0] + '数(率)' : ''">
  358 + <template slot-scope="scoped">
  359 + {{ scoped.row.leverValues[item[0]] }}
  360 + </template>
  361 + </el-table-column>
  362 + <!-- <el-table-column prop="excellenRate" label="优秀数(率)" width="120">
126 363 <template slot-scope="scoped">
127 364 {{ scoped.row.excellenRate }}%
128 365 </template>
... ... @@ -141,35 +378,77 @@
141 378 <template slot-scope="scoped">
142 379 {{ scoped.row.passRate }}%
143 380 </template>
144   - </el-table-column>
  381 + </el-table-column> -->
145 382 </el-table>
146 383 </el-tab-pane>
147 384 <el-tab-pane :name="'试题分析表'" :label="`试题分析表`" style="padding: 0 20px">
148 385 <div style="float: right;margin-bottom: 20px;">
149   - <el-button type="primary" class="opration-btn" icon="el-icon-upload2">导出报表</el-button>
150   - <el-button type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
  386 + 单题低分率
  387 + <el-input-number class="parent-number" v-model="lowLevel" :min="1" :max="100" label="低分率">
  388 + </el-input-number>
  389 + <el-button @click="_import" type="primary" style="margin-left:10px" class="opration-btn"
  390 + icon="el-icon-upload2">导出报表</el-button>
  391 + <el-button @click="_print" type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
151 392 </div>
152   - <el-table class="default-table" :data="testPaperExamReport">
  393 + <el-table class="default-table" :data="testPaperExamReport" :span-method="arraySpanMethod">
153 394 <el-table-column prop="questionIndex" label="题号" width="120" />
154 395 <el-table-column prop="questionType" label="题型" width="100">
155 396 <template slot-scope="scope">
156 397 {{ setSubPro(scope.row.questionType) }}
157 398 </template>
158 399 </el-table-column>
159   - <el-table-column prop="score" label="知识点" />
160   - <el-table-column prop="score" label="满分值" width="120" />
161   - <el-table-column prop="avgScore" label="年级平均分" width="120" />
162   - <el-table-column prop="gradeScoringRate" label="年级得分率" width="120" />
  400 + <el-table-column prop="knowledge" label="知识点">
  401 + <template slot-scope="scoped">
  402 + <el-tooltip effect="dark" :content="scoped.row.knowledge" placement="left">
  403 + <span class="overflowText">
  404 + {{ scoped.row.knowledge }}
  405 + </span>
  406 + </el-tooltip>
  407 + </template>
  408 + </el-table-column>
  409 + <el-table-column prop="score" label="满分值" width="120">
  410 + <template slot-scope="scoped">
  411 + <div v-if="scoped.row.type == 'colspan'">
  412 + {{ Number(scoped.row.score).toFixed(2) }}
  413 + </div>
  414 + <div v-else>
  415 + {{ scoped.row.score }}
  416 + </div>
  417 + </template>
  418 + </el-table-column>
  419 + <el-table-column prop="avgScore" label="年级平均分" width="120">
  420 + <template slot-scope="scoped">
  421 + <div v-if="scoped.row.type == 'colspan' && scoped.row.questionType != '客观题'"
  422 + :class="Number(scoped.row.avgScore) < lowLevel ? 'lowLevelClass' : ''">
  423 + {{ Number(scoped.row.avgScore).toFixed(2) }} %
  424 + </div>
  425 + <div v-else>
  426 + {{ scoped.row.avgScore }}
  427 + </div>
  428 + </template>
  429 + </el-table-column>
  430 + <el-table-column prop="gradeScoringRate" label="年级得分率" width="120">
  431 + <template slot-scope="scoped">
  432 + <div v-if="scoped.row.type == 'colspan'"
  433 + :class="scoped.row.gradeScoringRate < lowLevel ? 'lowLevelClass' : ''">
  434 + {{ scoped.row.gradeScoringRate }} %
  435 + </div>
  436 + <div v-else="scoped.row.gradeScoringRate"
  437 + :class="Number(scoped.row.gradeScoringRate * 100) < lowLevel ? 'lowLevelClass' : ''">
  438 + {{ Number(scoped.row.gradeScoringRate * 100).toFixed(2) }} %
  439 + </div>
  440 + </template>
  441 + </el-table-column>
163 442 <el-table-column prop="correctAnswer" label="答案" width="120" />
164   - <el-table-column v-for="(item, index) in testPaperExamReportOptions" :key="index" :label="item.title"
  443 + <el-table-column v-for="( item, index ) in testPaperExamReportOptions " :key="index" :label="item.title"
165 444 :prop="'count' + index" width="120">
166 445 <template slot-scope="scope">
167 446 <p class="persent">
168 447 {{
169   - scope.row.questionType == "5"
  448 + scope.row["option" + index] == "?" ? "未答" : scope.row.questionType == "5"
170 449 ? ""
171 450 : scope.row["option" + index]
172   - ? `${scope.row["option" + index]}(${scope.row["persent" + index] ?? "0"
  451 + ? `${scope.row["option" + index]} (${scope.row["persent" + index] ?? "0"
173 452 })`
174 453 : ""
175 454 }}
... ... @@ -180,40 +459,139 @@
180 459 </el-tab-pane>
181 460 <el-tab-pane :name="'学生成绩排行'" :label="`学生成绩排行`" style="padding: 0 20px">
182 461 <div style="float: right;margin-bottom: 20px;">
183   - <el-button type="primary" class="opration-btn" icon="el-icon-upload2">导出报表</el-button>
184   - <el-button type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
  462 + <el-button @click="_import" type="primary" class="opration-btn" icon="el-icon-upload2">导出报表</el-button>
  463 + <el-button @click="_print" type="primary" class="opration-btn" icon="el-icon-printer">打印报表</el-button>
185 464 </div>
186 465 <el-table class="default-table" style="margin-top: 10px" :data="testStudentExamReport">
187   - <el-table-column prop="gradeRank" label="年级排" />
  466 + <el-table-column prop="gradeRank" label="年级排" />
188 467 <el-table-column prop="code" label="学号" />
189 468 <el-table-column prop="name" label="姓名" />
190 469 <el-table-column prop="className" label="班级" />
191 470 <el-table-column prop="exam" label="分数" />
192   - <el-table-column prop="title" label="成绩等级" />
  471 + <el-table-column prop="lever" label="成绩等级" />
193 472 </el-table>
194 473 </el-tab-pane>
  474 +
195 475 </el-tabs>
196 476 </div>
197 477 </el-main>
  478 + <el-dialog :append-to-body="true" :close-on-click-modal="false" title="学生等级设置" :visible.sync="studentLevelDialog"
  479 + width="900px" @closed="_studentLevelClose">
  480 + <el-container class="default-body" style="background: transparent !important;">
  481 + <el-main>
  482 + <div class="default-main">
  483 + <el-form class="use-form">
  484 + <el-form-item class="use-form-item-box">
  485 + <el-form-item label="等级设置模式" class="use-form-item">
  486 + <el-select size="small" v-model="fromData.levelType">
  487 + <el-option label="按分数比例" :value="0"></el-option>
  488 + <el-option label="按已考人数比例" :value="1"></el-option>
  489 + </el-select>
  490 + </el-form-item>
  491 + </el-form-item>
  492 + <el-form-item>
  493 + <div class="dia-tab-box">
  494 + <p class="dia-tab-tit">
  495 + <span class="item1 boxitem">序号</span>
  496 + <span class="item2 boxitem"><i>*</i>等级名称</span>
  497 + <span class="item3 boxitem"><i>*</i>等级最高</span>
  498 + <span class="item3 boxitem"><i>*</i>等级最低</span>
  499 + <span class="item boxitem">操作</span>
  500 + </p>
  501 + <div class="dia-tab-item" v-for="(item, index) in fromData.levels" :key="index">
  502 + <span class="item1 boxitem">{{ index + 1 }}</span>
  503 + <p class="item2 boxitem">
  504 + <el-input class="score-ipt" v-model="item[0]" :maxlength="12"
  505 + @keydown.native="keydownRange($event)"></el-input>
  506 + </p>
  507 + <p class="item3 boxitem">
  508 + <el-input class="score-ipt" type="number" v-model="item[1]" :min="item[2]"
  509 + :max="index == 0 ? 100 : fromData.levels[index - 1][2]"
  510 + @keydown.native="keydownRange($event)"></el-input>
  511 + <span class="descption">
  512 + %
  513 + <template v-if="fromData.levelType == 0">
  514 + (
  515 + {{ index != 0 ? "不含" : "" }}
  516 + {{ Number(((item[1] / 100) * examPaperScore).toFixed(1)) }}分
  517 + )
  518 + </template>
  519 + <template v-else>{{ index != 0 ? "不含" : "" }}</template>
  520 + </span>
  521 + </p>
  522 + <p class="item3 boxitem">
  523 + <el-input class="score-ipt" type="number" v-model="item[2]" :min="0" :max="item[1]"
  524 + @keydown.native="keydownRange($event)"></el-input>
  525 + <span class="descption">
  526 + %
  527 + <template v-if="fromData.levelType == 0">
  528 + ({{ Number(((item[2] / 100) * examPaperScore).toFixed(1)) }}分)
  529 + </template>
  530 + </span>
  531 + </p>
  532 + <p class="item boxitem">
  533 + <el-link type="danger" :underline="false" @click="fromData.levels.splice(index, 1)">删除</el-link>
  534 + </p>
  535 + </div>
  536 + <div class="add">
  537 + <p @click="fromData.levels.push(['', '', ''])">
  538 + <el-button size="mini" icon="el-icon-plus" circle type="primary"></el-button>添加一行
  539 + </p>
  540 + </div>
  541 + </div>
  542 + </el-form-item>
  543 + </el-form>
  544 + </div>
  545 + </el-main>
  546 + </el-container>
  547 + <div class="dialog-footer" slot="footer" align="right">
  548 + <el-button type="info" :size="'small'" @click="studentLevelDialog = false">取 消</el-button>
  549 + <el-button type="primary" class="green-el-button" :size="'small'" @click="_savefrom">保存</el-button>
  550 + </div>
  551 + </el-dialog>
198 552 </el-container>
199 553 </template>
200 554  
201 555 <script>
  556 +import { formatDate, downloadFile, tablePrint } from "utils";
202 557 export default {
203 558 data() {
204 559 return {
  560 + studentLevelDialog: false,
205 561 checkAll: true,
206 562 isIndeterminate: true,
207 563 title: "",
  564 + defaultLevels: [],
208 565 paperId: null,
  566 + lowLevel: 20,
  567 + anyLowLevel: 20,
209 568 classInfos: [],
  569 + examIds: [],
  570 + testTranscriptDatas: [],
  571 + testTranscript: {
  572 + titleInfo: [],
  573 + studentList: [],
  574 + studentHeader: [],
  575 + question4List: [],
  576 + question7List: [],
  577 + question10List: [],
  578 + questionTotal: [],
  579 + },
  580 + currentPage: 0,
  581 + totalPage: 0,
210 582 checkedClassInfos: [],
211 583 queryLoading: false,
212 584 tabType: "0",
213   - testTranscriptCount: 0,
214   - titleInfo: [],
215   - studentList: [],
216   - studentHeader: [],
  585 + examPaperScore: 100, //卷面最高分
  586 + fromData: {
  587 + levelType: 0,
  588 + levels: [
  589 + ["优秀", 100, 90],
  590 + ["良好", 89.9, 70],
  591 + ["合格", 69.9, 60],
  592 + ["不合格", 59.9, 0],
  593 + ],
  594 + },
217 595 studentMapping: [
218 596 {
219 597 key: "code",
... ... @@ -240,11 +618,6 @@ export default {
240 618 label: "主观分",
241 619 },
242 620 ],
243   - questionList: [],
244   - questionHeaders: [],
245   - questionOtherList: [],
246   - questionOtherHeaders: [],
247   - questionTotal: [],
248 621 testPaperExamReport: [],
249 622 testPaperExamReportOptions: [],
250 623 testStudentExamReport: [],
... ... @@ -252,12 +625,40 @@ export default {
252 625 };
253 626 },
254 627 watch: {
255   - async tabType(value) {
256   - console.log(value);
257   - this.checkedClassInfos = this.classInfos;
258   - switch (value) {
  628 + async tabType() {
  629 + await this._anys();
  630 + },
  631 + async checkedClassInfos(value) {
  632 + if (value?.length >= 1) {
  633 + this.currentPage = 1;
  634 + this.totalPage = value.length;
  635 + } else {
  636 + this.currentPage = 0;
  637 + this.totalPage = 0;
  638 + }
  639 + this.tabType = '成绩测验单';
  640 + this.checkAll = value.length >= this.classInfos.length;
  641 + await this._anys();
  642 + },
  643 + async currentPage(value) {
  644 + await this._testExamReport(value - 1);
  645 + }
  646 + },
  647 + async created() {
  648 + this.title = this.$route.query.title || "";
  649 + this.paperId = this.$route.query.paperId;
  650 + this.classInfos = JSON.parse(this.$route.query.classListStr);
  651 + this.examIds = this.$route.query.examIds.split(',') || [];
  652 + this.checkedClassInfos = this.classInfos?.map(item => item.classId);
  653 + this.tabType = "成绩测验单";
  654 + await this._queryDefaultLevels();
  655 + },
  656 + methods: {
  657 + async _anys() {
  658 + this.queryLoading = true;
  659 + switch (this.tabType) {
259 660 case "成绩测验单":
260   - await this._testExamReport();
  661 + await this._testExamReport(0);
261 662 break;
262 663 case "班级对比情况":
263 664 await this._classdiffExamReport();
... ... @@ -269,28 +670,200 @@ export default {
269 670 await this._testStudentExamReport();
270 671 break;
271 672 }
  673 + this.queryLoading = false;
272 674 },
273   - },
274   - async created() {
275   - this.title = this.$route.query.title || "";
  675 + async _queryDefaultLevels() {
276 676  
277   - this.paperId = this.$route.query.paperId;
  677 + const { data, info, status } = await this.$request.gdefaultLevels();
278 678  
279   - this.classInfos = JSON.parse(this.$route.query.classListStr);
  679 + if (status != 0) {
  680 + this.$message.error(info);
  681 + return;
  682 + }
280 683  
281   - this.checkedClassInfos = this.classInfos;
  684 + this.defaultLevels = { ...data } || {
  685 + levelType: 0,
  686 + levels: [
  687 + ["优秀", 100, 90],
  688 + ["良好", 89.9, 70],
  689 + ["合格", 69.9, 60],
  690 + ["不合格", 59.9, 0],
  691 + ],
  692 + };
282 693  
283   - this.tabType = "成绩测验单";
284   - },
285   - methods: {
  694 + this.defaultLevels.type = 0
  695 +
  696 + this.fromData.levelType = this.defaultLevels.levelType;
  697 +
  698 + this.fromData.levels = [...this.defaultLevels.levels];
  699 +
  700 + sessionStorage.setItem(
  701 + "levelFromData",
  702 + JSON.stringify(this.defaultLevels)
  703 + );
  704 + },
  705 + async _savefrom() {
  706 + for (let i = 0; i < this.fromData.levels.length; i++) {
  707 + if (this.fromData.levels[i].includes("")) {
  708 + this.$message.warning("请补全编号" + (i + 1) + "设置信息!");
  709 + return;
  710 + }
  711 + }
  712 + if (this.fromData.levels.length == 0) {
  713 + this.$message.warning("请添加等级设置!");
  714 + return;
  715 + }
  716 + let nums = [];
  717 + let ERR_OK = false;
  718 + this.fromData.levels.map((item) => {
  719 + nums.push(Number(item[1]));
  720 + nums.push(Number(item[2]));
  721 + });
  722 + for (let i = 0; i < nums.length; i++) {
  723 + if (nums[i + 1] && nums[i + 1] > nums[i]) {
  724 + ERR_OK = true;
  725 + this.$message.warning("高等级比例不能低于低等级比例!请检查");
  726 + break;
  727 + }
  728 + }
  729 + if (ERR_OK) return;
  730 + this.tableData = [];
  731 + this.tableData2 = [];
  732 + this.defaultLevels.type = this.fromData.type;
  733 + this.defaultLevels.levelType = this.fromData.levelType;
  734 + this.defaultLevels.levels = [...this.fromData.levels];
  735 + sessionStorage.setItem("levelFromData", JSON.stringify(this.fromData));
  736 + this.studentLevelDialog = false;
  737 + await this._anys();
  738 + // await this._classdiffExamReport();
  739 + },
  740 + _studentLevelSet() {
  741 + this.studentLevelDialog = true;
  742 + },
  743 + _studentLevelClose() {
  744 + let levelFromData = sessionStorage.getItem("levelFromData");
  745 + if (levelFromData) {
  746 + levelFromData = JSON.parse(levelFromData);
  747 + this.fromData.type = levelFromData.type;
  748 + this.fromData.levelType = levelFromData.levelType;
  749 + this.fromData.levels = [...levelFromData.levels];
  750 + } else {
  751 + this.fromData.type = 0;
  752 + this.fromData.levelType = this.defaultLevels.levelType;
  753 + this.fromData.levels = [...this.defaultLevels.levels];
  754 + }
  755 + },
  756 + arraySpanMethod({ row, column, rowIndex, columnIndex }) {
  757 + if (rowIndex == this.testPaperExamReport?.length - 3) {
  758 + if (columnIndex == 0) {
  759 + return [3, 1];
  760 + }
  761 + else if (columnIndex == 6) {
  762 + return [3, 1];
  763 + }
  764 + else if (columnIndex == 7) {
  765 + return [3, 5];
  766 + }
  767 + else {
  768 + return [1, 1]
  769 + }
  770 + }
  771 + else {
  772 + return [1, 1]
  773 + }
  774 +
  775 + },
  776 + keydownRange(event) {
  777 + if (event.key == "-" || event.key == "e") {
  778 + event.returnValue = "";
  779 + }
  780 + },
  781 + _changePage(status) {
  782 + if (status == "next") {
  783 + if (this.currentPage < this.checkedClassInfos.length) {
  784 + this.currentPage += 1;
  785 + }
  786 + }
  787 + else if (status == "prev") {
  788 + if (this.currentPage > 1) {
  789 + this.currentPage -= 1;
  790 + }
  791 + }
  792 + else {
  793 + this.$message.error('异常操作');
  794 + }
  795 + },
286 796 _handleCheckAllChange(val) {
287   - // this.checkedClassInfos = val ? this.classInfos : [];
288   - // this.isIndeterminate = false;
  797 + this.checkAll = val;
  798 + if (val) this.checkedClassInfos = this.classInfos.map(item => item.classId);
  799 + else this.checkedClassInfos = [];
289 800 },
290 801 _handleCheckedClassChange(value) {
291   - // let checkedCount = value.length;
292   - // this.checkAll = checkedCount === this.cities.length;
293   - // this.isIndeterminate = checkedCount > 0 && checkedCount < this.cities.length;
  802 +
  803 + },
  804 + async _print() {
  805 + if (this.tabType == '成绩测验单') {
  806 + if (this.checkedClassInfos.length <= 0) {
  807 + this.$message.error('请选中班级');
  808 + return;
  809 + }
  810 +
  811 + this.testTranscriptDatas = [];
  812 + for (var page = 0; page < this.checkedClassInfos.length; page++) {
  813 + this.testTranscriptDatas.push(await this._testExamReport(page));
  814 + }
  815 + setTimeout(() => {
  816 + tablePrint("test-print", this.tabType);
  817 + }, 500);
  818 + }
  819 + else {
  820 + tablePrint("print-content", this.tabType);
  821 + }
  822 + },
  823 + async _import() {
  824 + let importRequest;
  825 + switch (this.tabType) {
  826 + case "成绩测验单": {
  827 + importRequest = this.$request.tgexportPhaseExamReport;
  828 + } break;
  829 + case "班级对比情况": {
  830 + importRequest = this.$request.tgexportPhaseExamReport2;
  831 + } break;
  832 + case "试题分析表": {
  833 + importRequest = this.$request.tgexportPhaseExamReport3;
  834 + } break;
  835 + case "学生成绩排行": {
  836 + importRequest = this.$request.tgexportPhaseExamReport4;
  837 + } break;
  838 + }
  839 +
  840 + let paramObj = JSON.parse(JSON.stringify(this.fromData))
  841 +
  842 + if (paramObj.levelType == 0) {
  843 + paramObj.levels = paramObj.levels.map((item) => {
  844 + item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);
  845 + item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);
  846 + return item;
  847 + });
  848 + }
  849 + var data = await importRequest({
  850 + paperId: this.paperId,
  851 + classIds: this.checkedClassInfos ?? [],
  852 + examIds: this.classInfos.
  853 + filter(item =>
  854 + this.checkedClassInfos.includes(item.classId)).map(ida => ida.examId),
  855 + reportRange: paramObj
  856 + })
  857 +
  858 + if (data) {
  859 + let blob = new Blob([data], {
  860 + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  861 + });
  862 +
  863 + downloadFile(this.tabType + ".xlsx", blob);
  864 + } else {
  865 + this.$message.error("下载失败");
  866 + }
294 867 },
295 868 _detailQ(id) { },
296 869 setSubPro(type) {
... ... @@ -309,19 +882,33 @@ export default {
309 882 tit = "主观题";
310 883 break;
311 884 default:
312   - tit = "其他";
  885 + tit = type;
313 886 }
314 887 return tit;
315 888 },
316   - async _testExamReport() {
  889 + async _testExamReport(page, type) {
  890 + let demoTestTranscript = {
  891 + titleInfo: [],
  892 + studentList: [],
  893 + studentHeader: [],
  894 + question4List: [],
  895 + question7List: [],
  896 + question10List: [],
  897 + questionTotal: [],
  898 + };
  899 +
  900 + if (type != 1) {
  901 + this.testTranscript = demoTestTranscript;
  902 + }
317 903  
318   - this.questionTotal = [];
  904 +
  905 + if (!this.checkedClassInfos || this.checkedClassInfos?.length <= 0) return;
319 906  
320 907 const request = this.$request.gTestExamReport;
321 908  
322 909 let response = await request({
323 910 paperId: this.paperId,
324   - classIds: this.checkedClassInfos.map((item) => item.classId),
  911 + classIds: [this.checkedClassInfos[page]],
325 912 });
326 913  
327 914 if (response.status != 0) {
... ... @@ -329,8 +916,8 @@ export default {
329 916 return;
330 917 }
331 918  
332   - this.titleInfo = response.data.titleInfos;
333   - console.log(this.titleInfo)
  919 + demoTestTranscript.titleInfo = response.data.titleInfos;
  920 +
334 921 var studentHeaders = [];
335 922  
336 923 var studentResults = [];
... ... @@ -349,7 +936,7 @@ export default {
349 936 }
350 937 }
351 938  
352   - this.studentHeader = [...studentHeaders];
  939 + demoTestTranscript.studentHeader = [...studentHeaders];
353 940  
354 941 for (var isp = 0; isp < response.data.gradeExamStudentReports.length; isp++) {
355 942  
... ... @@ -379,230 +966,321 @@ export default {
379 966 studentResults.push(item);
380 967 }
381 968  
382   - this.studentList = [...studentResults];
  969 + demoTestTranscript.studentList = [...studentResults];
383 970  
384   - var otherDatas = [];
  971 + var show4Area = true; //显示4选项区域
385 972  
386   - var questionHeaders = [];
  973 + var show7Area = true; //显示7选项区域
387 974  
388   - var questionResults = [];
  975 + var show10Area = true; //显示10选项区域
389 976  
390   - var questionOtherHeaders = [];
  977 + var optionNumList = [];
391 978  
392   - var questionOtherResults = [];
  979 + var maxOptions = 4;
393 980  
394   - var defaultQuestion = 6;
  981 + var minOptions = 10; //最多10个选项
395 982  
396   - var defaultCount = 3;
  983 + var questionList = response.data.questionInfos;
397 984  
398   - var defaultQuestionCount = 4;
  985 + questionList = questionList.sort((prev, next) => { return prev.questionIndex - next.questionIndex });
399 986  
400   - var maxQuestionCount = 4;
  987 + for (var i = 0; i < questionList.length; i++) {
401 988  
402   - var optionSt = 1;
  989 + var correctAnswerValue = questionList[i].correctAnswer == "1" ? "✓" : questionList[i].correctAnswer == 2 ? "✗" : questionList[i].correctAnswer;
403 990  
404   - for (var qheader = 0; qheader < defaultQuestion * defaultCount; qheader++) {
405   - if (qheader == 0 || qheader % 6 == 0) {
406   - questionHeaders.push({
407   - prop: "column_" + qheader,
408   - label: "题号&答案",
409   - });
410   - continue;
411   - } else if (qheader == 1 || (qheader - 1) % 6 == 0) {
412   - questionHeaders.push({
413   - prop: "column_" + qheader,
414   - label: "得分率",
415   - });
416   - optionSt = 1;
417   - continue;
418   - } else {
419   - questionHeaders.push({
420   - prop: "column_" + qheader,
421   - label: "选项" + optionSt,
422   - });
423   - optionSt += 1;
  991 + var missCount = 0;
  992 +
  993 + var missI = questionList[i].details.filter(item => !item.right);
  994 +
  995 + missI.forEach(itemsa => {
  996 + missCount = Number(missCount) + Number(itemsa.students?.length ?? 0)
  997 + });
  998 +
  999 + demoTestTranscript.questionTotal.push({
  1000 + quesion: "Q" + (questionList[i].questionIndex),
  1001 + anwser: correctAnswerValue ?? "-----",
  1002 + details: questionList[i].details,
  1003 + missPeopleNumber: missCount
  1004 + })
  1005 + if ((questionList[i].questionType == 2)) {
  1006 + //单选题可能有超过4个选项,多选题是固定的
  1007 + if (questionList[i].details?.length > maxOptions) {
  1008 + maxOptions = questionList[i].details.filter(iam => { return iam.option.indexOf('未答') < 0 })?.length;
  1009 + }
  1010 + //单选题可能有超过4个选项,多选题是固定的
  1011 + if (questionList[i].details?.length < minOptions) {
  1012 + minOptions = questionList[i].details.filter(iam => { return iam.option.indexOf('未答') < 0 })?.length;
  1013 + }
  1014 +
  1015 + optionNumList.push(questionList[i].details.filter(iam => { return iam.option.indexOf('未答') < 0 })?.length);
  1016 + }
  1017 +
  1018 + if (questionList[i].questionType == 4) {
  1019 + minOptions = 2;
  1020 + optionNumList.push(2);
424 1021 }
425 1022 }
426 1023  
427   - var noPassIndex = 0;
  1024 + console.log(demoTestTranscript.questionTotal)
428 1025  
429   - this.questionHeaders = questionHeaders;
  1026 + show4Area = minOptions <= 4;
430 1027  
431   - var itema = null;
  1028 + show7Area = optionNumList.filter(o => o > 4 && o <= 7);
432 1029  
433   - response.data.questionInfos = [...response.data.questionInfos]
  1030 + show10Area = optionNumList.filter(o => o > 7);
434 1031  
435   - for (var qIndex = 0; qIndex < response.data.questionInfos.length; qIndex++) {
436 1032  
437   - var currentData = response.data.questionInfos[qIndex];
  1033 + var currentRow = {};
438 1034  
439   - var filterDetail = currentData.details.filter(fl => fl.option != '未答');
  1035 + if (show4Area) {
440 1036  
441   - var correctAnswerValue = currentData.correctAnswer == "1" ? "✓" : currentData.correctAnswer == 2 ? "✗" : currentData.correctAnswer;
  1037 + var areaList = [];
442 1038  
443   - this.questionTotal.push({
444   - quesion: "Q" + (qIndex + 1),
445   - anwser: correctAnswerValue ?? "-----",
446   - details: currentData.details
447   - })
  1039 + var quesRow = Math.ceil(questionList?.length * 1.00 / 3);
448 1040  
449   - if (filterDetail.length > defaultQuestionCount || filterDetail.length > maxQuestionCount) {
450   - currentData.index = qIndex;
451   - otherDatas.push(currentData);
452   - if (filterDetail.length > maxQuestionCount) {
453   - maxQuestionCount = filterDetail.length;
454   - }
455   - continue;
  1041 + for (var irow = 0; irow < quesRow; irow++) {
  1042 + areaList.push({});
456 1043 }
457   - else {
458   - if (noPassIndex > defaultCount) {
459   - questionResults.push(itema)
460   - itema = null;
461   - noPassIndex = 0;
462   - }
463   - var stPass = noPassIndex * defaultQuestion;
464   - if (!itema) itema = {}
465 1044  
466   - var correctAnswerValue = currentData.correctAnswer == "1" ? "✓" : currentData.correctAnswer == 2 ? "✗" : currentData.correctAnswer;
  1045 + for (var i = 0; i < questionList?.length; i++) {
467 1046  
468   - itema["column_" + (stPass)] = (qIndex + 1) + "" + correctAnswerValue;
469   - itema["column_" + (stPass + 1)] = (currentData.gradeScoringRate * 100) + "%";
  1047 + var col = parseInt(i / quesRow);
470 1048  
471   - var value = "------";
  1049 + var row = parseInt(i % quesRow);
472 1050  
473   - for (var iOption = 0; iOption < defaultQuestion - 2; iOption++) {
474   - var currentOption = filterDetail[iOption];
475   - if (currentOption) {
476   - var optionValue = currentOption.option == "1" ? "✓" : currentOption.option == 2 ? "✗" : currentOption.option;
  1051 + var question = questionList[i];
477 1052  
478   - itema["column_" + (stPass + iOption + 2)] = optionValue + "(" + (currentOption.persent ?? "0%") + ")";
  1053 + var currentRow = areaList[row];
  1054 +
  1055 + var correctAnswerValue = question.correctAnswer == "1" ? "✓" : question.correctAnswer == 2 ? "✗" : question.correctAnswer;
  1056 +
  1057 + var details = question.details.filter(fl => {
  1058 + return fl.option.indexOf('未答') < 0;
  1059 + });
  1060 +
  1061 +
  1062 + for (var ilr = 0; ilr < 6; ilr++) {
  1063 +
  1064 + if (ilr == 0) {
  1065 + currentRow['column' + Number(6 * col + ilr)] = question.questionIndex + correctAnswerValue;
  1066 + }
  1067 + else if (ilr == 1) {
  1068 + currentRow['column' + Number(6 * col + ilr)] = (question.gradeScoringRate * 100).toFixed(2) + '%';
479 1069 }
480 1070 else {
481   - itema["column_" + (stPass + iOption + 2)] = value
  1071 +
  1072 + var questionDetail = details[ilr - 2];
  1073 +
  1074 + var questionColumn = 'column' + Number(6 * col + ilr);
  1075 +
  1076 + if (details.length <= 4) {
  1077 +
  1078 + var questionOption = questionDetail ? (questionDetail.option == "1" ? "✓" : questionDetail.option == "2" ? "✗" : questionDetail.option) : "- -"
  1079 +
  1080 + if (questionOption != "- -") questionOption += "(" + questionDetail.persent + ")";
  1081 +
  1082 + currentRow[questionColumn] = questionOption;
  1083 + }
  1084 + else {
  1085 + currentRow[questionColumn] = "--";
  1086 + }
482 1087 }
483 1088 }
484   -
485   - noPassIndex += 1
486 1089 }
487 1090  
488   - if (qIndex >= response.data.questionInfos.length - 1 && noPassIndex != 0) {
489   - questionResults.push(itema)
490   - itema = null;
491   - }
  1091 + demoTestTranscript.question4List = [...areaList]
  1092 +
492 1093 }
493 1094  
494   - optionSt = 1;
495 1095  
496   - maxQuestionCount += 2;
  1096 + if (show7Area && show7Area.length > -1) {
497 1097  
498   - this.questionList = [...questionResults]
  1098 + var areaList = [];
499 1099  
500   - var otherCount = parseInt(defaultQuestion * defaultCount / maxQuestionCount);
  1100 + var quesRow = Math.ceil(show7Area.length * 1.00 / 2);
501 1101  
502   - itema = null;
  1102 + var num = 0;
503 1103  
504   - for (var qOHeader = 0; qOHeader < maxQuestionCount * otherCount; qOHeader++) {
505   - if (qOHeader == 0 || qOHeader % (maxQuestionCount) == 0) {
506   - questionOtherHeaders.push({
507   - prop: "column_" + qOHeader,
508   - label: "题号&答案",
509   - });
510   - continue;
511   - } else if (qOHeader == 1 || (qOHeader - 1) % (maxQuestionCount) == 0) {
512   - questionOtherHeaders.push({
513   - prop: "column_" + qOHeader,
514   - label: "得分率",
515   - });
516   - optionSt = 1;
517   - continue;
518   - } else {
519   - questionOtherHeaders.push({
520   - prop: "column_" + qOHeader,
521   - label: "选项" + optionSt,
  1104 + for (var irow = 0; irow < quesRow; irow++) {
  1105 + areaList.push({});
  1106 + }
  1107 +
  1108 + for (var i = 0; i < questionList?.length; i++) {
  1109 +
  1110 + var question = questionList[i];
  1111 +
  1112 + var details = question.details.filter(fl => {
  1113 + return fl.option.indexOf('未答') < 0;
522 1114 });
523   - optionSt += 1;
  1115 +
  1116 + if (question.questionType == 2 && details.length > 4 && details.length <= 7) {
  1117 +
  1118 + var col = parseInt(num / quesRow);
  1119 +
  1120 + var row = parseInt(num % quesRow);
  1121 +
  1122 + var currentRow = areaList[row];
  1123 +
  1124 + var correctAnswerValue = question.correctAnswer == "1" ? "✓" : question.correctAnswer == 2 ? "✗" : question.correctAnswer;
  1125 +
  1126 + for (var ilr = 0; ilr < 9; ilr++) {
  1127 +
  1128 + if (ilr == 0) {
  1129 + currentRow['column' + Number(9 * col + ilr)] = question.questionIndex + correctAnswerValue;
  1130 + }
  1131 + else if (ilr == 1) {
  1132 + currentRow['column' + Number(9 * col + ilr)] = (question.gradeScoringRate * 100).toFixed(2) + '%';
  1133 + }
  1134 + else {
  1135 +
  1136 + var questionDetail = details[ilr - 2];
  1137 +
  1138 + var questionColumn = 'column' + Number(9 * col + ilr);
  1139 +
  1140 + currentRow[questionColumn] = questionDetail ? questionDetail.option + "(" + questionDetail.persent + ")" : "- -";
  1141 + }
  1142 + }
  1143 +
  1144 + num = num + 1;
  1145 + }
  1146 +
524 1147 }
  1148 +
  1149 + demoTestTranscript.question7List = [...areaList]
525 1150 }
526 1151  
527   - this.questionOtherHeaders = questionOtherHeaders;
528 1152  
529   - noPassIndex = 0;
  1153 + if (show10Area && show10Area.length > -1) {
530 1154  
531   - for (var qOIndex = 0; qOIndex < otherDatas.length; qOIndex++) {
  1155 + var areaList = [];
532 1156  
533   - var currentData = otherDatas[qOIndex];
  1157 + var quesRow = show10Area.length;
534 1158  
535   - var filterDetail = currentData.details.filter(fl => fl.option != '未答');
  1159 + var num = 0;
536 1160  
537   - if (noPassIndex >= otherCount) {
538   - questionOtherResults.push(itema)
539   - itema = null;
540   - noPassIndex = 0;
  1161 + for (var irow = 0; irow < quesRow; irow++) {
  1162 + areaList.push({});
541 1163 }
542 1164  
543   - var stPass = noPassIndex * maxQuestionCount;
  1165 + for (var i = 0; i < questionList?.length; i++) {
544 1166  
545   - if (!itema) itema = {}
  1167 + var question = questionList[i];
546 1168  
547   - var correctAnswerValue = currentData.correctAnswer == "1" ? "✓" : currentData.correctAnswer == 2 ? "✗" : currentData.correctAnswer;
  1169 + var details = question.details.filter(fl => {
  1170 + return fl.option.indexOf('未答') < 0;
  1171 + });
548 1172  
549   - itema["column_" + (stPass)] = (Number(currentData.index) + 1) + "" + correctAnswerValue;
  1173 + if (question.questionType == 2 && details.length > 7) {
  1174 + var col = parseInt(num / quesRow);
550 1175  
551   - itema["column_" + (stPass + 1)] = (currentData.gradeScoringRate * 100) + "%";
  1176 + var row = num;
552 1177  
553   - var value = "------";
  1178 + var currentRow = areaList[row];
554 1179  
555   - for (var iOption = 0; iOption < maxQuestionCount - 2; iOption++) {
  1180 + var correctAnswerValue = question.correctAnswer == "1" ? "✓" : question.correctAnswer == 2 ? "✗" : question.correctAnswer;
556 1181  
557   - var currentOption = filterDetail[iOption];
  1182 + for (var ilr = 0; ilr < 12; ilr++) {
558 1183  
559   - if (currentOption) {
  1184 + if (ilr == 0) {
  1185 + currentRow['column' + Number(12 * col + ilr)] = question.questionIndex + correctAnswerValue;
  1186 + }
  1187 + else if (ilr == 1) {
  1188 + currentRow['column' + Number(12 * col + ilr)] = (question.gradeScoringRate * 100).toFixed(2) + '%';
  1189 + }
  1190 + else {
560 1191  
561   - var optionValue = currentOption.option == "1" ? "✓" : currentOption.option == 2 ? "✗" : currentOption.option;
  1192 + var questionDetail = details[ilr - 2];
562 1193  
563   - itema["column_" + (stPass + iOption + 2)] = optionValue + "(" + (currentOption.persent ?? "0%") + ")";
564   - }
565   - else {
566   - itema["column_" + (stPass + iOption + 2)] = value
567   - }
568   - }
  1194 + var questionColumn = 'column' + Number(12 * col + ilr);
569 1195  
570   - noPassIndex += 1
  1196 + currentRow[questionColumn] = questionDetail ? questionDetail.option + "(" + questionDetail.persent + ")" : "- -";
  1197 + }
  1198 + }
571 1199  
572   - if (qOIndex >= otherDatas.length - 1 && noPassIndex != 0) {
  1200 + num = num + 1;
  1201 + }
573 1202  
574   - questionOtherResults.push(itema)
575   - itema = null;
576 1203 }
  1204 +
  1205 + demoTestTranscript.question10List = [...areaList]
577 1206 }
578 1207  
579   - this.questionOtherList = [...questionOtherResults]
  1208 +
  1209 + return demoTestTranscript;
580 1210  
581 1211 },
582 1212 async _testPaperExamReport() {
  1213 +
  1214 + this.testPaperExamReport = [];
  1215 +
  1216 + this.testPaperExamReportOptions = [];
  1217 +
  1218 + if (!this.checkedClassInfos || this.checkedClassInfos?.length <= 0) return;
  1219 +
583 1220 const request = this.$request.gPaperExamReport;
584 1221  
585 1222 let response = await request({
586 1223 paperId: this.paperId,
587   - classIds: this.checkedClassInfos.map((item) => item.classId),
  1224 + classIds: this.checkedClassInfos,
588 1225 });
589 1226  
590 1227 if (response.status != 0) {
591 1228 this.$message.error(response.info);
592 1229 return;
593 1230 }
  1231 + var maxOption = 0;
  1232 + response.data.forEach((item) => {
  1233 + if (item.details) {
  1234 + if (maxOption < item.details.length) {
  1235 + maxOption = item.details.length;
  1236 + }
  1237 + }
  1238 +
  1239 + })
594 1240  
595   - let optionsList = [{}, {}, {}, {}, {}];
  1241 + let optionsList = [];
  1242 +
  1243 + for (var io = 0; io < maxOption; io++) {
  1244 + optionsList.push({})
  1245 + }
  1246 + //主观
  1247 + var subjective = {
  1248 + sum: 0.0,
  1249 + avg: 0.0,
  1250 + rate: 0.0,
  1251 + number: 0
  1252 + };
  1253 +
  1254 + //客观
  1255 + var objective = {
  1256 + sum: 0.0,
  1257 + avg: 0.0,
  1258 + rate: 0.0,
  1259 + number: 0
  1260 + };
  1261 +
  1262 + //汇总
  1263 + var summary = {
  1264 + sum: 0.0,
  1265 + avg: 0.0,
  1266 + rate: 0.0,
  1267 + number: 0
  1268 + };
596 1269  
597 1270 let tableData = response.data?.map((item) => {
  1271 +
598 1272 let params = {};
  1273 +
599 1274 const detail = item.details;
  1275 +
600 1276 let lastOPtion = detail?.find((item) => {
601 1277 return item.option == "未答";
602 1278 });
  1279 +
603 1280 let defaultArr = detail?.filter((item) => {
604 1281 return item.option != "未答";
605 1282 });
  1283 +
606 1284 optionsList.map((items, index) => {
607 1285 if (index != 4) {
608 1286 params["count" + index] =
... ... @@ -624,12 +1302,28 @@ export default {
624 1302 items["title"] = "选项" + (index + 1);
625 1303 } else {
626 1304 items["title"] = "未答";
627   - params["count" + index] = lastOPtion.count;
628   - params["persent" + index] = lastOPtion.persent;
  1305 + params["count" + index] = lastOPtion?.count ?? "";
  1306 + params["persent" + index] = lastOPtion?.persent ?? "";
629 1307 params["option" + index] = "?";
630 1308 }
631 1309 });
632 1310  
  1311 + summary.sum += parseFloat(item.score);
  1312 + summary.avg += parseFloat(item.avgScore);
  1313 + summary.rate += parseFloat(item.gradeScoringRate);
  1314 + summary.number += 1;
  1315 + if (item.questionType == 5) {
  1316 + subjective.sum += parseFloat(item.score);
  1317 + subjective.rate += parseFloat(item.gradeScoringRate);
  1318 + subjective.avg += parseFloat(item.avgScore);
  1319 + subjective.number += 1;
  1320 + }
  1321 + else {
  1322 + objective.sum += parseFloat(item.score);
  1323 + objective.rate += parseFloat(item.gradeScoringRate);
  1324 + objective.avg += parseFloat(item.avgScore);
  1325 + objective.number += 1;
  1326 + }
633 1327 return {
634 1328 ...item,
635 1329 ...params,
... ... @@ -637,18 +1331,57 @@ export default {
637 1331 });
638 1332  
639 1333 this.testPaperExamReport = tableData?.sort((a, b) => {
640   - return a.questionIndex - b.questionIndex;
  1334 + return Number(a.questionIndex) - Number(b.questionIndex);
641 1335 });
642 1336  
643 1337 this.testPaperExamReportOptions = [...optionsList];
644 1338  
  1339 + console.log(objective, subjective, summary, Number(objective.avg / objective.sum))
  1340 + this.testPaperExamReport.push({
  1341 + questionIndex: "汇总",
  1342 + questionType: "客观题",
  1343 + type: "colspan",
  1344 + score: objective.sum,
  1345 + avgScore: objective.avg == 0 ? 0 : Number(objective.avg).toFixed(2),
  1346 + gradeScoringRate: objective.avg == 0 ? 0 : Number(objective.avg * 100 / objective.sum).toFixed(2),
  1347 + correctAnswer: "备注"
  1348 + })
  1349 +
  1350 + this.testPaperExamReport.push({
  1351 + questionIndex: "主观题",
  1352 + type: "colspan",
  1353 + knowledge: subjective.sum,
  1354 + score: subjective.avg == 0 ? 0 : Number(subjective.avg).toFixed(2),
  1355 + avgScore: subjective.avg == 0 ? 0 : Number(subjective.avg * 100 / subjective.sum).toFixed(2)
  1356 + })
  1357 +
  1358 + this.testPaperExamReport.push({
  1359 + questionIndex: "合计",
  1360 + type: "colspan",
  1361 + knowledge: summary.sum,
  1362 + score: summary.avg == 0 ? 0 : Number(summary.avg).toFixed(2),
  1363 + avgScore: summary.avg == 0 ? 0 : Number(summary.avg * 100 / summary.sum).toFixed(2)
  1364 + })
645 1365 },
646 1366 async _testStudentExamReport() {
  1367 + this.testStudentExamReport = [];
  1368 + if (!this.checkedClassInfos || this.checkedClassInfos?.length <= 0) return;
  1369 +
647 1370 const request = this.$request.gStudentExamReport;
648 1371  
  1372 + let paramObj = JSON.parse(JSON.stringify(this.fromData))
  1373 + if (paramObj.levelType == 0) {
  1374 + paramObj.levels = paramObj.levels.map((item) => {
  1375 + item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);
  1376 + item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);
  1377 + return item;
  1378 + });
  1379 + }
  1380 +
649 1381 let response = await request({
650 1382 paperId: this.paperId,
651   - classIds: this.checkedClassInfos.map((item) => item.classId),
  1383 + classIds: this.checkedClassInfos,
  1384 + reportRange: paramObj
652 1385 });
653 1386  
654 1387 if (response.status != 0) {
... ... @@ -659,11 +1392,26 @@ export default {
659 1392 this.testStudentExamReport = response.data;
660 1393 },
661 1394 async _classdiffExamReport() {
  1395 +
  1396 + this.classdiffExamReport = [];
  1397 +
  1398 + if (!this.checkedClassInfos || this.checkedClassInfos?.length <= 0) return;
  1399 +
662 1400 const request = this.$request.gClassdiffExamReport;
663 1401  
  1402 + let paramObj = JSON.parse(JSON.stringify(this.fromData))
  1403 + if (paramObj.levelType == 0) {
  1404 + paramObj.levels = paramObj.levels.map((item) => {
  1405 + item[1] = ((item[1] / 100) * this.examPaperScore).toFixed(1);
  1406 + item[2] = ((item[2] / 100) * this.examPaperScore).toFixed(1);
  1407 + return item;
  1408 + });
  1409 + }
  1410 +
664 1411 let response = await request({
665 1412 paperId: this.paperId,
666   - classIds: this.checkedClassInfos.map((item) => item.classId),
  1413 + classIds: this.checkedClassInfos,
  1414 + reportRange: paramObj
667 1415 });
668 1416  
669 1417 if (response.status != 0) {
... ... @@ -675,6 +1423,7 @@ export default {
675 1423 this.classdiffExamReport = response.data.map((item) => {
676 1424 item.index = index + 1;
677 1425 index += 1;
  1426 +
678 1427 return item;
679 1428 });
680 1429 },
... ... @@ -694,7 +1443,11 @@ export default {
694 1443 padding: 10px !important;
695 1444 }
696 1445  
  1446 +
697 1447 .row-line {
  1448 + overflow: hidden; //超出宽度隐藏
  1449 + white-space: nowrap; //强制文字在一行
  1450 + text-overflow: ellipsis; //文字溢出显示省略号
698 1451 width: calc(33% - 2px);
699 1452 border: 1px solid #ebeef5;
700 1453 background: #f5f7fa;
... ... @@ -705,5 +1458,71 @@ export default {
705 1458 .line-subfix {
706 1459 margin-left: 10px;
707 1460 }
  1461 +
  1462 +}
  1463 +
  1464 +.dia-tab-box {
  1465 + font-size: 14px;
  1466 +
  1467 + .boxitem {
  1468 + border: 1px solid #DCDFE6;
  1469 + margin: 0px !important;
  1470 +
  1471 + * {
  1472 + border: none;
  1473 + }
  1474 + }
  1475 +
  1476 + .dia-tab-tit,
  1477 + .dia-tab-item {
  1478 +
  1479 +
  1480 + i {
  1481 + color: #f30;
  1482 + padding-right: 5px;
  1483 + }
  1484 +
  1485 + display: flex;
  1486 +
  1487 + .item {
  1488 + width: 80px;
  1489 + }
  1490 +
  1491 + .item1 {
  1492 + padding-left: 10px;
  1493 + width: 10%;
  1494 + }
  1495 +
  1496 + .item2 {
  1497 + width: 18%;
  1498 + }
  1499 +
  1500 + .item3 {
  1501 + padding-left: 12px;
  1502 + flex: 1;
  1503 + }
  1504 +
  1505 + .score-ipt {
  1506 + width: 100px;
  1507 + }
  1508 + }
  1509 +
  1510 + .dia-tab-tit {
  1511 + background: rgb(245, 247, 250) !important
  1512 + }
  1513 +
  1514 + .add {
  1515 + display: flex;
  1516 + justify-content: center;
  1517 + margin: 0 auto;
  1518 +
  1519 + p {
  1520 + cursor: pointer;
  1521 + }
  1522 +
  1523 + .el-button {
  1524 + margin-right: 6px;
  1525 + }
  1526 + }
708 1527 }
709 1528 </style>
... ...
src/views/basic/askTestQuestion/index.vue
... ... @@ -7,16 +7,16 @@
7 7 <el-dropdown v-if="this.dataType == '2'" :hide-on-click="true" style="float: right;margin-right: 50px;">
8 8 <el-button :size="'small'" :icon="'el-icon-plus'" class="green-el-button">添加试卷</el-button>
9 9 <el-dropdown-menu slot="dropdown">
10   - <el-dropdown-item @click.native="import(1)">导入试卷</el-dropdown-item>
  10 + <el-dropdown-item @click.native="importQuestion(1)">导入试卷</el-dropdown-item>
11 11 <el-dropdown-item @click.native="createAnwseredCard()">创建答题卡</el-dropdown-item>
12 12 </el-dropdown-menu>
13 13 </el-dropdown>
14 14 <el-button style="float: right;margin-right: 50px;" :size="'small'" :icon="'el-icon-plus'"
15   - class="green-el-button" @click.native="import(2)" v-if="this.dataType == '1'">添加课件</el-button>
  15 + class="green-el-button" @click.native="importQuestion(2)" v-if="this.dataType == '1'">添加课件</el-button>
16 16 </el-header>
17 17 <div class="default-filter">
18   - <el-input v-model="query.paper" :placeholder="dataType == '1' ? '搜索课件' : '搜索试卷'"
19   - suffix-icon="el-icon-search" class="filter-input" type="number" clearable />
  18 + <!-- <el-input v-model="query.paper" :placeholder="dataType == '1' ? '搜索课件' : '搜索试卷'"
  19 + suffix-icon="el-icon-search" class="filter-input" type="number" clearable /> -->
20 20 <el-select @change="_changeClass" v-model="query.class" class="filter-select" placeholder="选择班级">
21 21 <el-option v-for="item in classList" :key="item.classId" :label="item.className"
22 22 :value="item.classId" />
... ... @@ -34,7 +34,7 @@
34 34 筛选
35 35 </el-button>
36 36 <el-radio-group v-model="dateStatus" class="default-date-radio-group">
37   - <el-radio-button label="onDay">天</el-radio-button>
  37 + <el-radio-button label="onDay">天</el-radio-button>
38 38 <el-radio-button label="onWeek">本周</el-radio-button>
39 39 <el-radio-button label="onMonth">本月</el-radio-button>
40 40 </el-radio-group>
... ... @@ -42,192 +42,206 @@
42 42 <el-main>
43 43 <div style='position: relative;'>
44 44 <el-tabs v-model="tabType" v-loading="queryLoading" type="card" class="default-tabs">
45   - <el-tab-pane :name="'0'" :label="`自编课件(${createdCount})`">
46   - <el-row>
47   - <el-col :key="index" v-for="( item, index ) in defaultList " :span="12">
48   - <div class="card-content">
49   - <el-row>
50   - <el-col :span="6" class="left">
51   - <div class="left-icon">
52   - <div class="icon">
53   - <img src="../../../assets/images/shuben.png" />
54   - </div>
55   - <div class="text">
56   - {{ item.id }}
57   - </div>
58   - </div>
59   - </el-col>
60   - <el-col :span="18" class="content">
61   - <div class="title-text">
  45 + <el-tab-pane :name="'0'" :label="`我自编的(${createdCount})`">
  46 + <div class="card-content" :key="index" v-for="( item, index ) in defaultList ">
  47 + <el-row>
  48 + <el-col :span="6" class="left">
  49 + <div class="left-icon">
  50 + <div class="icon">
  51 + <img src="../../../assets/images/shuben.png" />
  52 + </div>
  53 + <div class="text">
  54 + {{ item.id }}
  55 + </div>
  56 + </div>
  57 + </el-col>
  58 + <el-col :span="18" class="content">
  59 + <div class="title-text">
  60 + <el-tooltip effect="dark" :content="item.title" placement="left">
  61 + <div class="title-label overflowText">
62 62 {{ item.title }}
63   - <el-dropdown class="dropdown-button" :hide-on-click="false">
64   - <el-button>操作</el-button>
65   - <el-dropdown-menu slot="dropdown">
66   - <el-dropdown-item
67   - @click.native="_detailQ(item.id)">查看</el-dropdown-item>
68   - <el-dropdown-item
69   - @click.native="_updateQ(item)">修改</el-dropdown-item>
70   - <el-dropdown-item
71   - @click.native="_copy(item)">复制</el-dropdown-item>
72   - <el-dropdown-item>
73   - <el-popconfirm style="color:gray !important;"
74   - @confirm="_deleteDetermineQ(item.id)"
75   - title="这是一段内容确定删除吗?">
76   - <el-button style="color:#606266 !important;"
77   - @click.native="_delete(item.id)" type="text"
78   - slot="reference">删除</el-button>
79   - </el-popconfirm>
80   - </el-dropdown-item>
81   - </el-dropdown-menu>
82   - </el-dropdown>
83   - </div>
84   - <div class="descption-tag-text" v-if="role != 'ROLE_PERSONAL'">
85   - <template>
86   - 授课端同步:
87   - <span class="descption-tag"
88   - v-for="( clazzChild, indexs ) in item.classList "
89   - :key="clazzChild.classId"
90   - :class="clazzChild.keepStatus == 1 ? 'active' : ''">
91   - {{ clazzChild.className }}
92   - <i v-if="clazzChild.keepStatus == 1"
93   - class="el-icon-success"></i>
94   - </span>
95   - <el-tooltip effect="dark" content="刷新同步状态">
96   - <img @click="_loadQueryDatas" height="18px" width="18px"
97   - src="../../../assets/images/shuaxin.png" />
98   - </el-tooltip>
99   - </template>
100 63 </div>
101   - <div class="descption-text">
102   - <span class="descption-text-block">
103   - <div class="pic">
104   - <img src="../../../assets/images/tishu.png" />
105   - </div>
106   - <div class="text"> 总题数:</div>
107   - <div class="value">{{ item.questionNum }}</div>
108   - <div class="pic" v-if="dataType == 2" style="margin-left: 44px;">
109   - <img src="../../../assets/images/tishu.png" />
110   - </div>
111   - <div class="text" v-if="dataType == 2"> 预计时长:</div>
112   - <div class="value" v-if="dataType == 2">{{ item.examsDuration }}
113   - 分钟
114   - </div>
115   - <div class="pic" style="margin-left: 44px;">
116   - <img src="../../../assets/images/tishu.png" />
117   - </div>
118   - <div class="text"> 创建人:</div>
119   - <div class="value">{{ item.realName }}</div>
  64 + </el-tooltip>
  65 + <el-dropdown class="dropdown-button" :hide-on-click="false">
  66 + <el-button>操作</el-button>
  67 + <el-dropdown-menu slot="dropdown">
  68 + <el-dropdown-item
  69 + @click.native="_detailQ(item.id)">查看</el-dropdown-item>
  70 + <el-dropdown-item @click.native="_updateQ(item)">修改</el-dropdown-item>
  71 + <el-dropdown-item @click.native="_copy(item)">复制</el-dropdown-item>
  72 + <el-dropdown-item>
  73 + <el-popconfirm style="color:gray !important;"
  74 + @confirm="_deleteDetermineQ(item.id)"
  75 + :title="dataType == 1 ? '确认删除此课件' : '确认删除此试卷'">
  76 + <el-button style="color:#606266 !important;"
  77 + @click.native="_delete(item.id)" type="text"
  78 + slot="reference">删除</el-button>
  79 + </el-popconfirm>
  80 + </el-dropdown-item>
  81 + </el-dropdown-menu>
  82 + </el-dropdown>
  83 + </div>
  84 + <div class="descption-tag-text" v-if="role != 'ROLE_PERSONAL'">
  85 + <template>
  86 + <span class="descption-label"> 授课端同步:</span>
  87 + <div class="descption-box">
  88 + <span class="descption-tag"
  89 + v-for="( clazzChild, indexs ) in item.classList "
  90 + :key="clazzChild.classId"
  91 + :class="clazzChild.keepStatus == 1 ? 'active' : ''">
  92 + {{ clazzChild.className }}
  93 + <i v-if="clazzChild.keepStatus == 1" class="el-icon-success"></i>
120 94 </span>
  95 + <el-tooltip effect="dark" content="刷新同步状态">
  96 + <img @click="_serach" height="18px" width="18px"
  97 + src="../../../assets/images/shuaxin.png" />
  98 + </el-tooltip>
121 99 </div>
122   - <div class="descption-text">
123   - <span class="descption-text-block">
124   - <div class="pic"><img src="../../../assets/images/rili.png"></img>
125   - </div>
126   - <div class="text"> 更新时间:</div>
127   - <div class="value">{{ item.modifiedTime }}</div>
128   - <span class="sharing-descption"
129   - v-if="item.sharingType == 1">已分享到非任课班级</span>
130   - </span>
  100 + </template>
  101 + </div>
  102 + <div class="descption-text">
  103 + <span class="descption-text-block">
  104 + <div class="pic">
  105 + <img src="../../../assets/images/tishu.png" />
131 106 </div>
132   - </el-col>
133   - </el-row>
134   - </div>
135   - </el-col>
136   - </el-row>
137   - </el-tab-pane>
138   - <el-tab-pane :name="'1'" :label="`共享课件(${sharedCount})`">
139   - <el-row>
140   - <el-col :key="index" v-for="( item, index ) in sharedList " :span="12">
141   - <div class="card-content">
142   - <el-row>
143   - <el-col :span="6" class="left">
144   - <div class="left-icon">
145   - <div class="icon">
146   - <img src="../../../assets/images/shuben.png" />
147   - </div>
148   - <div class="text">
149   - {{ item.id }}
150   - </div>
  107 + <div class="text"> 总题数:</div>
  108 + <div class="value">{{ item.questionNum }}</div>
  109 + <div class="pic" v-if="dataType == 2" style="margin-left: 44px;">
  110 + <img src="../../../assets/images/tishu.png" />
151 111 </div>
152   - </el-col>
153   - <el-col :span="15" class="content">
154   - <div class="title-text">
155   - {{ item.title }}
  112 + <div class="text" v-if="dataType == 2"> 预计时长:</div>
  113 + <div class="value" v-if="dataType == 2">{{ item.examsDuration }}
  114 + 分钟
156 115 </div>
157   - <div class="descption-tag-text" v-if="role != 'ROLE_PERSONAL'">
158   - <template>
159   - 授课端同步:
160   - <span class="descption-tag"
161   - v-for="( clazzChild, indexs ) in item.classList "
162   - :key="clazzChild.classId"
163   - :class="clazzChild.keepStatus == 1 ? 'active' : ''">
164   - {{ clazzChild.className }}
165   - <i v-if="clazzChild.keepStatus == 1"
166   - class="el-icon-success"></i>
167   - </span>
168   - <el-tooltip effect="dark" content="刷新同步状态">
169   - <img @click="_loadQueryDatas" height="18px" width="18px"
170   - src="../../../assets/images/shuaxin.png" />
171   - </el-tooltip>
172   - </template>
  116 + <div class="pic" style="margin-left: 44px;">
  117 + <img src="../../../assets/images/tishu.png" />
173 118 </div>
174   - <div class="descption-text">
175   - <span class="descption-text-block">
176   - <div class="pic"><img src="../../../assets/images/tishu.png"></img>
177   - </div>
178   - <div class="text"> 总题数:</div>
179   - <div class="value">{{ item.questionNum }}</div>
180   -
181   - <div class="pic" style="margin-left: 44px;"><img
182   - src="../../../assets/images/tishu.png"></img>
183   - </div>
184   - <div class="text"> 创建人:</div>
185   - <div class="value">{{ item.realName }}</div>
186   - </span>
  119 + <div class="text"> 创建人:</div>
  120 + <div class="value">{{ item.realName }}</div>
  121 + </span>
  122 + </div>
  123 + <div class="descption-text">
  124 + <span class="descption-text-block">
  125 + <div class="pic"><img src="../../../assets/images/rili.png"></img>
187 126 </div>
188   - <div class="descption-text">
189   - <span class="descption-text-block">
190   - <div class="pic"><img src="../../../assets/images/rili.png"></img>
191   - </div>
192   - <div class="text"> 更新时间:</div>
193   - <div class="value">{{ item.createdTime }}</div>
  127 + <div class="text"> 更新时间:</div>
  128 + <div class="value">{{ item.modifiedTime }}</div>
  129 + <span class="sharing-descption"
  130 + v-if="item.sharingType == 1">已分享到非任课班级</span>
  131 + </span>
  132 + </div>
  133 + </el-col>
  134 + </el-row>
  135 + </div>
  136 + </el-tab-pane>
  137 + <el-tab-pane :name="'1'" :label="`被共享的(${sharedCount})`">
  138 + <div class="card-content" :key="index" v-for="( item, index ) in sharedList ">
  139 + <el-row>
  140 + <el-col :span="6" class="left">
  141 + <div class="left-icon">
  142 + <div class="icon">
  143 + <img src="../../../assets/images/shuben.png" />
  144 + </div>
  145 + <div class="text">
  146 + {{ item.id }}
  147 + </div>
  148 + </div>
  149 + </el-col>
  150 + <el-col :span="18" class="content">
  151 + <div class="title-text">
  152 + <el-tooltip effect="dark" :content="item.title" placement="left">
  153 + <div class="title-label overflowText">
  154 + {{ item.title }}
  155 + </div>
  156 + </el-tooltip>
  157 + <el-dropdown class="dropdown-button" :hide-on-click="false">
  158 + <el-button>操作</el-button>
  159 + <el-dropdown-menu slot="dropdown">
  160 + <el-dropdown-item
  161 + @click.native="_detailQ(item.id)">查看</el-dropdown-item>
  162 + <el-dropdown-item>
  163 + <el-popconfirm style="color:gray !important;"
  164 + @confirm="_deleteDetermineQ(item.id)"
  165 + :title="dataType == 1 ? '确认删除此课件' : '确认删除此试卷'">
  166 + <el-button style="color:#606266 !important;"
  167 + @click.native="_delete(item.id)" type="text"
  168 + slot="reference">删除</el-button>
  169 + </el-popconfirm>
  170 + </el-dropdown-item>
  171 + </el-dropdown-menu>
  172 + </el-dropdown>
  173 + </div>
  174 + <div class="descption-tag-text" v-if="role != 'ROLE_PERSONAL'">
  175 + <template>
  176 + <span class="descption-label"> 授课端同步:</span>
  177 + <div class="descption-box">
  178 + <span class="descption-tag"
  179 + v-for="( clazzChild, indexs ) in item.classList "
  180 + :key="clazzChild.classId"
  181 + :class="clazzChild.keepStatus == 1 ? 'active' : ''">
  182 + {{ clazzChild.className }}
  183 + <i v-if="clazzChild.keepStatus == 1" class="el-icon-success"></i>
194 184 </span>
  185 + <el-tooltip effect="dark" content="刷新同步状态">
  186 + <img @click="_serach" height="18px" width="18px"
  187 + src="../../../assets/images/shuaxin.png" />
  188 + </el-tooltip>
  189 + </div>
  190 + </template>
  191 + </div>
  192 + <div class="descption-text">
  193 + <span class="descption-text-block">
  194 + <div class="pic">
  195 + <img src="../../../assets/images/tishu.png" />
  196 + </div>
  197 + <div class="text"> 总题数:</div>
  198 + <div class="value">{{ item.questionNum }}</div>
  199 + <div class="pic" v-if="dataType == 2" style="margin-left: 44px;">
  200 + <img src="../../../assets/images/tishu.png" />
  201 + </div>
  202 + <div class="text" v-if="dataType == 2"> 预计时长:</div>
  203 + <div class="value" v-if="dataType == 2">{{ item.examsDuration }}
  204 + 分钟
  205 + </div>
  206 + <div class="pic" style="margin-left: 44px;">
  207 + <img src="../../../assets/images/tishu.png" />
195 208 </div>
196   - </el-col>
197   - <el-col :span="3" class="right">
198   - <el-dropdown :hide-on-click="true">
199   - <el-button>操作</el-button>
200   - <el-dropdown-menu slot="dropdown">
201   - <el-dropdown-item>查看</el-dropdown-item>
202   - <el-dropdown-item>删除</el-dropdown-item>
203   - </el-dropdown-menu>
204   - </el-dropdown>
205   - </el-col>
206   - </el-row>
207   - </div>
208   - </el-col>
209   - </el-row>
  209 + <div class="text"> 创建人:</div>
  210 + <div class="value">{{ item.realName }}</div>
  211 + </span>
  212 + </div>
  213 + <div class="descption-text">
  214 + <span class="descption-text-block">
  215 + <div class="pic"><img src="../../../assets/images/rili.png"></img>
  216 + </div>
  217 + <div class="text"> 更新时间:</div>
  218 + <div class="value">{{ item.modifiedTime }}</div>
  219 + </span>
  220 + </div>
  221 + </el-col>
  222 + </el-row>
  223 + </div>
210 224 </el-tab-pane>
211 225 <div slot="tab-bar">
212 226 <el-button type="primary" icon="el-icon-plus">新增</el-button>
213 227 </div>
214 228 </el-tabs>
215 229 <el-button size='mini' v-if="role == 'ROLE_PERSONAL' || role == 'ROLE_JIAOSHI'" @click="recycle"
216   - style='position: absolute;right:40px;top:5px;'>查看回收站</el-button>
  230 + style='position: absolute;right:40px;top:2.5px;'>查看回收站</el-button>
217 231 </div>
218 232 </el-main>
219 233 <el-footer class="el-footer-pagination">
220   - <el-pagination @current-change="pageSizeChange" background layout="prev, pager, next"
221   - :size="listPage.size" :current-page="listPage.page"
222   - :total="listPage.total">
  234 + <el-pagination @current-change="pageSizeChange" background layout="prev, pager, next" :size="listPage.size"
  235 + :current-page="listPage.page" :total="listPage.total">
223 236 </el-pagination>
224 237 </el-footer>
225   - <el-dialog :append-to-body="true" :close-on-click-modal="false" title="上传word文档" :visible.sync="diaUp" width="600px">
  238 + <el-dialog :append-to-body="true" :close-on-click-modal="false" title="上传word文档" :visible.sync="diaUp"
  239 + width="600px">
226 240 <upload :url="url" :params="{ type: importType }" @upSuccess="upSuccess" fileName="下载">
227 241 <div class="down-box p0" slot="down">
228 242 <p class="down-head" v-if="importType == 1">
229 243 <span>第一步:</span>
230   - <el-link type="primary" @click="downExcel">下载模板,</el-link>
  244 + <!-- <el-link type="primary" @click="downExcel">下载模板,</el-link> -->
231 245 <span>或者导出菁优网试卷/组卷网(学科网)试卷;
232 246 为保证第三方试卷导入成功,请注意参考导出示例:</span>
233 247 <span class="img-box">
... ... @@ -241,7 +255,9 @@
241 255 </span>
242 256 </p>
243 257 <p class="down-head" v-if="importType == 2">
244   - <span>第一步:导出菁优网试卷/组卷网(学科网)试卷;为保证第三方试卷导入成功,请注意参考导出示例:</span>
  258 + <span>第一步:
  259 + <el-link type="primary" @click="downExcel">下载模板,</el-link>
  260 + 导出菁优网试卷/组卷网(学科网)试卷;为保证第三方试卷导入成功,请注意参考导出示例:</span>
245 261 <span class="img-box">
246 262 <el-image class="img" :src="examplePic" :preview-src-list="examplePicList">
247 263 </el-image>
... ... @@ -266,10 +282,10 @@
266 282 </template>
267 283  
268 284 <script>
269   -import { setDateRules } from "@/utils";
270   -import example from "@/assets/images/example.jpg";
  285 +import { setDateRules, downloadFile } from "@/utils";
  286 +import example from "@/assets/images/example.png";
271 287 import example2 from "@/assets/images/example2.png";
272   -
  288 +import axios from "axios";
273 289  
274 290 export default {
275 291 data() {
... ... @@ -309,7 +325,7 @@ export default {
309 325 sharedCount: 0
310 326 };
311 327 },
312   - watch: {
  328 + watch: {
313 329 '$route'() {
314 330 this.dataType = location.href.endsWith("askPreparationQuestions") ? "1" : "2";
315 331 this._serach();
... ... @@ -323,16 +339,37 @@ export default {
323 339 this.query.dateRange = [dateRange.startDay, dateRange.endDay];
324 340 }
325 341 },
326   - created() {
  342 + async created() {
327 343 this.dataType = location.href.endsWith("askPreparationQuestions") ? "1" : "2";
328 344 this.code = this.$store.getters.csCode;
329 345 this.role =
330 346 this.$store.getters.info.showRole ||
331 347 this.$store.getters.info.permissions[0].role;
332   - this._loadQueryDatas();
  348 + this.dateStatus = "onWeek";
  349 + await this._loadQueryDatas();
333 350 },
334 351 methods: {
335   - async pageSizeChange(value){
  352 + async downExcel() {
  353 + let url;
  354 + let that = this;
  355 + if (that.dataType == 1) {
  356 + url = "static/课件模板.docx";
  357 + } else {
  358 + url = "static/试卷模板.docx";
  359 + }
  360 + axios(url, {
  361 + responseType: "arraybuffer",
  362 + }).then((res) => {
  363 + let blob = new Blob([res.data], {
  364 + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  365 + });
  366 + downloadFile(
  367 + that.dataType == 1 ? "课件模板.docx" : "试卷模板.docx",
  368 + blob
  369 + );
  370 + });
  371 + },
  372 + async pageSizeChange(value) {
336 373 this.listPage.page = value;
337 374 await this._serach();
338 375 },
... ... @@ -345,7 +382,7 @@ export default {
345 382 }
346 383 this.$router.push(routerItem);
347 384 },
348   - createAnwseredCard() {
  385 + createAnwseredCard(params) {
349 386 let routerItem = {
350 387 path: "/testPaperAdd",
351 388 query: {
... ... @@ -356,7 +393,7 @@ export default {
356 393 };
357 394 this.$router.push(routerItem);
358 395 },
359   - import(type) {
  396 + importQuestion(type) {
360 397 this.importType = type;
361 398 this.diaUp = true;
362 399 },
... ... @@ -373,13 +410,48 @@ export default {
373 410 });
374 411 this.diaUp = false;
375 412 let params = JSON.stringify(res.data);
376   - if (this.query.type == 2) {
377   - this.toAdd({ params, isUpload: 1 });
  413 + if (this.dataType == 1) {
  414 + this.toAdd({ params, isUpload: true });
378 415 } else {
379   - this.toAddQs({ params });
  416 + this.toAddQs({ params, isUpload: true });
380 417 }
381 418 }
382 419 },
  420 + toAdd(query) {
  421 + if (!this.query.class) {
  422 + this.$message.warning("没有任课班级,请先设置。");
  423 + return;
  424 + }
  425 + let routerItem = {
  426 + path: "/askPreparationQuestionsAdd",
  427 + query: {
  428 + ...query,
  429 + classId: this.query.class,
  430 + listType: 2,
  431 + listShare: 0,
  432 + subjectName: this.query.subject,
  433 + },
  434 + };
  435 + this.$router.push(routerItem);
  436 + },
  437 + //去备题
  438 + toAddQs(query) {
  439 + if (!this.query.class) {
  440 + this.$message.warning("没有任课班级,请先设置。");
  441 + return;
  442 + }
  443 + let routerItem = {
  444 + path: "/testPaperAdd",
  445 + query: {
  446 + ...query,
  447 + classId: this.query.class,
  448 + listType: 2,
  449 + listShare: 0,
  450 + subjectName: this.query.subject,
  451 + },
  452 + };
  453 + this.$router.push(routerItem);
  454 + },
383 455 async _changeClass() {
384 456 await this._loadSubjectData();
385 457 },
... ... @@ -488,7 +560,7 @@ export default {
488 560 this.createdCount = data?.myCount || 0;
489 561 this.sharedCount = data?.gradeCount || 0;
490 562 this.listPage.total = data.total;
491   -
  563 +
492 564 if (this.tabType == "0") {
493 565 this.defaultList = [];
494 566 if (data?.list) this.defaultList = [...data?.list];
... ... @@ -504,11 +576,18 @@ export default {
504 576 query: { id: id },
505 577 };
506 578 if (this.dataType == '2') {
507   - routerItem.path = "/testPaperQuestionsDetail";
  579 + var currentClass = this.classList.find(item => item.classId == this.query.class);
  580 + routerItem.query.paperId = routerItem.query.id;
  581 + routerItem.query.classId = currentClass.classId;
  582 + routerItem.query.isViewer = true;
  583 + routerItem.query.gradeName = currentClass.gradeName;
  584 + routerItem.query.paperType = 2;
  585 + routerItem.path = '/testPaperQuestionsUpdate';
  586 + // routerItem.path = "/testPaperQuestionsDetail";
508 587 }
509 588 this.$router.push(routerItem);
510 589 },
511   - _copy(currentRow) {
  590 + _copy(currentRow) {
512 591 let routerItem = {
513 592 path: "/askPreparationQuestionsAdd",
514 593 query: {
... ... @@ -530,19 +609,21 @@ export default {
530 609  
531 610 },
532 611 _updateQ(item) {
533   - console.log(item)
  612 +
534 613 var currentClass = this.classList.find(item => item.classId == this.query.class);
535 614  
536 615 let routerItem = {
537 616 path: "/askPreparationQuestionsUpdate",
538 617 query: {
539   - paperId: item.id, paperType: 1,
  618 + paperId: item.id,
  619 + paperType: 1,
540 620 classId: currentClass.classId,
541 621 gradeName: currentClass.gradeName
542 622 },
543 623 };
544 624  
545 625 if (this.dataType == '2') {
  626 + routerItem.query.paperType = 2;
546 627 routerItem.path = "/testPaperQuestionsUpdate";
547 628 }
548 629  
... ... @@ -610,12 +691,15 @@ export default {
610 691 color: #667FFD;
611 692 line-height: 32px;
612 693 padding: 0 10px;
613   - height: 32px;
614 694 margin-right: 10px;
  695 + height: 32px;
  696 + margin-top: 3px;
615 697 }
616 698  
  699 + width: 48.5%;
  700 + display: inline-block;
617 701 margin-bottom: 10px;
618   - height: 180px;
  702 + min-height: 190px;
619 703 border: 1px solid #E6E9F4;
620 704 border-radius: 10px 10px 10px 10px;
621 705 box-shadow: 0px 4px 14px 0px rgba(0, 0, 0, 0.08);
... ... @@ -628,13 +712,20 @@ export default {
628 712 font-size: 14px;
629 713 font-weight: 400;
630 714  
  715 + .descption-label {
  716 + min-width: 120px;
  717 + }
  718 +
631 719 .descption-tag-text {
632 720 margin-bottom: 20px;
633 721 display: flex;
634 722 justify-content: flex-start;
635 723 align-items: center;
  724 + width: calc(100% - 5px);
636 725 }
637 726  
  727 +
  728 +
638 729 .descption-text {
639 730 height: 30px;
640 731 margin-top: 10px;
... ... @@ -660,13 +751,17 @@ export default {
660 751 }
661 752  
662 753 .title-text {
663   - font-weight: bold;
664   - font-size: 20px;
665   - color: #303133;
666   - line-height: 28px;
667   - height: 28px;
668   - text-transform: none;
669   - padding-bottom: 10px !important;
  754 + .title-label {
  755 + font-weight: bold;
  756 + font-size: 24px !important;
  757 + color: #303133;
  758 + line-height: 28px;
  759 + display: inline-block;
  760 + width: calc(100% - 100px);
  761 + height: 28px;
  762 + text-transform: none;
  763 + padding-bottom: 10px !important;
  764 + }
670 765  
671 766 .dropdown-button {
672 767 .el-button {
... ... @@ -682,7 +777,7 @@ export default {
682 777 }
683 778  
684 779 .left {
685   - height: 180px;
  780 + height: 190px;
686 781 background-color: #41CC95;
687 782 vertical-align: middle;
688 783 border-radius: 10px 0px 0px 10px;
... ...
src/views/basic/askTestQuestion/recycle.vue
... ... @@ -32,7 +32,7 @@
32 32 <el-main>
33 33 <div style='position: relative;'>
34 34 <el-tabs v-model="tabType" v-loading="queryLoading" type="card" class="default-tabs">
35   - <el-tab-pane :name="'0'" :label="`自编课件(${createdCount})`">
  35 + <el-tab-pane :name="'0'" :label="`我自编的(${createdCount})`">
36 36 <el-table class="default-table" :data="defaultList">
37 37 <el-table-column prop="id" label="试卷ID" width="100"></el-table-column>
38 38 <el-table-column prop="title" label="试卷名称"></el-table-column>
... ... @@ -56,7 +56,7 @@
56 56 </el-table-column>
57 57 </el-table>
58 58 </el-tab-pane>
59   - <el-tab-pane :name="'1'" :label="`共享课件(${sharedCount})`">
  59 + <el-tab-pane :name="'1'" :label="`被共享的(${sharedCount})`">
60 60 <el-table class="default-table" :data="sharedList">
61 61 <el-table-column prop="id" label="试卷ID" width="100"></el-table-column>
62 62 <el-table-column prop="title" label="试卷名称"></el-table-column>
... ... @@ -66,11 +66,11 @@
66 66 <el-table-column prop="createdTime" label="创建时间"></el-table-column>
67 67 <el-table-column prop="modifiedTime" label="删除时间"></el-table-column>
68 68 <el-table-column prop="createdTime" label="操作">
69   - <template>
70   - <el-button class="edit" type="text" size="mini" @click="modify(item)">
  69 + <template slot-scope="scoped">
  70 + <el-button class="edit" type="text" size="mini" @click="modify(scoped.row)">
71 71 恢复
72 72 </el-button>
73   - <el-popconfirm title="确定删除这张答题卡吗?" @confirm="remove(item)">
  73 + <el-popconfirm title="确定删除这张答题卡吗?" @confirm="remove(scoped.row)">
74 74 <el-button style="color:red;margin-left: 10px;" slot="reference" class="delete"
75 75 type="text" size="mini">
76 76 删除
... ... @@ -96,6 +96,7 @@
96 96 </el-container>
97 97 </template>
98 98 <script>
  99 +import { setDateRules } from "utils";
99 100 export default {
100 101 data() {
101 102 return {
... ... @@ -139,12 +140,21 @@ export default {
139 140 this.$store.getters.info.showRole ||
140 141 this.$store.getters.info.permissions[0].role;
141 142  
  143 + var dateRange = setDateRules('onDay');
  144 + console.log(dateRange)
  145 + this.query.dateRange = [dateRange.startDay, dateRange.endDay];
142 146 await this._loadQueryDatas();
143 147 await this._serach();
144 148  
145 149 },
  150 + watch: {
  151 + 'tabType'() {
  152 + this.listPage.page = 1;
  153 + this._serach();
  154 + }
  155 + },
146 156 methods: {
147   - async modify(obj) {
  157 + async modify(obj) {
148 158 //恢复答题卡
149 159 let modifyPaper =
150 160 this.role == "ROLE_PERSONAL"
... ... @@ -152,10 +162,12 @@ export default {
152 162 : this.$request.modifyPaper;
153 163 const { data, status, info } = await modifyPaper({
154 164 paperId: obj.id,
155   - status: 1,
  165 + share: this.tabType == '0' ? "0" : "1",
  166 + status: 1
156 167 });
157 168 if (status == 0) {
158 169 let type = this.query.title ? 1 : 0;
  170 + this.$message.success(info);
159 171 this._serach(type);
160 172 } else {
161 173 this.$message.error(info);
... ... @@ -169,9 +181,13 @@ export default {
169 181 : this.$request.delPaper;
170 182 const { data, status, info } = await delPaper({
171 183 paperId: obj.id,
  184 + share: this.tabType == '0' ? "0" : "1",
  185 + status: 2
  186 +
172 187 });
173 188 if (status == 0) {
174 189 let type = this.query.title ? 1 : 0;
  190 + this.$message.success(info);
175 191 this._serach(type);
176 192 } else {
177 193 this.$message.error(info);
... ... @@ -284,7 +300,7 @@ export default {
284 300 }
285 301 this.queryLoading = false;
286 302 this.createdCount = data?.myCount || 0;
287   - this.sharedCount = data?.gradeCount || 0;
  303 + this.sharedCount = data?.delShare || 0;
288 304 this.listPage.total = data.total;
289 305 if (this.tabType == "0") {
290 306 this.defaultList = [];
... ...
src/views/basic/askTestQuestion/report.vue
... ... @@ -4,24 +4,29 @@
4 4 <div class="default-title">{{ dataType == "1" ? '随堂问报表' : '即时测报表' }}</div>
5 5 </el-header>
6 6 <div class="default-filter">
7   - <el-input v-model="query.paper" placeholder="报表名称" suffix-icon="el-icon-search" class="filter-input" type="number"
8   - clearable />
  7 + <!-- <el-input v-model="query.paper" placeholder="报表名称" suffix-icon="el-icon-search" class="filter-input" type="number"
  8 + clearable /> -->
9 9 <el-select @change="_changeClass" v-model="query.class" class="filter-select" placeholder="选择班级">
10 10 <el-option v-for="item in classList " :key="item.classId" :label="item.className" :value="item.classId" />
11 11 </el-select>
12 12 <el-select v-model="query.subject" v-if="role == 'ROLE_JIAOSHI'" placeholder="选择科目" class="filter-select">
13 13 <el-option v-for=" item in subjectList" :key="item" :label="item" :value="item" />
14 14 </el-select>
15   - <el-select v-model="query.subjects" collapse-tags v-if="role == 'ROLE_BANZHUREN'" multiple placeholder="选择科目"
  15 + <el-select v-model="query.subjects" style="width: 18%;" collapse-tags v-if="role == 'ROLE_BANZHUREN'" multiple placeholder="选择科目"
16 16 class="filter-select">
17 17 <el-option v-for="item in subjectList" :key="item" :label="item" :value="item">
18 18 <!-- <el-checkbox :checked="checkedSubject.indexOf(item) >= 0" @click="subjectCheck(item)">{{ item }}</el-checkbox> -->
19 19 </el-option>
20 20 </el-select>
21   - <el-date-picker class="filter-datePicker" v-model="query.dateRange" type="daterange" range-separator="-"
22   - value-format="yyyy-MM-dd">
  21 + <el-date-picker class="filter-datePicker" @change="_dateChange" v-model="query.dateRange" type="daterange"
  22 + range-separator="-" value-format="yyyy-MM-dd">
23 23 </el-date-picker>
24 24 <el-button type="primary" @click="_serach"> 筛选 </el-button>
  25 + <el-radio-group v-model="dateStatus" class="default-date-radio-group">
  26 + <el-radio-button label="onDay">今天</el-radio-button>
  27 + <el-radio-button label="onWeek">本周</el-radio-button>
  28 + <el-radio-button label="onMonth">本月</el-radio-button>
  29 + </el-radio-group>
25 30 </div>
26 31 <el-main>
27 32 <div style="position: relative">
... ... @@ -31,37 +36,43 @@
31 36 :queryParams="query" />
32 37 </el-tab-pane>
33 38 <el-tab-pane v-if="dataType == 1 && role == 'ROLE_JIAOSHI'" :name="'1'" :label="`单课时报表`">
34   - <askListReport v-if="apiDatas.askReportList" :datas="apiDatas.askReportList" />
  39 + <askListReport v-if="apiDatas.askReportList" :datas="apiDatas.askReportList" @opration="_serach" />
35 40 </el-tab-pane>
36   - <el-tab-pane v-if="dataType == 1 && role == 'ROLE_BANZHUREN'" :name="'0'" :label="`多科表现`"
37   - :queryParams="query">
  41 + <el-tab-pane v-if="dataType == 1 && role == 'ROLE_BANZHUREN' && query.status == 'multi'" :name="'0'"
  42 + :label="`多科表现`" :queryParams="query">
38 43 <askBzrMulti v-if="apiDatas.askReportIds" :askReportIds="apiDatas.askReportIds" :queryParams="query" />
39   - <!-- <askSummaryReport v-else-if="query.status == 'single'" :testReportIds="apiDatas.testReportIds"
40   - :queryParams="query" /> -->
  44 + </el-tab-pane>
  45 + <el-tab-pane v-if="dataType == 1 && role == 'ROLE_BANZHUREN' && query.status == 'single'" :name="'1'"
  46 + :label="`单科表现`" :queryParams="query">
  47 + <askSummaryReport :role="role" ref="askSummaryReport" v-if="apiDatas.askReportIds" :askReportIds="apiDatas.askReportIds"
  48 + :queryParams="query" />
41 49 </el-tab-pane>
42 50 <el-tab-pane v-if="dataType == 2 && role == 'ROLE_JIAOSHI'" :name="'0'" :label="`阶段报表`">
43 51 <testSummaryReport v-if="apiDatas.testReportIds" :testReportIds="apiDatas.testReportIds"
44   - :queryParams="query" />
  52 + @headerClick="_headerClick" :queryParams="query" />
45 53 </el-tab-pane>
46 54 <el-tab-pane v-if="dataType == 2 && role == 'ROLE_JIAOSHI'" :name="'1'" :label="`单卷报表`">
47   - <testListReport :datas="apiDatas.testReportList" />
  55 + <testListReport :datas="apiDatas.testReportList" @opration="_serach" />
48 56 </el-tab-pane>
49 57 <el-tab-pane v-if="dataType == 2 && role == 'ROLE_JIAOSHI'" :name="'2'" :label="`多班对比报表`">
50 58 <testMultiClassReport :params="query" />
51 59 </el-tab-pane>
52   - <el-tab-pane v-if="dataType == 2 && role == 'ROLE_BANZHUREN'" :name="'0'" :label="`多科表现`">
  60 + <el-tab-pane v-if="dataType == 2 && role == 'ROLE_BANZHUREN' && query.status == 'multi'" :name="'0'"
  61 + :label="`多科表现`">
53 62 <testBzrMulti v-if="apiDatas.testReportIds" :list="apiDatas.testReportList"
54 63 :testReportIds="apiDatas.testReportIds" :queryParams="query" />
55   -
56   - <!-- <testSummaryReport v-else-if="apiDatas.testReportIds" :testReportIds="apiDatas.testReportIds"
57   - :queryParams="query" /> -->
  64 + </el-tab-pane>
  65 + <el-tab-pane v-if="dataType == 2 && role == 'ROLE_BANZHUREN' && query.status == 'single'" :name="'1'"
  66 + :label="`单科表现`">
  67 + <testSummaryReport v-if="apiDatas.testReportIds" :role="role" :list="apiDatas.testReportList"
  68 + :testReportIds="apiDatas.testReportIds" :queryParams="query" />
58 69 </el-tab-pane>
59 70 <div slot="tab-bar">
60 71 <el-button type="primary" icon="el-icon-plus">新增</el-button>
61 72 </div>
62 73 </el-tabs>
63   - <el-button size='mini' v-if="role == 'ROLE_PERSONAL' || role == 'ROLE_JIAOSHI'" @click="_recycle"
64   - style='position: absolute;right:40px;top:5px;'>查看回收站</el-button>
  74 + <!-- <el-button size='mini' v-if="role == 'ROLE_PERSONAL' || role == 'ROLE_JIAOSHI'" @click="_recycle"
  75 + style='position: absolute;right:40px;top:5px;'>查看回收站</el-button> -->
65 76  
66 77 </div>
67 78 </el-main>
... ... @@ -69,6 +80,7 @@
69 80 </template>
70 81  
71 82 <script>
  83 +import { setDateRules } from "@/utils";
72 84 export default {
73 85 name: "repo",
74 86 components: {
... ... @@ -111,9 +123,15 @@ export default {
111 123 testReportList: null,
112 124 },
113 125 queryLoading: false,
  126 + dateStatus: "0"
114 127 };
115 128 },
116 129 watch: {
  130 + 'dateStatus'(val) {
  131 + if (val == -1) return;
  132 + var dateRange = setDateRules(val);
  133 + this.query.dateRange = [dateRange.startDay, dateRange.endDay];
  134 + },
117 135 '$route'() {
118 136 this.dataType = location.href.endsWith("askReport") ? "1" : "2";
119 137 this._loadQueryDatas();
... ... @@ -127,14 +145,16 @@ export default {
127 145 }
128 146 },
129 147 async 'query.subjects'(value) {
130   - console.log(value)
131 148 if (this.role == "ROLE_BANZHUREN") {
132 149 if (value.length == 1 && value[0] != '全部科目') {
133 150 this.query.status = 'single';
  151 + this.tabType = '1';
134 152 await this._serach();
135 153 }
136 154 else {
137   -
  155 + this.query.status = 'multi';
  156 + this.tabType = '0';
  157 + await this._serach();
138 158 }
139 159 }
140 160  
... ... @@ -146,9 +166,30 @@ export default {
146 166 this.role =
147 167 this.$store.getters.info.showRole ||
148 168 this.$store.getters.info.permissions[0].role;
  169 + this.dateStatus = "onWeek";
149 170 await this._loadQueryDatas();
150 171 },
151 172 methods: {
  173 + _opr() {
  174 + alert('opr');
  175 + },
  176 + _dateChange() {
  177 + this.dateStatus = -1;
  178 + },
  179 + async _ReScore() {
  180 + //重新记分
  181 + let { data, info, status } = await this.$request.reScore({
  182 + examId: this.id,
  183 + });
  184 + if (status === 0) {
  185 + this.$message.success(info);
  186 + this._serach();
  187 + this.paperModifyLog.modifiedTime = "";
  188 + this.paperModifyLog.realName = "";
  189 + } else {
  190 + this.$message.error(info);
  191 + }
  192 + },
152 193 async _changeClass() {
153 194 await this._loadSubjectData();
154 195 },
... ... @@ -202,7 +243,7 @@ export default {
202 243 },
203 244 _recycle() { },
204 245 async _serach() {
205   -
  246 +
206 247 this.queryLoading = true;
207 248 var queryParams = {
208 249 classId: "",
... ... @@ -214,12 +255,15 @@ export default {
214 255  
215 256 queryParams.classId = this.query.class;
216 257 queryParams.classIds = [this.query.class];
217   - if (this.query.subjects) {
  258 +
  259 + if (this.query.subjects && this.role == 'ROLE_BANZHUREN') {
218 260 queryParams.subjectNames = this.query.subjects;
  261 + queryParams.subject = queryParams.subjectNames[0];
219 262 }
220 263 else {
221 264 queryParams.subjectNames = [this.query.subject];
222 265 }
  266 + console.log(queryParams, this.query.subject)
223 267  
224 268 queryParams.startDay = this.query.dateRange
225 269 ? this.query.dateRange[0]
... ... @@ -266,10 +310,15 @@ export default {
266 310 this.$message.error(testReportResponse.info);
267 311 return;
268 312 }
  313 +
269 314 this.apiDatas.testReportList = [...testReportResponse?.data?.list ?? []];
  315 +
270 316 this.apiDatas.testReportIds = [...this.apiDatas.testReportList?.map((item) => item.id) ?? []];
  317 +
271 318 }
  319 +
272 320 this.tabIndexs += 1;
  321 +
273 322 this.queryLoading = false;
274 323  
275 324 },
... ... @@ -288,6 +337,17 @@ export default {
288 337 };
289 338 this.$router.push(routerItem);
290 339 },
  340 + _headerClick(row) {
  341 + this.$router.push({
  342 + path: "/testReportDetail",
  343 + query: {
  344 + dataType: 2,
  345 + classIds: this.query.class,
  346 + id: row.examId,
  347 + title: row.title
  348 + },
  349 + });
  350 + },
291 351 async _deleteDetermineQ(id) {
292 352 let modifyPaper =
293 353 this.role == "ROLE_PERSONAL"
... ...
src/views/basic/askTestQuestion/update.vue
... ... @@ -4,7 +4,7 @@
4 4 <back-box class="detailBack">
5 5 <template slot="title">
6 6 <span class="default-title">
7   - {{ type == 1 ? "修改试卷" : "修改答案" }}</span>
  7 + {{ isViewer ? "详情" : type == 1 ? paperType == 1 ? "修改课件" : "修改试卷" : "修改答案" }}</span>
8 8 </template>
9 9 </back-box>
10 10 </el-header>
... ... @@ -21,103 +21,207 @@
21 21 <div class="answer-title" :class="type == 1 ? 't-left' : ''">
22 22 <p class="name-box">
23 23 <span>试卷名称:</span>
24   - <el-input class="ipt-name" v-model="form.title"></el-input>
  24 + <el-input :disabled="isViewer" class="ipt-name" v-model="form.title"></el-input>
25 25 </p>
26 26 <p class="name-box">
27 27 <span>分享范围:</span>
28   - <el-radio class="name-radio" v-model="form.sharingType" :label="0">任课班级分享</el-radio>
29   - <el-radio class="name-radio" @click.native="_selectClassSharingType" v-model="form.sharingType"
30   - :label="1">自定义分享班级</el-radio>
  28 + <el-radio :disabled="isViewer" class="name-radio" v-model="form.sharingType" :label="0">任课班级分享</el-radio>
  29 + <el-radio :disabled="isViewer" class="name-radio" @click.native="_selectClassSharingType"
  30 + v-model="form.sharingType" :label="1">自定义分享班级</el-radio>
31 31 </p>
32 32 </div>
33 33 <div class="question-box">
34   - <div v-if="paperType == 1">
35   - <div class="courseware">
36   - <div class="courseware-title sub-questions">
37   - <div class="qs-num">题号</div>
38   - <div class="qs-stem">题干</div>
39   - <div class="qs-type">题型</div>
40   - <div class="qs-score">分数</div>
41   - <div class="qs-partScore">漏选得分</div>
42   - <div class="qs-options">选项设置</div>
43   - <div class="qs-oprations">操作</div>
44   - </div>
45   - <div v-for="(question, index) in questionList">
46   - <div class="courseware-content sub-questions" v-for="(subQuestion, subIndex) in question.subQuestions">
47   - <div class="qs-num">{{ subQuestion.questionId }}</div>
48   - <div class="qs-stem">
49   - <iframe style="height: 100% !important" class="screenshot" :src="subQuestion.screenshot"></iframe>
50   - </div>
51   - <div class="qs-type">
52   - <el-select v-model="subQuestion.questionType">
53   - <el-option v-for="item in questionOption" :key="item.Key" :label="item.Text" :value="item.Key" />
54   - </el-select>
  34 + <div class="question-content">
  35 + <div v-if="paperType == 1" class="courseware-title sub-questions">
  36 + <div class="qs-num">题号</div>
  37 + <div class="qs-stem">题干</div>
  38 + <div class="qs-type">题型</div>
  39 + <div class="qs-score">分数</div>
  40 + <div class="qs-partScore">漏选得分</div>
  41 + <div class="qs-options">选项设置</div>
  42 + <div v-if="!isViewer" class="qs-oprations">操作</div>
  43 + </div>
  44 + <div>
  45 + <div class="question-contents" v-for="(question, index) in questionList">
  46 + <div :class="paperType != 1 ? 'bigQuestion' : ''">
  47 + <div class="bigQuestionTitle" v-if="paperType != 1">
  48 + {{ question.questionTitle }}
  49 + (共{{ question.subQuestions.filter(subQuestion => subQuestion &&
  50 + subQuestion.questionId && subQuestion.questionType).length }}小题,
  51 + 共{{ question.score }}分)
55 52 </div>
56   - <div class="qs-score">
57   - <el-input-number class="number-ipt" size="medium" :min="1" :max="200" :precision="2" :step="1"
58   - v-model="subQuestion.score" label="单题分值" />
  53 + <div v-if="paperType == 2 && index == 0" class="courseware-title sub-questions">
  54 + <div class="qs-num">题号</div>
  55 + <div class="qs-stem">题干</div>
  56 + <div class="qs-type">题型</div>
  57 + <div class="qs-score">分数</div>
  58 + <div class="qs-partScore">漏选得分</div>
  59 + <div class="qs-options">选项设置</div>
  60 + <div v-if="!isViewer" class="qs-oprations">操作</div>
59 61 </div>
60   - <div class="qs-partScore">
61   - <p v-if="subQuestion.questionType != 3">------</p>
62   - <el-input-number class="number-ipt" v-else size="medium" :min="0" :precision="2"
63   - :max="subQuestion.score" :step="0.5" v-model="subQuestion.partScore" label="漏选得分" />
  62 +
  63 + <div class="courseware-content sub-questions" v-if="subQuestion &&
  64 + subQuestion.questionId && subQuestion.questionType && question.subQuestions"
  65 + v-for="(subQuestion, subIndex) in question.subQuestions">
  66 + <div class="qs-num">{{ subQuestion.questionId }}</div>
  67 + <div class="qs-stem">
  68 + <iframe style="height: 100% !important" class="screenshot" :src="subQuestion.screenshot"></iframe>
  69 + </div>
  70 + <div class="qs-type">
  71 + <el-select :disabled="isViewer" v-model="subQuestion.questionType">
  72 + <el-option v-for="item in questionOption" :key="item.Key" :label="item.Text"
  73 + :value="item.Key" />
  74 + </el-select>
  75 + </div>
  76 + <div class="qs-score">
  77 + <el-input-number :disabled="isViewer" class="number-ipt" size="medium" :min="1" :max="200"
  78 + :precision="2" :step="1" v-model="subQuestion.score" label="单题分值" />
  79 + </div>
  80 + <div class="qs-partScore">
  81 + <p v-if="subQuestion.questionType != 3">------</p>
  82 + <el-input-number class="number-ipt" v-else size="medium" :min="0" :precision="2"
  83 + :max="subQuestion.score" :step="0.5" v-model="subQuestion.partScore" label="漏选得分" />
  84 + </div>
  85 + <div class="qs-options">
  86 + <p v-if="subQuestion.questionType == 5">--</p>
  87 + <p v-if="subQuestion.questionType == 4" class="answer-box">
  88 + <span class="answer-s" v-if="!isViewer"
  89 + :class="subQuestion.correctAnswer == 1 ? 'answer-active' : ''"
  90 + @click="subQuestion.correctAnswer = 1">✓</span>
  91 + <span class="answer-s" v-if="!isViewer"
  92 + :class="subQuestion.correctAnswer == 2 ? 'answer-active' : ''"
  93 + @click="subQuestion.correctAnswer = 2">✗</span>
  94 + <span class="answer-s" v-if="isViewer"
  95 + :class="subQuestion.correctAnswer == 1 ? 'answer-active' : ''">✓</span>
  96 + <span class="answer-s" v-if="isViewer"
  97 + :class="subQuestion.correctAnswer == 2 ? 'answer-active' : ''">✗</span>
  98 + </p>
  99 + <p v-if="subQuestion.questionType == 3" class="answer-box">
  100 + <template :disabled="isViewer" v-for="option in subQuestion.answerOptions.split(',')">
  101 + <span v-if="option && !isViewer" class="answer-s"
  102 + :class="subQuestion.correctAnswer.includes(option) ? 'answer-active' : ''" :key="option"
  103 + @click="changAnswer(subQuestion, option)">{{ option }}</span>
  104 + <span v-if="option && isViewer" class="answer-s"
  105 + :class="subQuestion.correctAnswer.includes(option) ? 'answer-active' : ''" :key="option">{{
  106 + option }}</span>
  107 + </template>
  108 + <span class="answer-s answer-opration" v-if="!isViewer"
  109 + @click="openStem(subQuestion, 4, index, subIndex)">+</span>
  110 + <span class="answer-s answer-opration" v-if="!isViewer"
  111 + @click="openStem(subQuestion, 4, index, subIndex)">-</span>
  112 + </p>
  113 + <p v-if="subQuestion.questionType == 2" class="answer-box">
  114 + <template :disabled="isViewer" v-for="option in subQuestion.answerOptions.split(',')">
  115 + <span class="answer-s" v-if="option && !isViewer"
  116 + :class="subQuestion.correctAnswer == option ? 'answer-active' : ''" :key="option"
  117 + @click="subQuestion.correctAnswer = option">{{ option }}</span>
  118 + <span v-if="option && isViewer" class="answer-s"
  119 + :class="subQuestion.correctAnswer.includes(option) ? 'answer-active' : ''" :key="option">{{
  120 + option }}</span>
  121 + </template>
  122 + <span class="answer-s answer-opration" v-if="!isViewer"
  123 + @click="openStem(subQuestion, 4, index, subIndex)">+</span>
  124 + <span class="answer-s answer-opration" v-if="!isViewer"
  125 + @click="openStem(subQuestion, 5, index, subIndex)">-</span>
  126 + </p>
  127 + </div>
  128 + <div class="qs-oprations" v-if="!isViewer">
  129 + <div class="qs-set">
  130 + <el-button class="icon-tickets" type="text"
  131 + @click="openStem(subQuestion, 1, index, subIndex)">修改题干</el-button>
  132 + </div>
  133 + <div class="qs-set">
  134 + <el-button class="icon-tickets" type="text"
  135 + @click="openStem(subQuestion, 2, index, subIndex)">修改解析</el-button>
  136 + </div>
  137 + <div class="qs-set" v-if="false">
  138 + <el-button type="text" @click="openKnowledge(subQuestion, index, subIndex)">修改知识点</el-button>
  139 + </div>
  140 + <div class="qs-set" style="margin-left:10px">
  141 + <el-popconfirm @confirm="_deleteDetermineQ(subIndex, index)" title="这是一小题确定删除吗?">
  142 + <!-- <el-button style="color:red" type="text" slot="reference">删除</el-button> -->
  143 + </el-popconfirm>
  144 + </div>
  145 + </div>
64 146 </div>
65   - <div class="qs-options">
66   - <p v-if="subQuestion.questionType == 5">--</p>
67   - <p v-if="subQuestion.questionType == 4" class="answer-box">
68   - <span class="answer-s" :class="subQuestion.correctAnswer == 1 ? 'answer-active' : ''
69   - " @click="subQuestion.correctAnswer = 1">✓</span>
70   - <span class="answer-s" :class="subQuestion.correctAnswer == 2 ? 'answer-active' : ''
71   - " @click="subQuestion.correctAnswer = 2">✗</span>
72   - </p>
73   - <p v-if="subQuestion.questionType == 3" class="answer-box">
74   - <template v-for="option in subQuestion.answerOptions.split(',')">
75   - <span v-if="option" class="answer-s" :class="subQuestion.correctAnswer.includes(option)
  147 + <div v-if="!question.subQuestions" class="courseware-content sub-questions">
  148 + <div class="qs-num">{{ question.questionId }}</div>
  149 + <div class="qs-stem">
  150 + <iframe style="height: 100% !important" class="screenshot" :src="question.screenshot"></iframe>
  151 + </div>
  152 + <div class="qs-type">
  153 + <el-select v-model="question.questionType">
  154 + <el-option :disabled="isViewer" v-for="item in questionOption" :key="item.Key"
  155 + :label="item.Text" :value="item.Key" />
  156 + </el-select>
  157 + </div>
  158 + <div class="qs-score">
  159 + <el-input-number :disabled="isViewer" class="number-ipt" size="medium" :min="1" :max="200"
  160 + :precision="2" :step="1" v-model="question.score" label="单题分值" />
  161 + </div>
  162 + <div class="qs-partScore">
  163 + <p v-if="question.questionType != 3">------</p>
  164 + <el-input-number class="number-ipt" v-else size="medium" :min="0" :precision="2"
  165 + :max="question.score" :step="0.5" v-model="question.partScore" label="漏选得分" />
  166 + </div>
  167 + <div class="qs-options">
  168 + <p v-if="question.questionType == 5">--</p>
  169 + <p v-if="question.questionType == 4" class="answer-box">
  170 + <span class="answer-s" :class="question.correctAnswer == 1 ? 'answer-active' : ''
  171 + " @click="question.correctAnswer = 1">✓</span>
  172 + <span class="answer-s" :class="question.correctAnswer == 2 ? 'answer-active' : ''
  173 + " @click="question.correctAnswer = 2">✗</span>
  174 + </p>
  175 + <p v-if="question.questionType == 3" class="answer-box">
  176 + <template v-for="option in question.answerOptions.split(',')">
  177 + <span v-if="option" class="answer-s" :class="question.correctAnswer.includes(option)
76 178 ? 'answer-active'
77 179 : ''
78   - " :key="option" @click="changAnswer(subQuestion, option)">{{ option }}</span>
79   - </template>
80   - <span class="answer-s answer-opration" @click="openStem(subQuestion, 4, index, subIndex)">+</span>
81   - <span class="answer-s answer-opration" @click="openStem(subQuestion, 4, index, subIndex)">-</span>
82   - </p>
83   - <p v-if="subQuestion.questionType == 2" class="answer-box">
84   - <template v-for="option in subQuestion.answerOptions.split(',')">
85   - <span class="answer-s" v-if="option" :class="subQuestion.correctAnswer == option
  180 + " :key="option" @click="changAnswer(question, option)">{{ option }}</span>
  181 + </template>
  182 + <span class="answer-s answer-opration" v-if="!isViewer"
  183 + @click="openStem(question, 4, index, 0)">+</span>
  184 + <span class="answer-s answer-opration" v-if="!isViewer"
  185 + @click="openStem(question, 4, index, 0)">-</span>
  186 + </p>
  187 + <p v-if="question.questionType == 2" class="answer-box">
  188 + <template v-for="option in question.answerOptions.split(',')">
  189 + <span class="answer-s" v-if="option" :class="question.correctAnswer == option
86 190 ? 'answer-active'
87 191 : ''
88   - " :key="option" @click="subQuestion.correctAnswer = option">{{ option }}</span>
89   - </template>
90   - <span class="answer-s answer-opration" @click="openStem(subQuestion, 4, index, subIndex)">+</span>
91   - <span class="answer-s answer-opration" @click="openStem(subQuestion, 5, index, subIndex)">-</span>
92   - </p>
93   - </div>
94   - <div class="qs-oprations">
95   - <div class="qs-set">
96   - <el-button class="icon-tickets" type="text" circle size="mini"
97   - @click="openStem(subQuestion, 1, index, subIndex)">修改题干</el-button>
98   - </div>
99   - <div class="qs-set">
100   - <el-button class="icon-tickets" type="text" circle size="mini"
101   - @click="openStem(subQuestion, 2, index, subIndex)">修改解析</el-button>
  192 + " :key="option" @click="question.correctAnswer = option">{{ option }}</span>
  193 + </template>
  194 + <span class="answer-s answer-opration" v-if="!isViewer"
  195 + @click="openStem(question, 4, index, 0)">+</span>
  196 + <span class="answer-s answer-opration" v-if="!isViewer"
  197 + @click="openStem(question, 5, index, 0)">-</span>
  198 + </p>
102 199 </div>
103   - <div class="qs-set">
104   - <el-button type="text" circle size="mini"
105   - @click="openKnowledge(subQuestion, index, subIndex)">修改知识点</el-button>
106   - </div>
107   - <div class="qs-set">
108   - <el-button type="text" circle size="mini"
109   - @click="openStem(subQuestion, 3, index, subIndex)">删除</el-button>
  200 + <div class="qs-oprations">
  201 + <div class="qs-set">
  202 + <el-button class="icon-tickets" type="text"
  203 + @click="openStem(question, 1, index, 0)">修改题干</el-button>
  204 + </div>
  205 + <div class="qs-set">
  206 + <el-button class="icon-tickets" type="text"
  207 + @click="openStem(question, 2, index, 0)">修改解析</el-button>
  208 + </div>
  209 + <div class="qs-set" v-if="false">
  210 + <el-button type="text" @click="openKnowledge(question, index, 0)">修改知识点</el-button>
  211 + </div>
  212 + <div class="qs-set" style="margin-left:10px">
  213 + <el-popconfirm @confirm="_deleteDetermineQ(0, index)" title="这是一小题确定删除吗?">
  214 + <!-- <el-button style="color:red" type="text" slot="reference">删除</el-button> -->
  215 + </el-popconfirm>
  216 + </div>
110 217 </div>
111 218 </div>
112 219 </div>
113 220 </div>
114 221 </div>
115 222 </div>
116   - <div v-if="paperType == 2">
117   - <div class="paper"></div>
118   - </div>
119 223 </div>
120   - <el-dialog :close-on-click-modal="false" title="选择班级分享" :visible.sync="classSharingType" width="400"
  224 + <el-dialog :close-on-click-modal="false" title="选择班级分享" :visible.sync="classSharingType" width="800"
121 225 :modal-append-to-body="false" :append-to-body="true">
122 226 <div>
123 227 <el-row class="row-subfix">
... ... @@ -126,23 +230,26 @@
126 230 <span class="line-value">{{ gradeName }}</span>
127 231 </div>
128 232 </el-row>
129   - <el-row class="row-subfix">
  233 + <el-row class="row-subfix" style="margin-top: 20px;">
130 234 <span class="line-subfix" style="float: left;">班级:</span>
131   - <div class="row-line" style="float: left;">
132   - <span class="line-value" style=" border-radius: 4px; background: rgb(247,247,250);">
  235 + <div class="row-line" style="float: left;
  236 + background:rgb(245,247,250);padding:15px 10px;width: calc(100% - 80px);border-radius:5px;">
  237 + <span class="line-value" style="min-height: 300px;border-radius: 4px; background: rgb(247,247,250);">
133 238 <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
134 239 @change="handleCheckAllChange">全选</el-checkbox>
135   - <el-checkbox-group v-model="checkedClass" @change="handleCheckedClassChange">
136   - <el-checkbox v-for="(item, index) in gradeClass" :label="item.id" :key="item.id">{{
137   - item.className }}</el-checkbox>
  240 + <el-checkbox-group v-model="checkedClass" style="margin-top: 15px;"
  241 + @change="handleCheckedClassChange">
  242 + <el-checkbox v-for="(item, index) in gradeClass" :label="item.id" :key="item.id">
  243 + {{ item.className }}
  244 + </el-checkbox>
138 245 </el-checkbox-group>
139 246 </span>
140 247 </div>
141 248 </el-row>
142   - <el-row class="row-subfix" style="float:right;margin-right: 20px;">
143   - <el-button type="danger" @click="() => { classSharingType == false }">取消</el-button>
144   - <el-button type="primary" @click="_checkedClass">确定</el-button>
145   - </el-row>
  249 + </div>
  250 + <div slot="footer">
  251 + <el-button type="info" :size="'small'" @click="classSharingType = false">取消</el-button>
  252 + <el-button type="primary" :size="'small'" @click="_checkedClass">确定</el-button>
146 253 </div>
147 254 </el-dialog>
148 255 <el-dialog :close-on-click-modal="false" title="批量设置答案" :visible.sync="diaSetAns" width="400"
... ... @@ -215,8 +322,8 @@
215 322 <el-button @click="dialogStem = false">确定</el-button>
216 323 </div>
217 324 </el-dialog>
218   - <el-dialog :append-to-body="true" :close-on-click-modal="false" title="知识点" :visible.sync="dialogKnowledge" width="500px"
219   - :append-to-body="true">
  325 + <el-dialog :append-to-body="true" :close-on-click-modal="false" title="知识点" :visible.sync="dialogKnowledge"
  326 + width="500px">
220 327 <div>
221 328 <el-form ref="form" :model="stem" label-width="160px">
222 329 <el-form-item label="知识点:">
... ... @@ -236,8 +343,8 @@
236 343 </el-dialog>
237 344 </div>
238 345 <div class="content-fi">
239   - <el-button type="danger" @click="linkBack">取消</el-button>
240   - <el-button type="primary" @click="save">保存</el-button>
  346 + <el-button type="info" @click="linkBack">取消</el-button>
  347 + <el-button class="green-el-button" @click="save">保存</el-button>
241 348 </div>
242 349 </el-main>
243 350 </el-container>
... ... @@ -251,10 +358,13 @@ export default {
251 358 return {
252 359 role: "",
253 360 title: "",
  361 + classSharingType: false,
254 362 gradeName: "",
255 363 checkAll: false,
256 364 checkedClass: [],
257 365 gradeClass: [],
  366 + subjectName: "",
  367 + isViewer: false,
258 368 isIndeterminate: true,
259 369 type: 1, //1:答题卡 2:即时测报表题目列表 3:课时题目列表
260 370 questionList: [],
... ... @@ -362,8 +472,10 @@ export default {
362 472 this.type = this.$route.query.type || 1;
363 473 this.examType = this.$route.query.examType || 2;
364 474 this.paperType = this.$route.query.paperType || 2;
  475 + this.isViewer = this.$route.query.isViewer || false;
365 476 this.classId = this.$route.query.classId || -1;
366 477 this.gradeName = this.$route.query.gradeName || "";
  478 + this.subjectName = this.$route.query.subjectName || "";
367 479 this.form.title = this.$route.query.title || "";
368 480 this._QueryDetail();
369 481 this._GradeList();
... ... @@ -373,7 +485,7 @@ export default {
373 485 this.classSharingType = false;
374 486 },
375 487 handleCheckAllChange(val) {
376   - this.checkedClass = val ? this.gradeClass : [];
  488 + this.checkedClass = val ? this.gradeClass?.map(item => item.id) : [];
377 489 this.isIndeterminate = false;
378 490 },
379 491 handleCheckedClassChange(value) {
... ... @@ -382,13 +494,21 @@ export default {
382 494 this.isIndeterminate = checkedCount > 0 && checkedCount < this.checkedClass.length;
383 495 },
384 496 async _selectClassSharingType() {
  497 +
  498 + if (this.isViewer) return;
  499 +
  500 + this.gradeClass = [];
  501 +
385 502 this.classSharingType = true;
386   - var classResponse = await this.$request.tClassFromGrade(this.classId);
  503 +
  504 + var classResponse = await this.$request.tClassFromGrade(this.classId, this.form.subjectName);
387 505  
388 506 if (classResponse.status != 0) {
389 507 this.$message.error(classResponse.info);
390 508 }
391   - this.gradeClass = classResponse.data;
  509 +
  510 + this.gradeClass = [...classResponse.data];
  511 +
392 512 },
393 513 // v1.5
394 514 //上传截图
... ... @@ -403,7 +523,7 @@ export default {
403 523 }
404 524 this.stem.screenshot = obj.screenshot || "";
405 525 this.stem.answerScreenshot = "";
406   - return;
  526 + // return;
407 527 } else if (type == 3) {
408 528 } else if (type == 4) {
409 529 var current = this.questionList[index].subQuestions[indexs];
... ... @@ -516,6 +636,16 @@ export default {
516 636 }
517 637 return tit;
518 638 },
  639 + _deleteDetermineQ(subIndex, index) {
  640 + if (this.questionList[index].subQuestions) {
  641 + this.questionList[index].subQuestions.splice(subIndex, 1);
  642 + if (this.questionList[index].subQuestions?.length == 0) {
  643 + this.questionList.splice(index, 1);
  644 + }
  645 + } else {
  646 + this.questionList.splice(index, 1);
  647 + }
  648 + },
519 649 setBigNum(num) {
520 650 let txt = "";
521 651 let bigNum = [
... ... @@ -759,7 +889,6 @@ export default {
759 889 });
760 890 //更新答题卡
761 891 let modifyPaper, params;
762   - console.log(this.type)
763 892 if (this.type == 1) {
764 893 modifyPaper =
765 894 this.role == "ROLE_PERSONAL"
... ... @@ -796,7 +925,16 @@ export default {
796 925 ...params,
797 926 });
798 927 if (status == 0) {
799   - this.$router.go(-1);
  928 + if (this.paperType == 1) {
  929 + this.$router.push({
  930 + path: "/askPreparationQuestions",
  931 + });
  932 + }
  933 + else {
  934 + this.$router.push({
  935 + path: "/testPaper",
  936 + });
  937 + }
800 938 } else {
801 939 this.$message.error(message);
802 940 }
... ... @@ -837,7 +975,7 @@ export default {
837 975 ...this.form.paperModifyLog,
838 976 };
839 977 this.form = deepClone(data);
840   - console.log(this.form.sharingType)
  978 +
841 979 questionList = this.form.questionList.map((item) => {
842 980 if (item.subQuestions) {
843 981 item.subQuestions.map((subQuestion) => {
... ... @@ -855,13 +993,17 @@ export default {
855 993 }
856 994 return item;
857 995 });
  996 +
  997 +
858 998 } else {
859 999 questionList = data.list.sort((a, b) => {
860 1000 return a.questionIndex - b.questionIndex;
861 1001 });
862 1002 }
863 1003 this.questionList = questionList;
  1004 + console.log(this.questionList)
864 1005 this.formateQuestion();
  1006 + this.checkedClass = data.classList?.map(item => item.classId);
865 1007 } else {
866 1008 this.$message.error(info);
867 1009 }
... ... @@ -997,7 +1139,22 @@ export default {
997 1139 },
998 1140 };
999 1141 </script>
1000   -<style>
  1142 +<style lang="scss">
  1143 +.line-value {
  1144 + color: black;
  1145 +}
  1146 +
  1147 +.question-contents {
  1148 +
  1149 + .el-input__inner,
  1150 + .el-input,
  1151 + .el-select,
  1152 + .el-input-number__decrease,
  1153 + .el-input-number__increase {
  1154 + background: white !important;
  1155 + }
  1156 +}
  1157 +
1001 1158 .screenshot-box {
1002 1159 width: 600px;
1003 1160 }
... ... @@ -1019,7 +1176,7 @@ export default {
1019 1176 </style>
1020 1177 <style lang="scss" scoped>
1021 1178 .content-fi {
1022   - padding-top: 7px;
  1179 + padding-top: 12px;
1023 1180 width: 200px;
1024 1181 margin: 0px auto;
1025 1182 }
... ... @@ -1308,4 +1465,17 @@ export default {
1308 1465 .row-subfix {
1309 1466 margin-bottom: 10px;
1310 1467 }
  1468 +
  1469 +.bigQuestion {
  1470 + padding: 20px;
  1471 + box-shadow: 0px 1px 4px 0px rgba(21, 34, 50, 0.08);
  1472 + border: 1px solid #ebeef5;
  1473 + border-radius: 5px;
  1474 + margin-top: 10px;
  1475 +
  1476 + .bigQuestionTitle {
  1477 + font-size: 16px;
  1478 + font-weight: bold;
  1479 + }
  1480 +}
1311 1481 </style>
... ...
src/views/basic/card/index.vue
... ... @@ -36,11 +36,11 @@
36 36 <el-option label="换班" :value="2"></el-option>
37 37 </el-select>
38 38 <div class="d1">
39   - <el-date-picker v-model="query.startDay" type="date" @change="handleChangeTimeStart" placeholder="选择日期时间"
  39 + <el-date-picker style="width: 40%;" v-model="query.startDay" type="date" @change="handleChangeTimeStart" placeholder="选择日期时间"
40 40 value-format="yyyy-MM-dd">
41 41 </el-date-picker>
42 42 ~
43   - <el-date-picker v-model="query.endDay" type="date" placeholder="选择日期时间" @change="handleChangeTimeEnd"
  43 + <el-date-picker style="width: 40%;" v-model="query.endDay" type="date" placeholder="选择日期时间" @change="handleChangeTimeEnd"
44 44 value-format="yyyy-MM-dd">
45 45 </el-date-picker>
46 46 </div>
... ...
src/views/basic/dataSync/index.vue
... ... @@ -162,7 +162,7 @@ export default {
162 162 justify-content: center;
163 163  
164 164 .down-item {
165   - width: 400px;
  165 + width: 450px;
166 166 height: 330px;
167 167 border-radius: 20px;
168 168 margin: 20px;
... ...
src/views/basic/device/index.vue
... ... @@ -1457,7 +1457,7 @@ export default {
1457 1457 align-items: center;
1458 1458  
1459 1459 .p1 {
1460   - font-size: 28px;
  1460 + font-size: 28px !important;
1461 1461 }
1462 1462 }
1463 1463  
... ... @@ -1473,7 +1473,7 @@ export default {
1473 1473 .loading {
1474 1474 text-align: center;
1475 1475 line-height: 36px;
1476   - font-size: 16px;
  1476 + font-size: 16px !important;
1477 1477 color: #666;
1478 1478 }
1479 1479  
... ...
src/views/basic/down/index.vue
... ... @@ -31,8 +31,7 @@
31 31 <el-button plan round @click="downCard">发卡软件下载</el-button>
32 32 </div>
33 33 <div class="down-item" v-loading="loading">
34   - <p class="txt">
35   - 电脑缺少.NET Framework环境时,请下载安装.NET Framework
  34 + <p class="txt">电脑缺少.NET Framework环境时,请下载安装.NET Framework
36 35 4.5.2,以便于授课端可正常使用。
37 36 </p>
38 37 <el-button plan round @click="downNet">.Net环境下载</el-button>
... ... @@ -140,7 +139,7 @@ export default {
140 139 margin-left: 160px;
141 140  
142 141 .down-item {
143   - width: 200px;
  142 + width: 300px;
144 143 padding: 50px 20px;
145 144 border-radius: 20px;
146 145 margin: 20px;
... ... @@ -149,8 +148,7 @@ export default {
149 148 justify-content: center;
150 149 align-items: center;
151 150 background: #f8f8f8;
152   - box-shadow: 2px 2px 5px #ccc;
153   -
  151 + box-shadow: 2px 2px 5px #ccc;
154 152 .txt {
155 153 font-size: 16px;
156 154 color: #7f7f7f;
... ...
src/views/basic/setUp/archived.vue
... ... @@ -7,90 +7,108 @@
7 7 </back-box>
8 8 <div class="page-content">
9 9 <el-steps :active="step" align-center class="step">
10   - <el-step title="1 班级归档"></el-step>
11   - <el-step title="2 分班后学生名单"></el-step>
  10 + <el-step title="1 解散班级"></el-step>
  11 + <el-step title="2 导入班级名单"></el-step>
12 12 <el-step title="3 分班后任课老师"></el-step>
13   - <el-step title="4 授课端指引"></el-step>
14 13 </el-steps>
15 14 <ul v-loading="loading">
16   - <li v-show="step == 0">
17   - <div class="form-item">
18   - <span class="s-txt">选择分班年级:</span>
19   - <el-select class="sel" v-model="grade" placeholder="选择年级" @change="changeGrade">
20   - <el-option v-for="item in gradeList" :key="item.value" :label="item.label" :value="item.value">
21   - </el-option>
22   - </el-select>
23   - </div>
24   - <div class="form-item">
25   - <span class="s-txt">确定班级:</span>
26   - <i class="el-icon-loading" v-show="loadingClass"></i>
27   - <div class="check-box" v-if="classList.length && !loadingClass">
28   - <!-- <p class="all-check">
29   - <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
30   - @change="handleCheckAllChange">全选</el-checkbox>
31   - </p> -->
32   - <el-checkbox-group v-model="classIds" @change="handleCheckedChange">
33   - <el-checkbox disabled v-for="item in classList" :key="item.id" :label="item.id">{{
34   - item.className
35   - }}</el-checkbox>
36   - </el-checkbox-group>
  15 + <li v-show="step == 0" style="padding:0px 200px;">
  16 + <el-row class="row-subfix" style="margin-top: 20px;">
  17 + <el-row class="row-subfix">
  18 + <div class="row-line">
  19 + <span class="line-subfix">选择年级:</span>
  20 + <span class="line-value">
  21 + <el-select class="sel" v-model="grade" placeholder="选择年级" @change="changeGrade">
  22 + <el-option v-for="item in gradeList" :key="item.value" :label="item.label" :value="item.value">
  23 + </el-option>
  24 + </el-select>
  25 + </span>
  26 + </div>
  27 + </el-row>
  28 + <el-row class="row-subfix" style="margin-top: 20px;">
  29 + <span class="line-subfix" style="float: left;">选择班级:</span>
  30 + <div class="row-line"
  31 + style="float: left; background:rgb(245,247,250);padding:15px;width: calc(100% - 220px); border-radius:5px;">
  32 + <span class="line-value" style="min-height: 300px;border-radius: 4px; background: rgb(247,247,250);">
  33 + <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
  34 + @change="handleCheckAllChange">全选</el-checkbox>
  35 + <el-checkbox-group v-model="checkedClass" style="margin-top: 15px;">
  36 + <el-checkbox v-for="(item, index) in classList" :label="item.id" :key="item.id">
  37 + {{ item.className }}
  38 + </el-checkbox>
  39 + </el-checkbox-group>
  40 + </span>
  41 + </div>
  42 + </el-row>
  43 + </el-row>
  44 + <el-row class="row-subfix form-item" style="margin-top: 20px;">
  45 + <span class="line-subfix" style="float: left;"> <i class="el-icon-warning" /></span>
  46 + <div class="row-line" style="float: left; width: calc(100% - 220px); border-radius:5px;">
  47 + <div>请谨慎操作,班级归档后,学生解除班级关系且相关老师任课信息将不存在。</div>
  48 + <div style="margin-top: 10px;opacity: 0.7;">如需保存解散前的班级名单与任课信息,可点击“保存名单”按钮。</div>
37 49 </div>
38   - </div>
39   - <div class="form-item">
40   - <span class="s-txt"></span>
41   - <p class="tips">
42   - <i class="el-icon-warning"></i>请谨慎操作,班级归档后,学生解除班级关系且相关老师任课信息将不存在。
43   - </p>
44   - </div>
45   - <div class="btn-box">
46   - <el-button class="btn" round @click="toClazz">取消</el-button>
47   - <el-popconfirm confirm-button-text="确定" cancel-button-text="取消" icon="el-icon-info" icon-color="red"
48   - title="确定要将所选班级归档吗?" @confirm="_ClassArchiving">
49   - <el-button class="btn" slot="reference" type="primary" round>归档</el-button>
  50 + </el-row>
  51 + <div style="margin:0px auto;width: 30%;">
  52 + <el-button style="background: rgb(218,225,235) ;color:black;border:none !important;"
  53 + @click="toClazz">取消</el-button>
  54 + <el-button type="primary" @click="_downNameList">保存名单</el-button>
  55 + <el-popconfirm confirm-button-text="确定" cancel-button-text="取消" title="确定要将所选班级解散吗吗?"
  56 + @confirm="_ClassArchiving">
  57 + <el-button slot="reference" v-loading="loadingDown"
  58 + style="background: rgb(242,168,65) ;color:white;margin-left: 10px;border:none !important;">确定解散</el-button>
50 59 </el-popconfirm>
51 60 </div>
52 61 </li>
53 62 <li v-show="step == 1">
54   - <div class="step-item">
55   - <upload id="downTeacher" :url="urlClazz" @upSuccess="upStudentSuccess" fileName="学生名单模板">
  63 + <el-row class="row-subfix form-item">
  64 + <div class="row-line" style="float: left;">
  65 + <div>通过导入EXCEL文件方式添加班级名单,请按需求下载对应班级类型板并填写班级名单信息后,导入系统:</div>
  66 + <div style="margin-top: 10px;opacity: 0.7;margin-left:20px;">
  67 + 行政班定义:由固定学生、固定教室构成,由专门的班主任进行管理;
  68 + </div>
  69 + <div style="margin-top: 5px;opacity: 0.7;margin-left:20px;">
  70 + 教学班定义:由不同行政班的学生临时组成,没有专门的班主任,是在选课制基础上,由于教学的需要而产生的。
  71 + </div>
  72 + </div>
  73 + </el-row>
  74 + <el-row class="row-subfix form-item" style="margin-top: 20px;">
  75 + <el-button :icon="'el-icon-document'" @click="_downTemplate(0)">下载行政班名单模板</el-button>
  76 + <el-button :icon="'el-icon-document'" @click="_downTemplate(1)">下载教学班名单模板</el-button>
  77 + </el-row>
  78 + <el-row class="row-subfix form-item" style="margin-top: 20px;">
  79 + <upload id="downTeacher" drag :url="urlClazz"
  80 + style="border:rgb(219,226,235) dashed 1px;width: 100%;padding:40px 0px;border-radius: 5px;"
  81 + @upSuccess="upStudentSuccess" fileName="学生名单模板">
56 82 <p class="down-txt" slot="down">
57   - 通过Excel名单导入学生名单模板,点击
58   - <el-link type="primary" @click="downStudentExcel">导出未分配学生</el-link>
59   - 。
  83 + 通过Excel名单导入学生名单模板
60 84 </p>
61 85 </upload>
62   - </div>
  86 + </el-row>
63 87 </li>
64 88 <li v-show="step == 2">
65   - <div class="step-item">
66   - <upload id="downTeacher" :url="urlTeacher" @upSuccess="upTeacherSuccess" fileName="任课老师名单模板">
  89 + <el-row class="row-subfix form-item">
  90 + <div class="row-line" style="float: left;">
  91 + <div>通过导入EXCEL文件方式添加教师任课信息,请按需求下载板并填写任课信息后,导入系统:</div>
  92 + </div>
  93 + </el-row>
  94 + <el-row class="row-subfix form-item" style="margin-top: 20px;">
  95 + <el-button :icon="'el-icon-document'" @click="_downTemplate(2)">下载任课信息模板</el-button>
  96 + </el-row>
  97 + <el-row class="row-subfix form-item" style="margin-top: 20px;">
  98 + <upload id="downTeacher" drag :url="urlTeacher"
  99 + style="border:rgb(219,226,235) dashed 1px;width: 100%;padding:40px 0px;border-radius: 5px;"
  100 + @upSuccess="upTeacherSuccess" fileName="任课老师名单模板">
67 101 <p class="down-txt" slot="down">
68   - 通过Excel名单导入任课老师名单模板,点击
69   - <el-link type="primary" @click="downTeacherExcel">导出未分配教师</el-link>。
  102 + 通过Excel名单导入任课老师名单模板
70 103 </p>
71 104 </upload>
72   - </div>
73   - </li>
74   - <li v-show="step == 3">
75   - <div class="step-item2">
76   - <p class="p2">
77   - <el-button class="btn" type="success" icon="el-icon-check" circle
78   - size="small"></el-button>恭喜您,分班已经完成,分班后老师第一次上课时注意事项:
79   - </p>
80   - <p class="p1">
81   - 1、点击授课端的设置—应用设置—初始化设置—重新选择绑定班级。
82   - </p>
83   - <p class="p1">
84   - 2、点击授课端的设置—班级名册—基站登录—学生完成基站绑定。
85   - </p>
86   - </div>
  105 + </el-row>
87 106 </li>
88   -
89 107 <li v-show="step != 0">
90 108 <div class="btn-box">
91 109 <el-button class="btn" round @click="step -= 1">上一步</el-button>
92   - <el-button v-show="step != 3" class="btn" type="primary" round @click="step += 1">下一步</el-button><el-button
93   - v-show="step == 3" class="btn" type="primary" round @click="toClazz">完成</el-button>
  110 + <el-button v-show="step != 2" class="btn" type="primary" round @click="step += 1">下一步</el-button><el-button
  111 + v-show="step == 2" class="btn" type="primary" round @click="toClazz">完成</el-button>
94 112 </div>
95 113 </li>
96 114 </ul>
... ... @@ -109,31 +127,67 @@ export default {
109 127 step: 0,
110 128 grade: "",
111 129 gradeList: [],
112   - classIds: [],
  130 + checkAll: false,
  131 + checkedClass: [],
113 132 classList: [],
114 133 urlClazz: "/api_html/school/manager/importClassAndStudent",
115 134 urlTeacher: "/api_html/school/manager/importTeacher",
116   - checkAll: true,
117   - isIndeterminate: false,
  135 + isIndeterminate: true
118 136 };
119 137 },
  138 + watch: {
  139 + checkedClass(value) {
  140 + this.checkAll = value.length == this.classList.length;
  141 + this.isIndeterminate = value.length > 0 && value.length < this.classList.length;
  142 + }
  143 + },
120 144 created() {
121 145 this._QueryDataGrade();
122 146 },
123 147 methods: {
  148 + async _downNameList() {
  149 + this.loadingDown = true;
  150 + await this.downStudentExcel();
  151 + await this.downTeacherExcel();
  152 + this.loadingDown = false;
  153 + },
124 154 handleCheckAllChange(val) {
125   - this.classIds = val
126   - ? this.classList.map((item) => {
127   - return item.id;
128   - })
129   - : [];
130   - this.isIndeterminate = false;
  155 + if (val) this.checkedClass = this.classList.map(item => item.id);
  156 + else this.checkedClass = [];
131 157 },
132   - handleCheckedChange(value) {
133   - let checkedCount = value.length;
134   - this.checkAll = checkedCount === this.classList.length;
135   - this.isIndeterminate =
136   - checkedCount > 0 && checkedCount < this.classList.length;
  158 + async _downTemplate(type) {
  159 +
  160 + var template = type == 0 ? this.$request.classAndStudentTemplate : this.$request.tClassAndStudentTemplate;
  161 +
  162 + if (type == 2) template = await this.$request.teacherTemplate;
  163 + console.log(type)
  164 + let data = await template();
  165 +
  166 + if (data && !data.code) {
  167 +
  168 + let blob = new Blob([data], {
  169 + type: "application/vnd.ms-excel;charset=utf-8",
  170 + });
  171 +
  172 + downloadFile(type == 2 ? "教师任课信息" : type == 0 ? "行政班名单模板" : "教学班名单模板", blob);
  173 + }
  174 + else {
  175 + this.$message.error(data.info);
  176 + }
  177 + // const classAndStudentTemplate =
  178 + // type == 0
  179 + // ? this.$request.classAndStudentTemplate ? type == 2 :
  180 + // await this.$request.teacherTemplate()
  181 + // : this.$request.tClassAndStudentTemplate;
  182 + // let data = await classAndStudentTemplate();
  183 + // if (data && !data.code) {
  184 + // let blob = new Blob([data], {
  185 + // type: "application/vnd.ms-excel;charset=utf-8",
  186 + // });
  187 + // downloadFile(type == 0 ? type == 2 ? "教师任课信息模板" : "行政班名单模板" : "教学班名单模板", blob);
  188 + // } else {
  189 + // this.$message.error(data.info);
  190 + // }
137 191 },
138 192 toClazz() {
139 193 this.$router.push({
... ... @@ -166,41 +220,53 @@ export default {
166 220 },
167 221 //导出学生名单
168 222 async downStudentExcel() {
169   - this.loadingDown = true;
170   - let data = await this.$request.exportNoClassStudent();
171   - this.loadingDown = false;
  223 +
  224 + const exportClassAndStudent = this.$request.exportClassAndStudent;
  225 +
  226 + let data = await exportClassAndStudent();
  227 +
172 228 if (data) {
173 229 let blob = new Blob([data], {
174   - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  230 + type: "application/vnd.ms-excel;charset=utf-8",
175 231 });
176   - downloadFile("未分配学生名单.xlsx", blob);
  232 + downloadFile(`班级名单.xlsx`, blob);
177 233 } else {
178 234 this.$message.error("下载失败");
179 235 }
180 236 },
181 237 //导出任课老师名单
182 238 async downTeacherExcel() {
183   - this.loadingDown = true;
184   - let data = await this.$request.exportNoClassTeacher();
185   - this.loadingDown = false;
  239 +
  240 + let data = await this.$request.exportTeacher();
  241 +
186 242 if (data) {
187 243 let blob = new Blob([data], {
188   - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  244 + type: "application/vnd.ms-excel;charset=utf-8",
189 245 });
190   - downloadFile("未分配教师 名单.xlsx", blob);
  246 + downloadFile(`教师名单.xlsx`, blob);
191 247 } else {
192 248 this.$message.error("下载失败");
193 249 }
  250 + // let data = await this.$request.exportNoClassTeacher();
  251 +
  252 + // if (data) {
  253 + // let blob = new Blob([data], {
  254 + // type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  255 + // });
  256 + // downloadFile("未分配教师 名单.xlsx", blob);
  257 + // } else {
  258 + // this.$message.error("下载失败");
  259 + // }
194 260 },
195 261 //班级归档
196 262 async _ClassArchiving() {
197   - if (!this.classIds.length) {
  263 + if (!this.checkedClass.length) {
198 264 this.$message.warning("班级不能为空,请选择班级~");
199 265 return;
200 266 }
201 267 this.loading = true;
202 268 const { status, info } = await this.$request.classArchiving({
203   - classIds: [...this.classIds],
  269 + classIds: [...this.checkedClass],
204 270 });
205 271 this.loading = false;
206 272 if (status === 0) {
... ... @@ -234,14 +300,12 @@ export default {
234 300 this.loadingClass = true;
235 301 const { data, status, info } = await this.$request.schoolClassList({
236 302 grade: this.grade,
  303 + type: 0
237 304 });
238 305 this.loadingClass = false;
239 306 if (status === 0) {
240 307 this.classList = (data.list && [...data.list]) || [];
241   - this.classIds = this.classList.map((item) => {
242   - return item.id;
243   - });
244   - this.checkAll = true;
  308 + this.checkedClass = this.classList.map(item => item.id);
245 309 } else {
246 310 this.$message.error(info);
247 311 }
... ...
src/views/basic/setUp/clazz.vue
... ... @@ -6,37 +6,14 @@
6 6 </template>
7 7 <template slot="btns" v-if="!code">
8 8 <el-tooltip effect="dark" content="导入班级名单" placement="bottom">
9   - <el-button
10   - type="primary"
11   - icon="el-icon-upload2"
12   - size="mini"
13   - plain
14   - circle
15   - @click="diaUp = true"
16   - ></el-button>
  9 + <el-button type="primary" icon="el-icon-upload2" size="mini" plain circle @click="diaUp = true"></el-button>
17 10 </el-tooltip>
18 11 <el-tooltip effect="dark" content="导出班级名单" placement="bottom">
19   - <el-button
20   - type="primary"
21   - icon="el-icon-download"
22   - size="mini"
23   - plain
24   - circle
25   - @click="exportTeacherExl"
26   - ></el-button>
  12 + <el-button type="primary" icon="el-icon-download" size="mini" plain circle
  13 + @click="exportTeacherExl"></el-button>
27 14 </el-tooltip>
28   - <el-tooltip
29   - effect="dark"
30   - content="分班"
31   - placement="bottom"
32   - v-show="type == 0"
33   - >
34   - <img
35   - @click="toArchived"
36   - src="../../../assets/images/fenban.png"
37   - class="fenban"
38   - alt=""
39   - />
  15 + <el-tooltip effect="dark" content="分班" placement="bottom" v-show="type == 0">
  16 + <img @click="toArchived" src="../../../assets/images/fenban.png" class="fenban" alt="" />
40 17 </el-tooltip>
41 18 </template>
42 19 </back-box>
... ... @@ -45,42 +22,23 @@
45 22 <p class="tab-box">
46 23 <el-radio-group v-model="type" @change="_QueryData">
47 24 <el-radio-button :label="0">行政班</el-radio-button>
48   - <el-radio-button :label="1">教学班</el-radio-button>
  25 + <el-radio-button v-if="hasTeachingClass" :label="1">教学班</el-radio-button>
49 26 </el-radio-group>
50 27 </p>
51 28 <div class="grade-item" v-for="(item, index) in dataList">
52 29 <p class="h-title">
53 30 <span>{{ item.gradeName }}</span>
54   - <span class="s-num" v-if="item.classList"
55   - >(共{{ item.classList.length }}个班)</span
56   - >
57   - <el-button
58   - class="sub-btn"
59   - type="info"
60   - size="mini"
61   - round
62   - plain
63   - @click="openSubject(item)"
64   - >科目管理({{ item.subjectNames.length }})</el-button
65   - >
  31 + <span class="s-num" v-if="item.classList">(共{{ item.classList.length }}个班)</span>
  32 + <el-button class="sub-btn" type="info" size="mini" round plain @click="openSubject(item)">科目管理({{
  33 + item.subjectNames.length }})</el-button>
66 34 <span class="txt" v-if="index == 0">拖动班级进行排序</span>
67 35 </p>
68   - <draggable
69   - tag="ul"
70   - class="grade-info"
71   - v-model="item.classList"
72   - @start="start"
73   - @end="end(item)"
74   - v-bind="{
75   - animation: 300,
76   - }"
77   - >
  36 + <draggable tag="ul" class="grade-info" v-model="item.classList" @start="start" @end="end(item)" v-bind="{
  37 + animation: 300,
  38 + }">
78 39 <li class="clazz-li" v-for="clazz in item.classList" :key="item.id">
79 40 <div class="clazz-item">
80   - <i
81   - class="el-icon-edit"
82   - @click.stop="setClass(clazz, item.gradeName)"
83   - ></i>
  41 + <i class="el-icon-edit" @click.stop="setClass(clazz, item.gradeName)"></i>
84 42 <p class="clazz-name ellipsis">
85 43 {{ clazz.className }}
86 44 </p>
... ... @@ -94,34 +52,48 @@
94 52 </div>
95 53 </div>
96 54 </div>
97   - <el-dialog :append-to-body="true"
98   - :close-on-click-modal="false"
99   - title="导入班级名单"
100   - :visible.sync="diaUp"
101   - width="600"
102   - >
103   - <upload :url="url" @upSuccess="upSuccess" fileName="班级名单">
104   - <p class="down-txt" slot="down">
105   - 通过Excel名单导入班级名单,点击
106   - <el-link type="danger" @click="downExcel">模板下载</el-link> 。
107   - </p>
108   - </upload>
  55 + <el-dialog :append-to-body="true" :close-on-click-modal="false" title="添加班级" width="70%" :visible.sync="diaUp">
  56 + <div style="width: 90%;margin:0px auto;">
  57 + <el-row class="row-subfix form-item">
  58 + <div class="row-line" style="float: left;color:black;">
  59 + <div>通过导入文件方式添加班级名单</div>
  60 + <div class="row-line" style="margin-top:10px">
  61 + <div style="float:left;">第一步:</div>
  62 + <div style="float:left;">
  63 + <div style="margin-bottom: 10px;">无需走班,请 <el-link type="primary"
  64 + @click="_downTemplate(0)">下载行政班模板名单;</el-link>
  65 + </div>
  66 + <div style="margin-bottom: 10px;">需要走班,请按需求
  67 + <el-link type="primary" @click="_downTemplate(0)">下载行政班模板名单;</el-link>或者
  68 + <el-link type="primary" @click="_downTemplate(1)">教学班名单模板</el-link>
  69 + </div>
  70 + <div style="margin-top: 10px;opacity: 0.7;margin-left:20px;">
  71 + 行政班定义:由固定学生、固定教室构成,由专门的班主任进行管理。
  72 + </div>
  73 + <div style="margin-top: 5px;opacity: 0.7;margin-left:20px;">
  74 + 教学班定义:由不同行政班的学生临时组成,没有专门的班主任,是在选课制基础上,由于教学的需要而产生的。
  75 + </div>
  76 + </div>
  77 + </div>
  78 + <div style="float:left;margin-top:10px">第二步:<span>上传完成编辑好的名单文件</span></div>
  79 + </div>
  80 + </el-row>
  81 + <el-row class="row-subfix form-item" style="margin-top: 20px;">
  82 + <upload id="downTeacher" drag :url="url"
  83 + style="border:rgb(219,226,235) dashed 1px;margin:0px auto;width: 80%;padding:40px 0px;border-radius: 5px;"
  84 + @upSuccess="upSuccess" fileName="班级名单">
  85 + <p class="down-txt" slot="down">
  86 + 通过Excel名单导入班级名单模板
  87 + </p>
  88 + </upload>
  89 + </el-row>
  90 + </div>
109 91 <div class="dialog-footer" slot="footer">
110 92 <el-button @click="diaUp = false">取 消</el-button>
111 93 </div>
112 94 </el-dialog>
113   - <el-dialog :append-to-body="true"
114   - :close-on-click-modal="false"
115   - title="修改班级"
116   - :visible.sync="diaClass"
117   - width="400"
118   - >
119   - <el-form
120   - ref="formClass"
121   - :model="formClass"
122   - :rules="rulesClass"
123   - label-width="160px"
124   - >
  95 + <el-dialog :append-to-body="true" :close-on-click-modal="false" title="修改班级" :visible.sync="diaClass" width="400">
  96 + <el-form ref="formClass" :model="formClass" :rules="rulesClass" label-width="160px">
125 97 <el-form-item label="所在年级:">
126 98 <span>{{ formClass.gradeName }}</span>
127 99 </el-form-item>
... ... @@ -140,20 +112,14 @@
140 112 </el-form-item>
141 113 <el-form-item label="入学年份:">
142 114 <el-col :span="10">
143   - <el-date-picker
144   - v-model="formClass.intoSchoolYear"
145   - type="year"
146   - placeholder="选择年"
147   - >
  115 + <el-date-picker v-model="formClass.intoSchoolYear" type="year" placeholder="选择年">
148 116 </el-date-picker>
149 117 </el-col>
150 118 </el-form-item>
151 119 </el-form>
152 120 <div class="dialog-footer" slot="footer">
153 121 <el-popconfirm title="确定删除该班级吗?" @confirm="_RemoveClass">
154   - <el-button class="el-button-del" slot="reference" type="danger"
155   - >删 除</el-button
156   - >
  122 + <el-button class="el-button-del" slot="reference" type="danger">删 除</el-button>
157 123 </el-popconfirm>
158 124 <el-button @click="_SaveClass" type="primary">确 定</el-button>
159 125 <el-button @click="diaClass = false">取 消</el-button>
... ... @@ -163,11 +129,7 @@
163 129 </el-popconfirm> -->
164 130 </div>
165 131 </el-dialog>
166   - <el-dialog :append-to-body="true"
167   - :close-on-click-modal="false"
168   - :visible.sync="diaSubject"
169   - width="400"
170   - >
  132 + <el-dialog :append-to-body="true" :close-on-click-modal="false" :visible.sync="diaSubject" width="400">
171 133 <p slot="title" class="dia-tit">
172 134 {{ formClass.gradeName }}
173 135 <span class="tips">(默认科目和已经有任课老师的科目不能删除)</span>
... ... @@ -176,54 +138,25 @@
176 138 <el-form-item label="科目:">
177 139 <div class="subject-box">
178 140 <el-checkbox-group v-model="subjectNames">
179   - <p
180   - class="p1"
181   - v-for="(item, index) in subjectList"
182   - :key="item.default"
183   - >
  141 + <p class="p1" v-for="(item, index) in subjectList" :key="item.default">
184 142 <el-checkbox v-if="!item.checked" :label="item.value">{{
185   - item.value
186   - }}</el-checkbox>
187   - <el-input
188   - class="sub-ipt"
189   - v-else
190   - v-model="item.value"
191   - @keyup.enter.native="_EditSub(item)"
192   - ></el-input>
193   - <i
194   - class="el-icon el-icon-edit"
195   - v-show="!item.checked"
196   - @click="item.checked = true"
197   - ></i>
198   - <i
199   - class="el-icon el-icon-check"
200   - v-show="item.checked"
201   - @click="_EditSub(item)"
202   - ></i>
  143 + item.value
  144 + }}</el-checkbox>
  145 + <el-input class="sub-ipt" v-else v-model="item.value" @keyup.enter.native="_EditSub(item)"></el-input>
  146 + <i class="el-icon el-icon-edit" v-show="!item.checked" @click="item.checked = true"></i>
  147 + <i class="el-icon el-icon-check" v-show="item.checked" @click="_EditSub(item)"></i>
203 148 <!-- <i
204 149 class="el-icon el-icon-close"
205 150 v-show="item.checked"
206 151 @click="resetSub(item)"
207 152 ></i> -->
208   - <i
209   - v-show="!item.checked"
210   - class="el-icon el-icon-delete"
211   - @click="_DelSubject(item, index)"
212   - ></i>
  153 + <i v-show="!item.checked" class="el-icon el-icon-delete" @click="_DelSubject(item, index)"></i>
213 154 </p>
214 155 </el-checkbox-group>
215 156 </div>
216 157 <el-col :span="8">
217   - <el-input
218   - placeholder="添加科目"
219   - v-model.trim="subjectName"
220   - maxlength="30"
221   - >
222   - <i
223   - slot="suffix"
224   - class="el-input__icon el-icon-plus"
225   - @click="addSubjectName"
226   - ></i>
  158 + <el-input placeholder="添加科目" v-model.trim="subjectName" maxlength="30">
  159 + <i slot="suffix" class="el-input__icon el-icon-plus" @click="addSubjectName"></i>
227 160 </el-input>
228 161 </el-col>
229 162 </el-form-item>
... ... @@ -255,6 +188,7 @@ export default {
255 188 },
256 189 data() {
257 190 return {
  191 + hasTeachingClass: false,
258 192 code: "",
259 193 loading: false,
260 194 loadingDown: false,
... ... @@ -355,6 +289,18 @@ export default {
355 289 : "";
356 290 this.diaClass = true;
357 291 },
  292 + async _downTemplate(type) {
  293 + const template = type == 0 ? this.$request.classAndStudentTemplate : this.$request.tClassAndStudentTemplate;
  294 + let data = await template();
  295 + if (data && !data.code) {
  296 + let blob = new Blob([data], {
  297 + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  298 + });
  299 + downloadFile(type == 0 ? "行政班名单模板" : "教学班名单模板", blob);
  300 + } else {
  301 + this.$message.error(data.info);
  302 + }
  303 + },
358 304 async _RemoveClass() {
359 305 const { data, status, info } = await this.$request.deleteClass({
360 306 id: this.formClass.classId,
... ... @@ -485,7 +431,22 @@ export default {
485 431 }
486 432 },
487 433 async _QueryData() {
  434 +
488 435 this.loading = true;
  436 +
  437 + var loadTeachingClass = await this.$request.classManager({
  438 + type: 1,
  439 + });
  440 + if (loadTeachingClass.status != 0) {
  441 + this.$message.error(loadTeachingClass.info);
  442 + return;
  443 + }
  444 +
  445 + this.hasTeachingClass = loadTeachingClass.data.list?.find(item => {
  446 + return item?.classList?.length >= 1;
  447 + });
  448 + console.log(loadTeachingClass.data.list, this.hasTeachingClass)
  449 +
489 450 this.dataList = [];
490 451 let { data, status, info } = await this.$request.classManager({
491 452 type: this.type,
... ... @@ -691,7 +652,7 @@ export default {
691 652 }
692 653 }
693 654  
694   - .is-checked ~ .el-icon-delete {
  655 + .is-checked~.el-icon-delete {
695 656 display: none;
696 657 }
697 658 }
... ...
src/views/basic/test/components/scoreSet.vue
... ... @@ -8,51 +8,19 @@
8 8 </div>
9 9 <div class="set-content">
10 10 <div class="test-title">
11   - <el-button class="import-btn" round @click="diaUp = true"
12   - >从excel文件导入</el-button
13   - >
14   - <el-button
15   - class="save-btn"
16   - type="primary"
17   - round
18   - :loading="loadingSave"
19   - @click="_SubmitScore"
20   - >保存</el-button
21   - >
  11 + <el-button class="import-btn" round @click="diaUp = true">从excel文件导入</el-button>
  12 + <el-button class="save-btn" type="primary" round :loading="loadingSave" @click="_SubmitScore">保存</el-button>
22 13 <p class="p1">{{ title }}</p>
23 14 <p class="p2">卷面总分:{{ examScore }}分</p>
24 15 </div>
25   - <el-table
26   - :data="tableData"
27   - border
28   - style="width: 100%"
29   - :max-height="tableMaxHeight"
30   - >
31   - <el-table-column
32   - prop="studentCode"
33   - label="学号"
34   - align="center"
35   - fixed
36   - ></el-table-column>
37   - <el-table-column
38   - prop="studentName"
39   - label="学号"
40   - align="center"
41   - fixed
42   - ></el-table-column>
43   - <el-table-column prop="score" label="总得分" align="center" fixed
44   - ><template slot-scope="scoped">
45   - <el-input
46   - v-if="showAllSetScore"
47   - type="number"
48   - :min="0"
49   - v-model="scoped.row.all"
50   - ></el-input>
  16 + <el-table :key="tableDataIndex" :data="tableData" border style="width: 100%" :max-height="tableMaxHeight">
  17 + <el-table-column prop="studentCode" label="学号" align="center" fixed></el-table-column>
  18 + <el-table-column prop="studentName" label="学号" align="center" fixed></el-table-column>
  19 + <el-table-column prop="score" label="总得分" align="center" fixed><template slot-scope="scoped">
  20 + <el-input v-if="showAllSetScore" type="number" :min="0" v-model="scoped.row.all"></el-input>
51 21 <template v-else>{{ scoped.row.all }}</template>
52   - </template></el-table-column
53   - >
54   - <el-table-column prop="objectiveScore" label="客观题分" align="center"
55   - ><template slot-scope="scoped">
  22 + </template></el-table-column>
  23 + <el-table-column prop="objectiveScore" label="客观题分" align="center"><template slot-scope="scoped">
56 24 <!-- <el-input
57 25 v-if="scoped.row.showSetScore"
58 26 type="number"
... ... @@ -61,8 +29,7 @@
61 29 @input="setOtherScore($event, scoped.row)"
62 30 ></el-input> -->
63 31 <template>{{ scoped.row.object }}</template>
64   - </template></el-table-column
65   - >
  32 + </template></el-table-column>
66 33 <el-table-column prop="subjectiveScore" label="主观题分" align="center">
67 34 <template slot-scope="scoped">
68 35 <!-- <el-input
... ... @@ -76,56 +43,29 @@
76 43 </template>
77 44 </el-table-column>
78 45 <!-- <el-table-column v-for="(item, index) in questionList" :key="index" :label="'第' + cNum[index] + '大题'" -->
79   - <el-table-column
80   - v-for="(question, index) in questionList"
81   - :key="index"
82   - :label="'Q' + question.questionId"
83   - align="center"
84   - >
  46 + <el-table-column v-for="(question, index) in questionList" :key="index" :label="'Q' + question.questionId"
  47 + align="center">
85 48 <template slot-scope="scoped">
86   - <el-input
87   - v-if="showSetScore"
88   - type="number"
89   - :min="0"
90   - :max="question.questionScore"
91   - @input="
92   - setScore(
93   - $event,
94   - question.questionScore,
95   - scoped.row.scoreMap,
96   - question.questionId,
97   - scoped.row
98   - )
99   - "
100   - v-model="scoped.row.scoreMap[question.questionId]"
101   - ></el-input>
102   - <template v-else>{{
103   - scoped.row.scoreMap[question.questionId]
104   - }}</template>
  49 + <el-input v-if="showSetScore" type="number" :min="0" :max="question.questionScore" @input="setScore(
  50 + $event,
  51 + question.questionScore,
  52 + scoped.row.scoreMap,
  53 + question.questionId,
  54 + scoped.row
  55 + )
  56 + " v-model="scoped.row.scoreMap[question.questionId]"></el-input>
  57 + <template v-else>{{ scoped.row.scoreMap[question.questionId] }}</template>
105 58 </template>
106 59 </el-table-column>
107 60 </el-table>
108 61 </div>
109 62  
110   - <el-dialog
111   - :close-on-click-modal="false"
112   - :append-to-body="true"
113   - title="答卷录分"
114   - :visible.sync="diaUp"
115   - width="600px"
116   - top="120px"
117   - >
118   - <upload
119   - :url="url"
120   - :examId="id"
121   - @upSuccess="upSuccess"
122   - fileName="主观题分数"
123   - v-loading="loadingDown"
124   - >
  63 + <el-dialog :close-on-click-modal="false" :append-to-body="true" title="答卷录分" :visible.sync="diaUp" width="600px"
  64 + top="120px">
  65 + <upload :url="url" :examId="id" @upSuccess="upSuccess" fileName="主观题分数" v-loading="loadingDown">
125 66 <template slot="down">
126 67 <p class="down-txt">
127   - 第一步:<el-link type="danger" @click="downExcel">下载模板</el-link
128   - >,并编辑完成学生分数。
  68 + 第一步:<el-link type="danger" @click="downExcel">下载模板</el-link>,并编辑完成学生分数。
129 69 </p>
130 70 <p class="down-txt">第二步:上传完成编辑的模板文件并导入。</p>
131 71 </template>
... ... @@ -160,8 +100,11 @@ export default {
160 100 url: "/api_html/teaching/importScore",
161 101 tableData: [],
162 102 questionList: [],
  103 + dataReponse: [],
  104 + tableDataIndex: 0,
163 105 cNum: cNum,
164 106 tableMaxHeight: 300,
  107 + studentList: [],
165 108 };
166 109 },
167 110 watch: {
... ... @@ -209,7 +152,7 @@ export default {
209 152 if (obj.scoreMap[keys] == 0) {
210 153 obj.scoreMap[keys] = 0;
211 154 } else {
212   - obj.scoreMap[keys] = "";
  155 + obj.scoreMap[keys] = 0;
213 156 }
214 157 } else {
215 158 let num = Number(obj.scoreMap[keys]);
... ... @@ -238,8 +181,9 @@ export default {
238 181 });
239 182 this.loading = false;
240 183 if (status === 0) {
241   - let studentList = data.students || [];
242   - this.questionList = data?.questionList || [];
  184 + this.dataReponse = data;
  185 + let studentList = this.dataReponse.students || [];
  186 + this.questionList = this.dataReponse?.questionList || [];
243 187 if (this.questionList.length == 0) {
244 188 this.questionList = Object.keys(studentList[0].scoreMap).map(
245 189 (item) => {
... ... @@ -269,7 +213,6 @@ export default {
269 213 item.scoreMap[keys] = num;
270 214 }
271 215 });
272   -
273 216 return item;
274 217 }) || [];
275 218 this.setTableHeight();
... ... @@ -310,10 +253,68 @@ export default {
310 253  
311 254 //导入成功
312 255 upSuccess(res) {
  256 +
313 257 this.$message.success("导入成功");
  258 +
  259 + let studentList = this.dataReponse.students || [];
  260 +
  261 + this.tableData =
  262 + studentList.map((item) => {
  263 + // setScore();
  264 + item.all = 0; //总分
  265 + item.object = 0; //客观题分数
  266 + item.subject = 0; //主观题分数
  267 + var detail = JSON.parse(res.data[item.studentId]);
  268 +
  269 + var scoreMap = {};
  270 +
  271 + if (detail) {
  272 + detail.forEach(item => {
  273 + scoreMap[item.id] = item.score
  274 + })
  275 + }
  276 +
  277 + item.scoreMap = scoreMap;
  278 +
  279 + this.questionList.map((question) => {
  280 + let keys = question.questionId;
  281 + if (!item.scoreMap[keys]) {
  282 + if (item.scoreMap[keys] == 0) {
  283 + item.scoreMap[keys] = 0;
  284 + } else {
  285 + item.scoreMap[keys] = "";
  286 + }
  287 + } else {
  288 + let num = Number(item.scoreMap[keys]);
  289 + item.scoreMap[keys] = num;
  290 + }
  291 + });
  292 +
  293 + return item;
  294 + }) || [];
  295 +
  296 + this.setTableHeight();
  297 +
  298 + this.tableDataIndex += 1;
  299 + // for (let key in res.data) {
  300 +
  301 + // var detail = JSON.parse(res.data[key]);
  302 +
  303 + // let studentList = this.dataReponse.students || [];
  304 +
  305 +
  306 +
  307 + // // if (student) {
  308 + // // for (let scoreMapKey in student?.scoreMap) {
  309 + // // var sDetail = detail.find(dl => dl.id == scoreMapKey);
  310 + // // if (sDetail) {
  311 + // // student.scoreMap[scoreMapKey] = sDetail.score;
  312 + // // }
  313 + // // }
  314 + // // }
  315 + // }
  316 + // this.setTableHeight();
314 317 this.diaUp = false;
315   - // this.closeScoreSet();
316   - this.$emit("SuccessScoreSet");
317 318 },
318 319 async downExcel() {
319 320 //模板下载
... ... @@ -338,10 +339,10 @@ export default {
338 339 <style lang="scss" scoped>
339 340 .set-container {
340 341 position: fixed;
341   - left: 200px;
342   - top: 50px;
343   - width: calc(100% - 200px);
344   - height: calc(100% - 70px);
  342 + left: 250px;
  343 + top: 60px;
  344 + width: calc(100% - 250px);
  345 + height: calc(100% - 80px);
345 346 background: #fff;
346 347 z-index: 2000;
347 348 overflow-y: auto;
... ...
src/views/examinationPaper/add.vue
... ... @@ -3,10 +3,40 @@
3 3 <div ref="content" class="content-box">
4 4 <back-box>
5 5 <template slot="title">
6   - <span>{{ "创建答题卡" }}</span>
  6 + <span>{{ isUpload ? "导入试卷" : "创建答题卡" }}</span>
7 7 </template>
8 8 </back-box>
9 9 <div class="content">
  10 + <el-dialog :close-on-click-modal="false" title="选择班级分享" :visible.sync="classSharingType" width="800"
  11 + :modal-append-to-body="false" :append-to-body="true">
  12 + <div>
  13 + <el-row class="row-subfix">
  14 + <div class="row-line">
  15 + <span class="line-subfix">年级:</span>
  16 + <span class="line-value">{{ gradeName }}</span>
  17 + </div>
  18 + </el-row>
  19 + <el-row class="row-subfix" style="margin-top: 20px;">
  20 + <span class="line-subfix" style="float: left;">班级:</span>
  21 + <div class="row-line" style="float: left;
  22 + background:rgb(245,247,250);padding:15px 10px;width: calc(100% - 80px);border-radius:5px;">
  23 + <span class="line-value" style="min-height: 300px;border-radius: 4px; background: rgb(247,247,250);">
  24 + <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
  25 + @change="handleCheckAllChange">全选</el-checkbox>
  26 + <el-checkbox-group v-model="checkedClass" style="margin-top: 15px;" @change="handleCheckedClassChange">
  27 + <el-checkbox v-for="(item, index) in shareClass" :label="item.id" :key="item.id">
  28 + {{ item.className }}
  29 + </el-checkbox>
  30 + </el-checkbox-group>
  31 + </span>
  32 + </div>
  33 + </el-row>
  34 + </div>
  35 + <div slot="footer">
  36 + <el-button type="info" :size="'small'" @click="classSharingType = false">取消</el-button>
  37 + <el-button type="primary" :size="'small'" @click="_checkedClass">确定</el-button>
  38 + </div>
  39 + </el-dialog>
10 40 <el-steps :active="step" finish-status="success" simple style="margin: 20px 0">
11 41 <el-step title="基础信息" icon="el-icon-edit"></el-step>
12 42 <el-step v-if="!isUpload" title="题目编辑" icon="el-icon-tickets"></el-step>
... ... @@ -49,7 +79,8 @@
49 79 <el-form-item v-if="role != 'ROLE_PERSONAL'" label="分享范围:" prop="sharingType">
50 80 <el-radio-group v-model="form.sharingType">
51 81 <el-radio :label="0">任课班级分享</el-radio>
52   - <el-radio :label="1">全年级分享</el-radio>
  82 + <el-radio class="name-radio" @click.native="_selectClassSharingType" v-model="form.sharingType"
  83 + :label="1">自定义分享班级</el-radio>
53 84 </el-radio-group>
54 85 </el-form-item>
55 86 </el-form>
... ... @@ -57,7 +88,8 @@
57 88 <el-button type="danger" plain round @click="linkBack">取消</el-button>
58 89 <el-button type="primary" round @click="isUpload ? setStep2() : setStep1()">下一步</el-button>
59 90 </div>
60   - <el-dialog :close-on-click-modal="false" title="设置测验类型" :visible.sync="dialogVisible" width="500px">
  91 + <el-dialog :close-on-click-modal="false" title="设置测验类型" :visible.sync="dialogVisible" width="500px"
  92 + :append-to-body="true">
61 93 <div class="dia-content">
62 94 <p class="add-type" v-for="item in tagList" :key="item.id">
63 95 <el-row :gutter="10">
... ... @@ -217,7 +249,8 @@
217 249 <el-button :type="form.questionList.length == 0 ? 'info' : 'primary'" round
218 250 @click="setStep2">下一步</el-button>
219 251 </div>
220   - <el-dialog :close-on-click-modal="false" title="添加大题" :visible.sync="addQuestionVisible" width="600px">
  252 + <el-dialog :close-on-click-modal="false" title="添加大题" :append-to-body="true"
  253 + :visible.sync="addQuestionVisible" width="600px">
221 254 <div class="dia-content">
222 255 <el-form ref="form" :model="questionForm" :rules="questionFormRules" label-width="100px">
223 256 <el-form-item label="标题:">
... ... @@ -514,7 +547,7 @@
514 547 </div>
515 548 </div>
516 549 <el-dialog :close-on-click-modal="false" :title="stem.type == 1 ? '上传题干' : '上传题目解析'" :visible.sync="dialogStem"
517   - v-if="dialogStem" width="800px">
  550 + v-if="dialogStem" width="800px" :append-to-body="true">
518 551 <div class="upload-box">
519 552 <div v-loading="iframeLoading">
520 553 <template v-if="stem.type == 1">
... ... @@ -535,7 +568,8 @@
535 568 <el-button @click="dialogStem = false">确定</el-button>
536 569 </div>
537 570 </el-dialog>
538   - <el-dialog :close-on-click-modal="false" title="知识点" :visible.sync="dialogKnowledge" width="500px">
  571 + <el-dialog :close-on-click-modal="false" :append-to-body="true" title="知识点" :visible.sync="dialogKnowledge"
  572 + width="1200px">
539 573 <div>
540 574 <el-form ref="form" :model="stem" label-width="160px">
541 575 <el-form-item label="知识点:">
... ... @@ -620,6 +654,13 @@ export default {
620 654 },
621 655 data() {
622 656 return {
  657 + shareClass: [],
  658 + role: "",
  659 + checkedClass: [],
  660 + classSharingType: false,
  661 + gradeName: "",
  662 + isIndeterminate: false,
  663 + checkAll: false,
623 664 role: "",
624 665 step: 0, //步骤
625 666 gradeClassList: [], //年级-班级数据
... ... @@ -744,6 +785,18 @@ export default {
744 785 }
745 786 },
746 787 methods: {
  788 + _checkedClass() {
  789 + this.classSharingType = false;
  790 + },
  791 + handleCheckAllChange(val) {
  792 + this.checkedClass = val ? this.shareClass?.map(item => item.id) : [];
  793 + this.isIndeterminate = false;
  794 + },
  795 + handleCheckedClassChange(value) {
  796 + let checkedCount = value.length;
  797 + this.checkAll = checkedCount === this.checkedClass.length;
  798 + this.isIndeterminate = checkedCount > 0 && checkedCount < this.checkedClass.length;
  799 + },
747 800 // v1.5
748 801 //上传截图
749 802 openStem(obj, index, indexs, type) {
... ... @@ -825,13 +878,25 @@ export default {
825 878 )
826 879 .then(() => { })
827 880 .catch(() => {
828   - this.$router.push({
829   - path: "/examinationPaper",
830   - query: {
831   - type: this.listType,
832   - share: this.listShare,
833   - },
834   - });
  881 + if (location.href.indexOf('askPreparationQuestionsAdd') >= 1) {
  882 + this.$router.push({
  883 + path: "/askPreparationQuestions"
  884 + });
  885 + }
  886 + else if (location.href.indexOf('testPaperAdd') >= 1) {
  887 + this.$router.push({
  888 + path: "/testPaper"
  889 + });
  890 + }
  891 + else {
  892 + this.$router.push({
  893 + path: "/examinationPaper",
  894 + query: {
  895 + type: this.listType,
  896 + share: this.listShare,
  897 + },
  898 + });
  899 + }
835 900 });
836 901 },
837 902 //转换题型显示方式
... ... @@ -1183,6 +1248,24 @@ export default {
1183 1248 }
1184 1249 }
1185 1250 },
  1251 + async _selectClassSharingType() {
  1252 +
  1253 + this.classSharingType = true;
  1254 +
  1255 + var grade = this.gradeClassList.find(item => item.gradeName == this.form.gradeName);
  1256 +
  1257 + var classResponse = await this.$request.tClassGrade(grade?.grade,this.form.subjectName);
  1258 +
  1259 + if (classResponse.status != 0) {
  1260 + this.$message.error(classResponse.info);
  1261 + }
  1262 +
  1263 + this.gradeName = grade.gradeName;
  1264 +
  1265 + this.shareClass = classResponse.data;
  1266 +
  1267 +
  1268 + },
1186 1269 openQuestion() {
1187 1270 this.questionForm = { ...questionForm };
1188 1271 this.addQuestionVisible = true;
... ... @@ -1437,16 +1520,28 @@ export default {
1437 1520 },
1438 1521 async save() {
1439 1522 if (this.saveLoading) return;
  1523 +
1440 1524 this.saveLoading = true;
  1525 +
1441 1526 this.formatQuestionList();
  1527 +
1442 1528 let formDatas = deepClone(this.form);
  1529 +
  1530 + formDatas.questionList = formDatas.questionList.filter(item => {
  1531 + return item.subQuestions?.length >= 1;
  1532 + });
  1533 +
1443 1534 for (let i = 0; i < formDatas.questionList.length; i++) {
1444 1535 delete formDatas.questionList[i].show;
1445 1536 }
  1537 +
1446 1538 let addPaper =
1447 1539 this.role == "ROLE_PERSONAL"
1448 1540 ? this.$request.pAddPaper
1449 1541 : this.$request.addPaper;
  1542 +
  1543 + formDatas.classIds = this.checkedClass.join(",");
  1544 +
1450 1545 const { data, status, info } = await addPaper({
1451 1546 ...formDatas,
1452 1547 });
... ...
src/views/examinationPaper/addQs.vue
... ... @@ -7,6 +7,37 @@
7 7 </template>
8 8 </back-box>
9 9 <div class="content">
  10 +
  11 + <el-dialog :close-on-click-modal="false" title="选择班级分享" :visible.sync="classSharingType" width="800"
  12 + :modal-append-to-body="false" :append-to-body="true">
  13 + <div>
  14 + <el-row class="row-subfix">
  15 + <div class="row-line">
  16 + <span class="line-subfix">年级:</span>
  17 + <span class="line-value">{{ gradeName }}</span>
  18 + </div>
  19 + </el-row>
  20 + <el-row class="row-subfix" style="margin-top: 20px;">
  21 + <span class="line-subfix" style="float: left;">班级:</span>
  22 + <div class="row-line" style="float: left;
  23 + background:rgb(245,247,250);padding:15px 10px;width: calc(100% - 80px);border-radius:5px;">
  24 + <span class="line-value" style="min-height: 300px;border-radius: 4px; background: rgb(247,247,250);">
  25 + <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
  26 + @change="handleCheckAllChange">全选</el-checkbox>
  27 + <el-checkbox-group v-model="checkedClass" style="margin-top: 15px;" @change="handleCheckedClassChange">
  28 + <el-checkbox v-for="(item, index) in shareClass" :label="item.id" :key="item.id">{{
  29 + item.className }}</el-checkbox>
  30 + </el-checkbox-group>
  31 + </span>
  32 + </div>
  33 + </el-row>
  34 + </div>
  35 + <div slot="footer">
  36 + <el-button type="info" :size="'small'" @click="classSharingType = false">取消</el-button>
  37 + <el-button type="primary" :size="'small'" @click="_checkedClass">确定</el-button>
  38 + </div>
  39 + </el-dialog>
  40 +
10 41 <el-steps :active="step" finish-status="success" simple style="margin: 20px 0">
11 42 <el-step title="基础信息" icon="el-icon-edit"></el-step>
12 43 <el-step title="题目编辑" icon="el-icon-tickets"></el-step>
... ... @@ -36,7 +67,8 @@
36 67 <el-form-item v-if="role != 'ROLE_PERSONAL'" label="分享范围:" prop="sharingType">
37 68 <el-radio-group v-model="form.sharingType">
38 69 <el-radio :label="0">任课班级分享</el-radio>
39   - <el-radio :label="1">全年级分享</el-radio>
  70 + <el-radio class="name-radio" @click.native="_selectClassSharingType" v-model="form.sharingType"
  71 + :label="1">自定义分享班级</el-radio>
40 72 </el-radio-group>
41 73 </el-form-item>
42 74 </el-form>
... ... @@ -59,7 +91,7 @@
59 91 <div class="qs-options qs-options2">选项设置</div>
60 92 <div class="qs-upload">题干</div>
61 93 <div class="qs-upload">题目解析</div>
62   - <div class="qs-upload" v-if="knowledgeData.length">知识点</div>
  94 + <div class="qs-upload" >知识点</div>
63 95 <div class="qs-set">操作</div>
64 96 </li>
65 97 </ul>
... ... @@ -99,8 +131,8 @@
99 131 </p>
100 132 <p v-if="question.questionType == 3" class="answer-box">
101 133 <span class="answer-s" v-for="option in question.answerOptions?.split(',')" :class="question.correctAnswer?.includes(option)
102   - ? 'active'
103   - : ''
  134 + ? 'active'
  135 + : ''
104 136 " :key="option" @click="changAnswer(question, option)">{{ option }}</span>
105 137 </p>
106 138 <p v-if="question.questionType == 2" class="answer-box">
... ... @@ -125,7 +157,7 @@
125 157 <el-button class="icon-tickets" type="primary" circle size="mini" icon="el-icon-tickets"
126 158 @click="openStem(question, 2, index)"></el-button>
127 159 </div>
128   - <div class="qs-upload" v-if="knowledgeData.length">
  160 + <div class="qs-upload" >
129 161 <el-button type="primary" circle size="mini" icon="el-icon-price-tag"
130 162 @click="openKnowledge(question, index)"></el-button>
131 163 </div>
... ... @@ -179,8 +211,8 @@
179 211 <span class="answer-s" v-for="option in subQuestions.answerOptions?.split(
180 212 ','
181 213 )" :class="subQuestions.correctAnswer?.includes(option)
182   - ? 'active'
183   - : ''
  214 + ? 'active'
  215 + : ''
184 216 " :key="option" @click="changAnswer(subQuestions, option)">{{ option }}</span>
185 217 </p>
186 218 <p v-if="subQuestions.questionType == 2" class="answer-box">
... ... @@ -206,17 +238,8 @@
206 238 <div class="qs-upload">
207 239 <el-button class="icon-tickets" type="primary" circle size="mini" icon="el-icon-tickets"
208 240 @click="openStem(subQuestions, 2, index, indexs)"></el-button>
209   - </div> if (location.href.indexOf('askPreparationQuestionsAdd') >= 1) {
210   - this.$router.push({
211   - path: "/askPreparationQuestions"
212   - });
213   - }
214   - else if (location.href.indexOf('testPaperAdd') >= 1) {
215   - this.$router.push({
216   - path: "/testPaper"
217   - });
218   - }
219   - <div class="qs-upload" v-if="knowledgeData.length">
  241 + </div>
  242 + <div class="qs-upload" >
220 243 <el-button type="primary" circle size="mini" icon="el-icon-price-tag"
221 244 @click="openKnowledge(subQuestions, index, indexs)"></el-button>
222 245 </div>
... ... @@ -233,7 +256,7 @@
233 256 </template>
234 257 </div>
235 258 <el-dialog :close-on-click-modal="false" title="批量设置答案" :visible.sync="diaSetAns" width="400"
236   - :modal-append-to-body="true">
  259 + :modal-append-to-body="false">
237 260 <div class="qs-options">
238 261 <p class="dia-tips">
239 262 请点击选项按钮设置答案,多选题题目之间用“,”隔开,若添加5道题:“AC,AD,BD,AC,CD”
... ... @@ -284,8 +307,8 @@
284 307 <el-button round @click="step = 0">上一步</el-button>
285 308 <el-button type="primary" round @click="toStep(2)">下一步</el-button>
286 309 </div>
287   - <el-dialog :close-on-click-modal="false" :title="stem.type == 1 ? '上传题干' : '上传题目解析'" :visible.sync="dialogStem"
288   - v-if="dialogStem" width="800px">
  310 + <el-dialog :close-on-click-modal="false" :modal-append-to-body="false"
  311 + :title="stem.type == 1 ? '上传题干' : '上传题目解析'" :visible.sync="dialogStem" v-if="dialogStem" width="800px">
289 312 <div class="upload-box">
290 313 <div v-loading="iframeLoading">
291 314 <template v-if="stem.type == 1">
... ... @@ -306,14 +329,10 @@
306 329 <el-button @click="dialogStem = false">保存</el-button>
307 330 </div>
308 331 </el-dialog>
309   - <el-dialog :close-on-click-modal="false" title="知识点" :visible.sync="dialogKnowledge" width="500px">
  332 + <el-dialog :close-on-click-modal="false" :modal-append-to-body="false" title="知识点"
  333 + :visible.sync="dialogKnowledge" width="60%" >
310 334 <div>
311   - <el-form ref="form" :model="stem" label-width="160px">
312   - <el-form-item label="知识点:">
313   - <el-cascader size="small" filterable :show-all-levels="false" collapse clearable placeholder="选择知识点"
314   - v-model="stem.knowledge" :options="knowledgeData" :props="{ expandTrigger: 'hover' }"></el-cascader>
315   - </el-form-item>
316   - </el-form>
  335 + <knowledgePoints :sectionName="stem.sectionName" :subjectName="stem.subjectName" :knowledges="stem.knowledge" @points="_points" />
317 336 </div>
318 337 <div slot="footer">
319 338 <el-button @click="dialogKnowledge = false">取 消</el-button>
... ... @@ -354,10 +373,20 @@
354 373 <script>
355 374 import { deepClone, checkAnswer } from "utils";
356 375 import knowledgeList from "assets/js/knowledgeList.js";
  376 +import knowledgePoints from "@/components/knowledgePoints"
357 377 export default {
  378 + components: {
  379 + knowledgePoints
  380 + },
358 381 data() {
359 382 return {
  383 + shareClass: [],
360 384 role: "",
  385 + checkedClass: [],
  386 + classSharingType: false,
  387 + gradeName: "",
  388 + isIndeterminate: false,
  389 + checkAll: false,
361 390 step: 0, //步骤
362 391 gradeClassList: [], //年级-班级数据
363 392 gradeList: [], //年级
... ... @@ -405,6 +434,8 @@ export default {
405 434 screenshot: "", //题干图片地址
406 435 answerScreenshot: "", //题目解析图片地址
407 436 knowledge: [], //知识点
  437 + subjectName: "",
  438 + sectionName: "",
408 439 },
409 440 type: 1, //1-创建,2-复制答题卡
410 441 questionOptions: [
... ... @@ -423,33 +454,33 @@ export default {
423 454 subjectName: "",
424 455 };
425 456 },
426   - computed: {
427   - // 知识点列表 根据学段-科目筛选
428   - knowledgeData: function () {
429   - let jsons = [];
430   - if (this.form.gradeName && this.form.subjectName) {
431   - let sectionName = "";
432   - this.gradeClassList.map((item) => {
433   - if (this.form.gradeName == item.gradeName) {
434   - sectionName = item.sectionName;
435   - }
436   - });
437   - if (
438   - sectionName &&
439   - Object.keys(this.knowledgeList).includes(sectionName)
440   - ) {
441   - if (
442   - Object.keys(this.knowledgeList[sectionName]).includes(
443   - this.form.subjectName
444   - )
445   - ) {
446   - jsons = this.knowledgeList[sectionName][this.form.subjectName];
447   - }
448   - }
449   - }
450   - return jsons;
451   - },
452   - },
  457 + // computed: {
  458 + // // 知识点列表 根据学段-科目筛选
  459 + // knowledgeData: function () {
  460 + // let jsons = [];
  461 + // if (this.form.gradeName && this.form.subjectName) {
  462 + // let sectionName = "";
  463 + // this.gradeClassList.map((item) => {
  464 + // if (this.form.gradeName == item.gradeName) {
  465 + // sectionName = item.sectionName;
  466 + // }
  467 + // });
  468 + // if (
  469 + // sectionName &&
  470 + // Object.keys(this.knowledgeList).includes(sectionName)
  471 + // ) {
  472 + // if (
  473 + // Object.keys(this.knowledgeList[sectionName]).includes(
  474 + // this.form.subjectName
  475 + // )
  476 + // ) {
  477 + // jsons = this.knowledgeList[sectionName][this.form.subjectName];
  478 + // }
  479 + // }
  480 + // }
  481 + // return jsons;
  482 + // },
  483 + // },
453 484 watch: {
454 485 step: function () {
455 486 this.$nextTick(function () {
... ... @@ -488,6 +519,31 @@ export default {
488 519 }
489 520 },
490 521 methods: {
  522 + _points(point) {
  523 +
  524 + },
  525 + _checkedClass() {
  526 + this.classSharingType = false;
  527 + },
  528 + handleCheckAllChange(val) {
  529 + this.checkedClass = val ? this.shareClass?.map(item => item.id) : [];
  530 + this.isIndeterminate = false;
  531 + },
  532 + handleCheckedClassChange(value) {
  533 + let checkedCount = value.length;
  534 + this.checkAll = checkedCount === this.checkedClass.length;
  535 + this.isIndeterminate = checkedCount > 0 && checkedCount < this.checkedClass.length;
  536 + },
  537 + async _selectClassSharingType() {
  538 + this.classSharingType = true;
  539 + var findGrade = this.gradeClassList.find(item => item.gradeName == this.form.gradeName);
  540 + this.gradeName = findGrade.gradeName;
  541 + var classResponse = await this.$request.tClassGrade(findGrade.grade, this.form.subjectName);
  542 + if (classResponse.status != 0) {
  543 + this.$message.error(classResponse.info);
  544 + }
  545 + this.shareClass = classResponse.data;
  546 + },
491 547 // v1.5
492 548 //上传截图
493 549 openStem(obj, type, index, indexs) {
... ... @@ -550,6 +606,16 @@ export default {
550 606 this.stem.index = index;
551 607 this.stem.indexs = indexs;
552 608 this.stem.knowledge = (obj.knowledge && obj.knowledge.split("#")) || [];
  609 + if (this.form.gradeName && this.form.subjectName) {
  610 + var matchClass = this.gradeClassList.find((item) => {
  611 + if (this.form.gradeName == item.gradeName) {
  612 + return item.sectionName;
  613 + }
  614 + });
  615 + this.stem.sectionName = matchClass?.sectionName ?? "";
  616 + this.stem.subjectName = this.form.subjectName ?? "";
  617 + }
  618 + // this.stem.sectionName =
553 619 this.dialogKnowledge = true;
554 620 },
555 621 // 知识点
... ... @@ -578,13 +644,25 @@ export default {
578 644 )
579 645 .then(() => { })
580 646 .catch(() => {
581   - this.$router.push({
582   - path: "/examinationPaper",
583   - query: {
584   - type: this.listType,
585   - share: this.listShare,
586   - },
587   - });
  647 + if (location.href.indexOf('askPreparationQuestionsAdd') >= 1) {
  648 + this.$router.push({
  649 + path: "/askPreparationQuestions"
  650 + });
  651 + }
  652 + else if (location.href.indexOf('testPaperAdd') >= 1) {
  653 + this.$router.push({
  654 + path: "/testPaper"
  655 + });
  656 + }
  657 + else {
  658 + this.$router.push({
  659 + path: "/examinationPaper",
  660 + query: {
  661 + type: this.listType,
  662 + share: this.listShare,
  663 + },
  664 + });
  665 + }
588 666 });
589 667 },
590 668 //转换题型显示方式
... ... @@ -1025,6 +1103,13 @@ export default {
1025 1103 this.saveLoading = true;
1026 1104 this.formatQuestionList();
1027 1105 let formDatas = deepClone(this.form);
  1106 +
  1107 + formDatas.classIds = this.checkedClass.join(",");
  1108 +
  1109 + formDatas.questionList = formDatas.questionList.filter(item => {
  1110 + return item.subQuestions?.length >= 1;
  1111 + });
  1112 +
1028 1113 let addPaper =
1029 1114 this.role == "ROLE_PERSONAL"
1030 1115 ? this.$request.pAddPaper
... ... @@ -1046,14 +1131,26 @@ export default {
1046 1131 });
1047 1132 }
1048 1133 else {
1049   - this.$router.push({
1050   - path: "/examinationPaper",
1051   - query: {
1052   - type: this.listType,
1053   - share: this.listShare,
1054   - },
1055   - });
1056   - }
  1134 + if (location.href.indexOf('askPreparationQuestionsAdd') >= 1) {
  1135 + this.$router.push({
  1136 + path: "/askPreparationQuestions"
  1137 + });
  1138 + }
  1139 + else if (location.href.indexOf('testPaperAdd') >= 1) {
  1140 + this.$router.push({
  1141 + path: "/testPaper"
  1142 + });
  1143 + }
  1144 + else {
  1145 + this.$router.push({
  1146 + path: "/examinationPaper",
  1147 + query: {
  1148 + type: this.listType,
  1149 + share: this.listShare,
  1150 + },
  1151 + });
  1152 + }
  1153 + }
1057 1154 } else {
1058 1155 this.$message.error(info);
1059 1156 }
... ...
src/views/examinationPaper/index.vue
... ... @@ -181,7 +181,7 @@
181 181 <script>
182 182 import { downloadFile } from "@/utils";
183 183 import axios from "axios";
184   -import example from "@/assets/images/example.jpg";
  184 +import example from "@/assets/images/example.png";
185 185 import example2 from "@/assets/images/example2.png";
186 186 export default {
187 187 name: "examinationPaper",
... ...
src/views/layout/header/header.vue
... ... @@ -397,7 +397,7 @@ ul.el-menu {
397 397 justify-content: center;
398 398 margin: 0 5px;
399 399 p {
400   - line-height: 16px;
  400 + line-height: 20px;
401 401 font-size: 12px;
402 402 }
403 403 }
... ...
src/views/login/index.vue
... ... @@ -171,7 +171,7 @@ $cursor: #000;
171 171 }
172 172 .login-container {
173 173 width: 100%;
174   - height: 100vh;
  174 + height: 150vh;
175 175 background: url("../../assets/images/login-bg.png") no-repeat;
176 176 background-size: cover;
177 177 overflow: hidden;
... ... @@ -215,8 +215,7 @@ $cursor: #000;
215 215 padding: 30px 35px 0;
216 216 border-radius: 10px;
217 217 background: #fff;
218   - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
219   - margin-top: 200px;
  218 + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
220 219 box-sizing: border-box;
221 220 }
222 221  
... ...
vue.config.js
... ... @@ -11,7 +11,7 @@ module.exports = {
11 11 lintOnSave: false, //是否开启编译时是否不符合eslint提示
12 12 productionSourceMap: false, // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
13 13 devServer: {
14   - hot:true,
  14 + hot: true,
15 15 port: 8081, // 端口
16 16 open: false, // 启动后打开浏览器
17 17 compress: true,
... ... @@ -23,10 +23,11 @@ module.exports = {
23 23 proxy: {
24 24 "/": {
25 25 // target:"http://ezquiz.sunvotecloud.cn",
26   - // target:"http://192.168.3.221:8080",
27   - target:"http://121.40.127.171",
  26 + // target:"http://192.168.1.151:8089",
  27 + target: "http://121.40.127.171:8089",
  28 + // target:"http://127.0.0.1:8089",
28 29 changeOrigin: true,
29   - ws:true,
  30 + ws: true,
30 31 },
31 32 },
32 33 disableHostCheck: true
... ...