Commit 9309dc5d890aab5ff73ff7df9be2945454fdec58

Authored by 梁保满
1 parent 225a00b6

任课老师接口完成

src/api/apis/apis.js
... ... @@ -26,6 +26,233 @@ export default {
26 26 data,
27 27 });
28 28 },
  29 + // 班主任首页数据
  30 + classIndex(data) {
  31 + return service({
  32 + url: setUpUrls.classIndex,
  33 + method: "POST",
  34 + data,
  35 + });
  36 + },
  37 + //班主任-查询管理的班级
  38 + cTClassList(data) {
  39 + return service({
  40 + url: setUpUrls.cTClassList,
  41 + method: "POST",
  42 + data,
  43 + });
  44 + },
  45 + //班主任-查询管理班级授课科目
  46 + cTSubjectList(data) {
  47 + return service({
  48 + url: setUpUrls.cTSubjectList,
  49 + method: "POST",
  50 + data,
  51 + });
  52 + },
  53 + //班主任-查询阶段问答报表
  54 + cTPhaseAnswerReport(data) {
  55 + return service({
  56 + url: setUpUrls.cTPhaseAnswerReport,
  57 + method: "POST",
  58 + data,
  59 + });
  60 + },
  61 + //班主任-查询阶段互动报表
  62 + cTPhaseInteractiveReport(data) {
  63 + return service({
  64 + url: setUpUrls.cTPhaseInteractiveReport,
  65 + method: "POST",
  66 + data,
  67 + });
  68 + },
  69 + //班主任-查询阶段测练报表
  70 + cTPhaseExamReport(data) {
  71 + return service({
  72 + url: setUpUrls.cTPhaseExamReport,
  73 + method: "POST",
  74 + data,
  75 + });
  76 + },
  77 +
  78 + //任课老师-查询管理的班级
  79 + tClassList(data) {
  80 + return service({
  81 + url: setUpUrls.tClassList,
  82 + method: "POST",
  83 + data,
  84 + });
  85 + },
  86 + //任课老师-查询管理班级授课科目
  87 + tSubjectList(data) {
  88 + return service({
  89 + url: setUpUrls.tSubjectList,
  90 + method: "POST",
  91 + data,
  92 + });
  93 + },
  94 + //任课老师-分页查询课时报表列表
  95 + periodReportList(data) {
  96 + return service({
  97 + url: setUpUrls.periodReportList,
  98 + method: "POST",
  99 + data,
  100 + });
  101 + },
  102 + //任课老师-查询阶段问答报表
  103 + phaseAnswerReport(data) {
  104 + return service({
  105 + url: setUpUrls.phaseAnswerReport,
  106 + method: "POST",
  107 + data,
  108 + });
  109 + },
  110 + //任课老师-查询阶段互动报表
  111 + phaseInteractiveReport(data) {
  112 + return service({
  113 + url: setUpUrls.phaseInteractiveReport,
  114 + method: "POST",
  115 + data,
  116 + });
  117 + },
  118 + //任课老师-查询课时题目列表
  119 + periodQuestionList(data) {
  120 + return service({
  121 + url: setUpUrls.periodQuestionList,
  122 + method: "POST",
  123 + data,
  124 + });
  125 + },
  126 + //任课老师-设置课时报表答案
  127 + setPeriodAnswer(data) {
  128 + return service({
  129 + url: setUpUrls.setPeriodAnswer,
  130 + method: "POST",
  131 + data,
  132 + });
  133 + },
  134 + //任课老师-查询课时报表详情
  135 + periodDetail(data) {
  136 + return service({
  137 + url: setUpUrls.periodDetail,
  138 + method: "POST",
  139 + data,
  140 + });
  141 + },
  142 + //任课老师-分页查询课时题目统计列表
  143 + periodQuestionReport(data) {
  144 + return service({
  145 + url: setUpUrls.periodQuestionReport,
  146 + method: "POST",
  147 + data,
  148 + });
  149 + },
  150 + //任课老师-查询课时学生答题明细
  151 + periodStudentReport(data) {
  152 + return service({
  153 + url: setUpUrls.periodStudentReport,
  154 + method: "POST",
  155 + data,
  156 + });
  157 + },
  158 + //任课老师-分页查询即时测报表
  159 + examReportList(data) {
  160 + return service({
  161 + url: setUpUrls.examReportList,
  162 + method: "POST",
  163 + data,
  164 + });
  165 + },
  166 + //任课老师-查询阶段测练报表
  167 + phaseExamReport(data) {
  168 + return service({
  169 + url: setUpUrls.phaseExamReport,
  170 + method: "POST",
  171 + data,
  172 + });
  173 + },
  174 + //任课老师-查询即时测报表题目列表
  175 + examQuestionList(data) {
  176 + return service({
  177 + url: setUpUrls.examQuestionList,
  178 + method: "POST",
  179 + data,
  180 + });
  181 + },
  182 + //任课老师-设置即时测报表答案
  183 + setExamAnswer(data) {
  184 + return service({
  185 + url: setUpUrls.setExamAnswer,
  186 + method: "POST",
  187 + data,
  188 + });
  189 + },
  190 + //任课老师-查询即时测报表详情
  191 + examDetail(data) {
  192 + return service({
  193 + url: setUpUrls.examDetail,
  194 + method: "POST",
  195 + data,
  196 + });
  197 + },
  198 + //任课老师-下载导入主观题分模板
  199 + subjectiveScoreTemplate(data) {
  200 + return service({
  201 + url: setUpUrls.subjectiveScoreTemplate,
  202 + method: "POST",
  203 + data,
  204 + });
  205 + },
  206 + //任课老师-导入主观题得分
  207 + importSubjectiveScore(data) {
  208 + return service({
  209 + url: setUpUrls.importSubjectiveScore,
  210 + method: "POST",
  211 + data,
  212 + });
  213 + },
  214 + //任课老师-分页查询即时测题目统计
  215 + examQuestionReport(data) {
  216 + return service({
  217 + url: setUpUrls.examQuestionReport,
  218 + method: "POST",
  219 + data,
  220 + });
  221 + },
  222 + //任课老师-查询即时测学生统计
  223 + examStudentReport(data) {
  224 + return service({
  225 + url: setUpUrls.examStudentReport,
  226 + method: "POST",
  227 + data,
  228 + });
  229 + },
  230 + //任课老师-重新判分
  231 + reScore(data) {
  232 + return service({
  233 + url: setUpUrls.reScore,
  234 + method: "POST",
  235 + data,
  236 + });
  237 + },
  238 + //任课老师-数据导出
  239 + exportData(data) {
  240 + return service({
  241 + url: setUpUrls.exportData,
  242 + method: "POST",
  243 + data,
  244 + });
  245 + },
  246 + //任课老师-数据导入
  247 + importData(data) {
  248 + return service({
  249 + url: setUpUrls.importData,
  250 + method: "POST",
  251 + data,
  252 + });
  253 + },
  254 +
  255 +
29 256 // 查询角色列表
30 257 roleList(data) {
31 258 return service({
... ...
src/api/urls/apis.js
... ... @@ -6,6 +6,68 @@ export default {
6 6 schoolIndex: "/api_html/school/manager/index",
7 7 // 学校管理员首页数据
8 8 tenantIndex: "/api_html/tenant/index",
  9 + // 班主任首页数据
  10 + classIndex: "/api_html/class/manager/index",
  11 + //班主任-查询管理的班级
  12 + cTClassList: "/api_html/class/manager/classList",
  13 + //班主任-查询管理班级授课科目
  14 + cTSubjectList: "/api_html/class/manager/subjectList",
  15 + //班主任-查询阶段问答报表
  16 + cTPhaseAnswerReport: "/api_html/class/manager/phaseAnswerReport",
  17 + //班主任-查询阶段互动报表
  18 + cTPhaseInteractiveReport: "/api_html/class/manager/phaseInteractiveReport",
  19 + //班主任-查询阶段测练报表
  20 + cTPhaseExamReport: "/api_html/class/manager/phaseExamReport",
  21 +
  22 + //任课老师-查询管理班级
  23 + tClassList: "/api_html/teaching/classList",
  24 + //任课老师-查询管理班级授课科目
  25 + tSubjectList: "/api_html/teaching/subjectList",
  26 + //任课老师-分页查询课时报表列表
  27 + periodReportList: "/api_html/teaching/periodReportList",
  28 + //任课老师-查询阶段问答报表
  29 + phaseAnswerReport: "/api_html/teaching/phaseAnswerReport",
  30 + //任课老师-查询阶段互动报表
  31 + phaseInteractiveReport: "/api_html/teaching/phaseInteractiveReport",
  32 + //任课老师-查询课时题目列表
  33 + periodQuestionList: "/api_html/teaching/periodQuestionList",
  34 + //任课老师-设置课时报表答案
  35 + setPeriodAnswer: "/api_html/teaching/setPeriodAnswer",
  36 + //任课老师-查询课时报表详情
  37 + periodDetail: "/api_html/teaching/periodDetail",
  38 + //任课老师-分页查询课时题目统计列表
  39 + periodQuestionReport: "/api_html/teaching/periodQuestionReport",
  40 + //任课老师-查询课时学生答题明细
  41 + periodStudentReport: "/api_html/teaching/periodStudentReport",
  42 + //任课老师-分页查询即时测报表
  43 + examReportList: "/api_html/teaching/examReportList",
  44 + //任课老师-查询阶段测练报表
  45 + phaseExamReport: "/api_html/teaching/phaseExamReport",
  46 + //任课老师-查询即时测报表题目列表
  47 + examQuestionList: "/api_html/teaching/examQuestionList",
  48 + //任课老师-设置即时测报表答案
  49 + setExamAnswer: "/api_html/teaching/setExamAnswer",
  50 + //任课老师-查询即时测报表详情
  51 + examDetail: "/api_html/teaching/examDetail",
  52 + //任课老师-下载导入主观题分模板
  53 + subjectiveScoreTemplate: "/api_html/teaching/subjectiveScoreTemplate",
  54 + //任课老师-导入主观题得分
  55 + importSubjectiveScore: "/api_html/teaching/importSubjectiveScore",
  56 + //任课老师-分页查询即时测题目统计
  57 + examQuestionReport: "/api_html/teaching/examQuestionReport",
  58 + //任课老师-查询即时测学生统计
  59 + examStudentReport: "/api_html/teaching/examStudentReport",
  60 + //任课老师-重新判分
  61 + reScore: "/api_html/teaching/reScore",
  62 + //任课老师-数据导出
  63 + exportData: "/api_html/teaching/exportData",
  64 + //任课老师-数据导入
  65 + importData: "/api_html/teaching/importData",
  66 +
  67 +
  68 +
  69 +
  70 +
9 71 // 查询角色列表
10 72 roleList: "/api_html/school/manager/roleList",
11 73 // 分页查询账号
... ... @@ -68,8 +130,8 @@ export default {
68 130 usageAnalysis: "/api_html/school/manager/usageAnalysis",
69 131 // 发卡记录
70 132 cardList: "/api_html/school/manager/cardList",
71   -
72   -
  133 +
  134 +
73 135 // 查询区域列表
74 136 regionList: "/api_html/tenant/regionList",
75 137 // 查询学校列表
... ... @@ -100,7 +162,7 @@ export default {
100 162 tenantGradeList: "/api_html/tenant/gradeList",
101 163 // 查询学校班级
102 164 tenantClassList: "/api_html/tenant/classList",
103   -
  165 +
104 166 // 学校使用对比
105 167 schoolContrast: "/api_html/tenant/schoolContrast",
106 168 // 年级使用对比
... ...
src/assets/css/index.scss
... ... @@ -120,7 +120,7 @@
120 120 .down-txt{
121 121 display: flex;
122 122 align-items: center;
123   - justify-content: center;
  123 + padding-left: 160px;
124 124 }
125 125 .h-title{
126 126 padding-left:12px;
... ...
src/components/setAnswer.vue
... ... @@ -8,145 +8,64 @@
8 8 >
9 9 <div class="el-dialog-content">
10 10 <p class="title">
11   - 设置答案 <i class="fa fa-exchange" @click="editType = !editType"></i>
  11 + 设置答案 <i class="fa fa-exchange"></i>
12 12 <!-- 设置答案 -->
13 13 <i class="el-icon-close" @click="cancel"></i>
14 14 </p>
15   - <div v-if="editType">
16   - <div v-for="(item, index) in FormQuestionList" :key="index">
17   - <template v-for="(subQuestions, indexs) in item.subQuestions">
18   - <div
19   - class="sub-questions"
20   - :key="indexs"
21   - v-if="subQuestions.correctAnswer"
  15 + <div class="dia-question-box">
  16 + <p class="dia-tips">点击批量设置答案按钮,批量设置答案</p>
  17 + <div v-for="(subQuestions, index) in FormQuestionList" :key="index">
  18 + <p
  19 + class="set-ans-btn"
  20 + v-if="
  21 + subQuestions.qusType &&
  22 + subQuestions.subNum &&
  23 + subQuestions.subNum > 4
  24 + "
  25 + >
  26 + <el-button type="primary" @click="setFormAns(index)"
  27 + >批量设置答案</el-button
22 28 >
23   - <div class="qs-num">题{{ subQuestions.questionIndex }}</div>
24   - <div class="qs-options qs-options2">
25   - <p v-if="subQuestions.questionType == 4" class="answer-box">
26   - <span
27   - class="answer-s"
28   - :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
29   - @click="subQuestions.correctAnswer = 1"
30   - >✓</span
31   - >
32   - <span
33   - class="answer-s"
34   - :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
35   - @click="subQuestions.correctAnswer = 2"
36   - >✗</span
37   - >
38   - </p>
39   - <p v-if="subQuestions.questionType == 3" class="answer-box">
40   - <span
41   - class="answer-s"
42   - v-for="option in subQuestions.answerOptions"
43   - :class="
44   - subQuestions.correctAnswer.includes(option)
45   - ? 'active'
46   - : ''
47   - "
48   - :key="option"
49   - @click="changAnswer(subQuestions, option)"
50   - >{{ option }}</span
51   - >
52   - </p>
53   - <p v-if="subQuestions.questionType == 2" class="answer-box">
54   - <span
55   - class="answer-s"
56   - v-for="option in subQuestions.answerOptions"
57   - :class="
58   - subQuestions.correctAnswer == option ? 'active' : ''
59   - "
60   - :key="option"
61   - @click="subQuestions.correctAnswer = option"
62   - >{{ option }}</span
63   - >
64   - </p>
65   - </div>
66   - </div>
67   - </template>
68   - </div>
69   - </div>
70   - <div v-else>
71   - <p class="dia-tips">
72   - 请点击选项按钮设置答案,多选题题目之间用“,”隔开,若添加5道题:“AC,AD,BD,AC,CD”
73   - </p>
74   - <div class="dia-question-box">
75   - <div v-for="(item, index) in FormQuestionList2" :key="index">
76   - <div class="set-questions">
77   - <div class="qs-num">
78   - <p class="txt">{{ item.name }}</p>
79   - <p class="num">共{{ item.list.length }}题</p>
80   - </div>
81   - <div class="qs-options">
82   - <p class="ipt">
83   - <el-input
84   - v-model="item.answerList"
85   - @keydown.native="keydownAnswer($event)"
86   - ></el-input>
87   - </p>
88   - <p class="answer-box">
89   - <template v-if="item.list[0].questionType == 4">
90   - <span
91   - class="answer-s active"
92   - @click="
93   - item.answerList.length < item.list.length
94   - ? (item.answerList += '✓')
95   - : ''
96   - "
97   - >✓</span
98   - >
99   - <span
100   - class="answer-s active"
101   - @click="
102   - item.answerList.length < item.list.length
103   - ? (item.answerList += '✗')
104   - : ''
105   - "
106   - >✗</span
107   - >
108   - </template>
109   - <template v-if="item.list[0].questionType == 3">
110   - <span
111   - class="answer-s active"
112   - v-for="option in item.list[0].answerOptions"
113   - :key="option"
114   - @click="setAnswer(item, option)"
115   - >{{ option }}</span
116   - >
117   - <span
118   - class="answer-s active"
119   - @click="
120   - item.answerList.split(',').length < item.list.length
121   - ? (item.answerList += ',')
122   - : ''
123   - "
124   - >,</span
125   - >
126   - </template>
127   - <template
128   - v-if="item.list[0].questionType == 2"
129   - class="answer-box"
130   - >
131   - <span
132   - class="answer-s active"
133   - v-for="option in item.list[0].answerOptions"
134   - :key="option"
135   - @click="
136   - item.answerList.length < item.list.length
137   - ? (item.answerList += option)
138   - : ''
139   - "
140   - >{{ option }}</span
141   - >
142   - </template>
143   - <span
144   - class="answer-s delButton"
145   - @click="item.answerList = item.answerList.slice(0, -1)"
146   - >x</span
147   - >
148   - </p>
149   - </div>
  29 + </p>
  30 + <div class="sub-questions" :key="index" v-else>
  31 + <div class="qs-num">题{{ subQuestions.questionIndex }}</div>
  32 + <div class="qs-options qs-options2">
  33 + <p v-if="subQuestions.questionType == 4" class="answer-box">
  34 + <span
  35 + class="answer-s"
  36 + :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
  37 + @click="subQuestions.correctAnswer = 1"
  38 + >✓</span
  39 + >
  40 + <span
  41 + class="answer-s"
  42 + :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
  43 + @click="subQuestions.correctAnswer = 2"
  44 + >✗</span
  45 + >
  46 + </p>
  47 + <p v-if="subQuestions.questionType == 3" class="answer-box">
  48 + <span
  49 + class="answer-s"
  50 + v-for="option in subQuestions.answerOptions.split(',')"
  51 + :class="
  52 + subQuestions.correctAnswer.includes(option) ? 'active' : ''
  53 + "
  54 + :key="option"
  55 + @click="changAnswer(subQuestions, option)"
  56 + >{{ option }}</span
  57 + >
  58 + </p>
  59 + <p v-if="subQuestions.questionType == 2" class="answer-box">
  60 + <span
  61 + class="answer-s"
  62 + v-for="option in subQuestions.answerOptions.split(',')"
  63 + :class="subQuestions.correctAnswer == option ? 'active' : ''"
  64 + :key="option"
  65 + @click="subQuestions.correctAnswer = option"
  66 + >{{ option }}</span
  67 + >
  68 + </p>
150 69 </div>
151 70 </div>
152 71 </div>
... ... @@ -160,6 +79,84 @@
160 79 >
161 80 </div>
162 81 </div>
  82 + <el-dialog
  83 + title="批量设置答案"
  84 + :visible.sync="diaSetAns"
  85 + width="400"
  86 + :modal-append-to-body="false"
  87 + >
  88 + <div class="qs-options">
  89 + <p>{{ setSubPro(formAns.qusType) }}:</p>
  90 + <p class="ipt">
  91 + <el-input
  92 + v-model="formAns.answerList"
  93 + @keydown.native="keydownAnswer($event)"
  94 + ></el-input>
  95 + </p>
  96 + <p class="answer-box">
  97 + <template v-if="formAns.qusType == 4">
  98 + <span
  99 + class="answer-s active"
  100 + @click="
  101 + formAns.answerList.length < formAns.subNum
  102 + ? (formAns.answerList += '✓')
  103 + : ''
  104 + "
  105 + >✓</span
  106 + >
  107 + <span
  108 + class="answer-s active"
  109 + @click="
  110 + formAns.answerList.length < formAns.subNum
  111 + ? (formAns.answerList += '✗')
  112 + : ''
  113 + "
  114 + >✗</span
  115 + >
  116 + </template>
  117 + <template v-if="formAns.qusType == 3">
  118 + <span
  119 + class="answer-s active"
  120 + v-for="option in formAns.answerOptions.split(',')"
  121 + :key="option"
  122 + @click="setMultiple(formAns, option)"
  123 + >{{ option }}</span
  124 + >
  125 + <span
  126 + class="answer-s active"
  127 + @click="
  128 + formAns.answerList.split(',').length < formAns.subNum
  129 + ? (formAns.answerList += ',')
  130 + : ''
  131 + "
  132 + >,</span
  133 + >
  134 + </template>
  135 + <template v-if="formAns.qusType == 2" class="answer-box">
  136 + <span
  137 + class="answer-s active"
  138 + v-for="option in formAns.answerOptions.split(',')"
  139 + :key="option"
  140 + @click="
  141 + formAns.answerList.length < formAns.subNum
  142 + ? (formAns.answerList += option)
  143 + : ''
  144 + "
  145 + >{{ option }}</span
  146 + >
  147 + </template>
  148 + <span
  149 + class="answer-s delButton"
  150 + @click="formAns.answerList = formAns.answerList.slice(0, -1)"
  151 + >x</span
  152 + >
  153 + </p>
  154 + </div>
  155 + <div class="dialog-footer" slot="footer">
  156 + <el-button @click="saveFormAns">确 定</el-button>
  157 + <el-button @click="diaSetAns = false">取 消</el-button>
  158 + </div>
  159 + </el-dialog>
163 160 </div>
164 161 </template>
165 162  
... ... @@ -174,62 +171,116 @@ export default {
174 171 },
175 172 data() {
176 173 return {
  174 + diaSetAns: false,
177 175 editType: true, //修改答案模式
178 176 FormQuestionList: [],
179   - FormQuestionList2: [],
  177 + FormQuestionList: [],
  178 + formAns: {
  179 + endIndex: 0, //相同题目最后一位题目的questionIndex
  180 + qusType: "", //题目类型
  181 + subNum: 0, //数量
  182 + answerOptions: [], //答案选项
  183 + answerList: "", //答案列表-字符串
  184 + },
180 185 };
181 186 },
182 187 watch: {
183 188 questionList: {
184   - handler: function () {
185   - this.FormQuestionList = deepClone(this.questionList);
186   - this.FormQuestionList2 = [];
187   - console.log(this.questionList);
188   - // 组合每道大题中的相同题目
189   - let questionList = deepClone(this.questionList);
190   - let jsons = {};
191   - let answerOptions = [];
192   - for (let i = 0; i < questionList.length; i++) {
193   - questionList[i].subQuestions.map((items) => {
194   - let txt = this.setSubPro(items.questionType);
195   - if (jsons[txt]) {
196   - jsons[txt].push(items);
  189 + handler: function (val) {
  190 + const questions = deepClone(val).sort((a, b) => {
  191 + return a.questionIndex - b.questionIndex;
  192 + });
  193 + this.FormQuestionList = deepClone(questions);
  194 + let types = [{}];
  195 + let addndex = 0;
  196 + this.FormQuestionList?.map((sub, index) => {
  197 + if (!!sub.questionType) {
  198 + if (sub.questionType == types[addndex].qusType) {
  199 + //同类型批量答案+1
  200 + types[addndex].subNum += 1;
  201 + if (
  202 + types[addndex].answerOptions.length < sub.answerOptions.length
  203 + ) {
  204 + types[addndex].answerOptions = sub.answerOptions;
  205 + }
  206 + types[addndex].answerList += this.setAnswer(
  207 + sub.questionType,
  208 + sub.correctAnswer
  209 + );
  210 + if (index == this.questionList.length - 1) {
  211 + //循环最后类型数量大于等于5,保存批量答案
  212 + if (types[addndex].subNum && types[addndex].subNum >= 5) {
  213 + types[addndex].endIndex = sub.questionIndex;
  214 + types[addndex].index = index;
  215 + }
  216 + }
197 217 } else {
198   - jsons[txt] = [items];
199   - }
200   - if (items.questionType == 2 || items.questionType == 3) {
201   - if (items.answerOptions.length > answerOptions.length) {
202   - answerOptions = items.answerOptions;
  218 + if (types[addndex].subNum && types[addndex].subNum >= 5) {
  219 + //不同类型时如果原有类型数量大于等于5,保存批量答案
  220 + types[addndex].endIndex =
  221 + this.questionList[index - 1].questionIndex;
  222 + types[addndex].index = index;
  223 + addndex += 1;
  224 + types[addndex] = {};
203 225 }
204   - jsons[txt][0].answerOptions = answerOptions;
205   - }
206   - });
207   - console.log(jsons);
208   - }
209   - this.FormQuestionList2 = Object.keys(jsons).map((item) => {
210   - let answerList = "";
211   - jsons[item].map((items, index) => {
212   - if (items.questionType == 2) {
213   - answerList += items.correctAnswer;
214   - } else if (items.questionType == 3) {
215   - answerList +=
216   - items.correctAnswer +
217   - (jsons[item].length - 1 != index ? "," : "");
218   - } else if (items.questionType == 4) {
219   - answerList += items.correctAnswer == 1 ? "✓" : "✗";
  226 + //不同类型初始化批量答案
  227 + types[addndex].qusType = sub.questionType;
  228 + types[addndex].subNum = 1;
  229 + types[addndex].answerOptions = sub.answerOptions;
  230 + types[addndex].answerList = this.setAnswer(
  231 + sub.questionType,
  232 + sub.correctAnswer
  233 + );
220 234 }
221   - });
222   - return {
223   - name: item,
224   - list: jsons[item],
225   - answerList: answerList,
226   - };
  235 + }
227 236 });
  237 + for (let i = 0; i < types.length; i++) {
  238 + if (types[i].qusType == 3) {
  239 + types[i].answerList = types[i].answerList.slice(0, -1);
  240 + }
  241 + if (types[i].subNum >= 5) {
  242 + item.subQuestions.splice(
  243 + types[i].index + i + 1,
  244 + 0,
  245 + deepClone(types[i])
  246 + );
  247 + }
  248 + }
228 249 },
229 250 deep: true,
230 251 },
231 252 },
232 253 methods: {
  254 + setFormAns(indexs) {
  255 + //初始化要修改的答案
  256 + this.formAns = { ...this.FormQuestionList[indexs] };
  257 + this.diaSetAns = true;
  258 + },
  259 + saveFormAns() {
  260 + //批量修改答案
  261 + let EndIndex;
  262 + let subNum = this.formAns.subNum - 1;
  263 + this.FormQuestionList.some((item, index) => {
  264 + if (this.formAns.endIndex == item.questionIndex) {
  265 + EndIndex = index;
  266 + return;
  267 + }
  268 + });
  269 + for (let i = 0; i <= subNum; i++) {
  270 + let correctAnswer = "";
  271 + if (this.formAns.qusType == 2) {
  272 + correctAnswer = this.formAns.answerList[subNum - i];
  273 + } else if (this.formAns.qusType == 3) {
  274 + correctAnswer = this.formAns.answerList.split(",")[subNum - i];
  275 +
  276 + console.log(this.formAns.answerList.split(",")[subNum - i]);
  277 + } else if (this.formAns.qusType == 4) {
  278 + correctAnswer = this.formAns.answerList[subNum - i] == "✓" ? 1 : 2;
  279 + }
  280 + this.questionList[EndIndex - i].correctAnswer = correctAnswer;
  281 + }
  282 + this.diaSetAns = false;
  283 + },
233 284 setSubPro(type) {
234 285 let tit;
235 286 switch (type) {
... ... @@ -270,15 +321,26 @@ export default {
270 321 event.returnValue = "";
271 322 }
272 323 },
273   - setAnswer(obj, answer) {
  324 + setAnswer(type, ans) {
  325 + let txt = "";
  326 + if (type == 2) {
  327 + txt = ans;
  328 + } else if (type == 3) {
  329 + txt = ans + ",";
  330 + } else if (type == 4) {
  331 + txt = ans == 1 ? "✓" : "✗";
  332 + }
  333 + return txt;
  334 + },
  335 + setMultiple(obj, answer) {
274 336 //多选答案设置
275 337 obj.answerList += answer;
276 338 let str = obj.answerList;
277 339 let str2 = checkAnswer(
278 340 str,
279 341 3,
280   - obj.list[0].answerOptions,
281   - obj.list.length
  342 + obj.answerOptions.split(",").length,
  343 + obj.answerList.length
282 344 );
283 345 obj.answerList = str2;
284 346 },
... ... @@ -294,39 +356,16 @@ export default {
294 356 }
295 357 },
296 358 async saveAnswer() {
297   - let questionList = [],
298   - questionList2 = [];
299   - if (this.editType) {
300   - questionList = [...this.FormQuestionList];
301   - } else {
302   - this.FormQuestionList2.map((item) => {
303   - item.list.map((items, index) => {
304   - if (items.questionType == 2 ) {
305   - items.correctAnswer = item.answerList.split("")[index];
306   - } else if (items.questionType == 3) {
307   - items.correctAnswer = item.answerList.split(",")[index];
308   - }else if (items.questionType == 4) {
309   - items.correctAnswer = item.answerList[index] == "✓" ? 1 : 2;
310   - }
311   - questionList2.push(items);
312   - });
313   - });
314   - questionList = this.FormQuestionList.map((item) => {
315   - let subQuestions = item.subQuestions.map((items) => {
316   - items.correctAnswer = questionList2.find((question) => {
317   - return question.questionIndex == items.questionIndex;
318   - })?.correctAnswer;
319   - return items;
320   - });
321   - return {
322   - ...item,
323   - subQuestions: [...subQuestions],
324   - };
325   - });
  359 + let questionList = [];
  360 + for (let i = 0; i < this.FormQuestionList.length; i++) {
  361 + if (this.FormQuestionList[i].qusType) {
  362 + this.FormQuestionList.splice(i, 1);
  363 + i--;
  364 + }
326 365 }
327 366 console.log(questionList);
328   - const { data, status, message } = await this.$request.modifyPaper({
329   - paperId: this.paperId,
  367 + const { data, status, message } = await this.$request.setPeriodAnswer({
  368 + periodId: this.paperId,
330 369 questionList: questionList,
331 370 });
332 371 if (status == 0) {
... ...
src/components/upload.vue
... ... @@ -7,7 +7,7 @@
7 7 ref="upload"
8 8 :action="url"
9 9 :multiple="false"
10   - :data="{ id: id }"
  10 + :data="{ ...query }"
11 11 :with-credentials="true"
12 12 :limit="1"
13 13 :on-change="change"
... ... @@ -34,6 +34,10 @@ export default {
34 34 type: String,
35 35 default: "",
36 36 },
  37 + examId: {
  38 + type: String,
  39 + default: "",
  40 + },
37 41 url: {
38 42 type: String,
39 43 default: "",
... ... @@ -44,6 +48,19 @@ export default {
44 48 default: "模板",
45 49 },
46 50 },
  51 + computed: {
  52 + query: function () {
  53 + if (this.id) {
  54 + return {
  55 + id: this.id,
  56 + };
  57 + } else if (this.examId) {
  58 + return {
  59 + examId: this.examId,
  60 + };
  61 + }
  62 + },
  63 + },
47 64 data() {
48 65 return {
49 66 file: null,
... ...
src/views/ask/analysis.vue
... ... @@ -10,150 +10,413 @@
10 10 <span
11 11 class="tab-item"
12 12 :class="type == 1 ? 'active' : ''"
13   - @click="type = 1"
  13 + @click="setType(1)"
14 14 >答题表现</span
15 15 >
16 16 <span
17 17 class="tab-item"
18 18 :class="type == 2 ? 'active' : ''"
19   - @click="type = 2"
  19 + @click="setType(2)"
20 20 >学生问答表现</span
21 21 >
22 22 <span
23 23 class="tab-item"
24 24 :class="type == 3 ? 'active' : ''"
25   - @click="type = 3"
  25 + @click="setType(3)"
26 26 >学生互动表现</span
27 27 >
28 28 <span
29 29 class="tab-item"
30 30 :class="type == 4 ? 'active' : ''"
31   - @click="type = 4"
  31 + @click="setType(4)"
32 32 >签到明细</span
33 33 >
34 34 </div>
35   - <ul class="info">
36   - <li class="info-item">科目:语文</li>
37   - <li class="info-item">课时:课时1</li>
38   - <li class="info-item">上课时间:2022-11-9 21:30</li>
39   - <li class="info-item">下课时间:2022-11-9 21:30</li>
40   - <li class="info-item">签到人数:45</li>
41   - <li class="info-item">题目总数:8</li>
42   - <li class="info-item">答题总数:8</li>
43   - <li class="info-item">课时时长:45分钟</li>
44   - <li class="info-item">总参与度::80%</li>
45   - <li class="info-item">班级总正确率:82%</li>
46   - <li class="info-item">已答总正确率:89%</li>
47   - <li class="info-item">反馈时长:15分钟</li>
48   - </ul>
49   - <el-table
50   - :data="tableData"
51   - border
52   - style="width: 100%"
53   - :default-sort="{ prop: 'dadui', order: 'descending' }"
54   - >
55   - <el-table-column
56   - prop="questionIndex"
57   - label="题号"
58   - align="center"
59   - ><template slot-scope="scoped">Q{{scoped.row.questionIndex}}</template></el-table-column>
60   - <el-table-column
61   - prop="questionType"
62   - label="题型"
63   - align="center"
64   - ></el-table-column>
65   - <el-table-column
66   - prop="dati"
67   - label="答题人数"
68   - sortable
69   - align="center"
70   - ></el-table-column>
71   - <el-table-column
72   - prop="dadui"
73   - label="答对人数"
74   - sortable
75   - align="center"
76   - ></el-table-column>
77   - <el-table-column
78   - prop="canyu"
79   - label="班级参与度"
80   - sortable
81   - align="center"
82   - ><template slot-scope="scoped">{{scoped.row.canyu}}%</template></el-table-column>
83   - <el-table-column
84   - prop="banjidadui"
85   - label="班级正确率"
86   - sortable
87   - align="center"
88   - ><template slot-scope="scoped">{{scoped.row.banjidadui}}%</template></el-table-column>
89   - <el-table-column
90   - prop="yida"
91   - label="已答正确率"
92   - sortable
93   - align="center"
94   - ><template slot-scope="scoped">{{scoped.row.yida}}%</template></el-table-column>
95   - <el-table-column
96   - prop="correctAnswer"
97   - label="正确答案"
98   - align="center"
99   - ></el-table-column>
100   - <el-table-column
101   - prop="ganrao"
102   - label="干扰答案"
103   - align="center"
104   - ></el-table-column>
105   - </el-table>
  35 + <div v-loading="loading">
  36 + <ul class="info" v-if="type == 1">
  37 + <li class="info-item">科目:{{ detail.subjectName }}</li>
  38 + <li class="info-item">课时:{{ detail.title }}</li>
  39 + <li class="info-item">上课时间:{{ detail.startTime }}</li>
  40 + <li class="info-item">下课时间:{{ detail.endTime }}</li>
  41 + <li class="info-item">签到人数:{{ detail.answeredNum }}</li>
  42 + <li class="info-item">题目总数:{{ detail.questionNum }}</li>
  43 + <li class="info-item">答题总数:{{ detail.totalAnswersNum }}</li>
  44 + <li class="info-item">课时时长:{{ detail.duration / 60 }}分钟</li>
  45 + <li class="info-item">总参与度::{{ detail.participationRate }}%</li>
  46 + <li class="info-item">
  47 + 班级总正确率:{{ detail.classCorrectRate }}%
  48 + </li>
  49 + <li class="info-item">
  50 + 已答总正确率:{{ detail.answerCorrectRate }}%
  51 + </li>
  52 + <li class="info-item">
  53 + 反馈时长:{{ detail.consumingDuration / 60 }}分钟
  54 + </li>
  55 + </ul>
  56 + <el-table v-if="type == 1" :data="tableData" border style="width: 100%">
  57 + <el-table-column prop="questionIndex" label="题号" align="center"
  58 + ><template slot-scope="scoped"
  59 + >Q{{ scoped.row.questionIndex }}</template
  60 + ></el-table-column
  61 + >
  62 + <el-table-column prop="questionType" label="题型" align="center">
  63 + <template slot-scope="scoped">{{
  64 + setSubPro(scoped.row.questionType)
  65 + }}</template>
  66 + </el-table-column>
  67 + <el-table-column
  68 + prop="answeredNum"
  69 + label="答题人数"
  70 + sortable
  71 + align="center"
  72 + ></el-table-column>
  73 + <el-table-column
  74 + prop="correctAnswerNum"
  75 + label="答对人数"
  76 + sortable
  77 + align="center"
  78 + ></el-table-column>
  79 + <el-table-column
  80 + prop="canyu"
  81 + label="班级参与度"
  82 + sortable
  83 + align="center"
  84 + ><template slot-scope="scoped"
  85 + >{{ scoped.row.canyu }}%</template
  86 + ></el-table-column
  87 + >
  88 + <el-table-column
  89 + prop="classCorrectRate"
  90 + label="班级正确率"
  91 + sortable
  92 + align="center"
  93 + ><template slot-scope="scoped"
  94 + >{{ scoped.row.classCorrectRate }}%</template
  95 + ></el-table-column
  96 + >
  97 + <el-table-column
  98 + prop="answerCorrectRate"
  99 + label="已答正确率"
  100 + sortable
  101 + align="center"
  102 + ><template slot-scope="scoped"
  103 + >{{ scoped.row.answerCorrectRate }}%</template
  104 + ></el-table-column
  105 + >
  106 + <el-table-column
  107 + prop="correctAnswer"
  108 + label="正确答案"
  109 + align="center"
  110 + ></el-table-column>
  111 + <el-table-column
  112 + prop="fallible"
  113 + label="干扰答案"
  114 + align="center"
  115 + ></el-table-column>
  116 + <el-table-column prop="screenshot" label="题干" align="center">
  117 + <template slot-scope="scoped">
  118 + <el-image
  119 + style="width: 60px; height: 40px"
  120 + :src="scoped.row.screenshot"
  121 + :preview-src-list="[scoped.row.screenshot]"
  122 + >
  123 + </el-image></template
  124 + ></el-table-column>
  125 + </el-table>
  126 + <el-table v-if="type == 2" :data="tableData" border style="width: 100%">
  127 + <el-table-column
  128 + prop="studentCode"
  129 + label="学号"
  130 + align="center"
  131 + ></el-table-column>
  132 + <el-table-column
  133 + prop="studentName"
  134 + label="姓名"
  135 + align="center"
  136 + ></el-table-column>
  137 + <el-table-column
  138 + prop="answerTimes"
  139 + label="答题次数"
  140 + align="center"
  141 + ></el-table-column>
  142 + <el-table-column
  143 + prop="correctAnswerNum"
  144 + label="答题耗时"
  145 + align="center"
  146 + ></el-table-column>
  147 + <el-table-column
  148 + prop="correctAnswerTimes"
  149 + label="答对次数"
  150 + align="center"
  151 + ></el-table-column>
  152 + <el-table-column
  153 + prop="participationRate"
  154 + label="参与度"
  155 + sortable
  156 + align="center"
  157 + ><template slot-scope="scoped"
  158 + >{{ scoped.row.participationRate }}%</template
  159 + ></el-table-column
  160 + >
  161 + <el-table-column
  162 + prop="correctRate"
  163 + label="正确率"
  164 + sortable
  165 + align="center"
  166 + ><template slot-scope="scoped"
  167 + >{{ scoped.row.correctRate }}%</template
  168 + ></el-table-column
  169 + >
  170 + <el-table-column
  171 + prop="answerCorrectRate"
  172 + label="已答正确率"
  173 + sortable
  174 + align="center"
  175 + ><template slot-scope="scoped"
  176 + >{{ scoped.row.answerCorrectRate }}%</template
  177 + ></el-table-column
  178 + >
  179 + </el-table>
  180 + <el-table v-if="type == 3" :data="tableData" border style="width: 100%">
  181 + <el-table-column
  182 + prop="studentCode"
  183 + label="学号"
  184 + align="center"
  185 + ></el-table-column>
  186 + <el-table-column
  187 + prop="studentName"
  188 + label="姓名"
  189 + align="center"
  190 + ></el-table-column>
  191 + <el-table-column
  192 + prop="rushAnswerTimes"
  193 + label="抢答成功次数"
  194 + sortable
  195 + align="center"
  196 + ></el-table-column>
  197 + <el-table-column
  198 + prop="rushAnswerCorrectTimes"
  199 + label="答对次数"
  200 + sortable
  201 + align="center"
  202 + ></el-table-column>
  203 + <el-table-column
  204 + prop="checkAnswerTimes"
  205 + label="抽答次数"
  206 + sortable
  207 + align="center"
  208 + ></el-table-column>
  209 + <el-table-column
  210 + prop="checkAnswerCorrectTimes"
  211 + label="抽答答对次数"
  212 + sortable
  213 + align="center"
  214 + ></el-table-column>
  215 + <el-table-column
  216 + prop="interactionsNum"
  217 + label="参与得分"
  218 + sortable
  219 + align="center"
  220 + ></el-table-column>
  221 + <el-table-column
  222 + prop="interactionsCorrectNum"
  223 + label="对错得分"
  224 + sortable
  225 + align="center"
  226 + ></el-table-column>
  227 + </el-table>
  228 + <el-table v-if="type == 4" :data="tableData" border style="width: 100%">
  229 + <el-table-column
  230 + prop="studentName"
  231 + label="姓名"
  232 + align="center"
  233 + ></el-table-column>
  234 + <el-table-column
  235 + prop="checkInTime"
  236 + label="签到时间"
  237 + sortable
  238 + align="center"
  239 + ></el-table-column>
  240 + <el-table-column
  241 + prop="makeUpTime"
  242 + label="补签时间"
  243 + sortable
  244 + align="center"
  245 + ></el-table-column>
  246 + </el-table>
  247 + <div class="pagination-box" v-show="type == 1">
  248 + <el-pagination
  249 + small=""
  250 + layout="total,prev, pager, next"
  251 + :hide-on-single-page="true"
  252 + :total="total"
  253 + @current-change="changePage"
  254 + :current-page="page"
  255 + :page-size="size"
  256 + >
  257 + </el-pagination>
  258 + </div>
  259 + <p class="down">
  260 + <el-button
  261 + @click="exportData"
  262 + type="info"
  263 + plain
  264 + round
  265 + icon="fa fa-cloud-download"
  266 + >导出报表</el-button
  267 + >
  268 + <el-button @click="edit" type="primary" round>设置答案</el-button>
  269 + </p>
  270 + </div>
106 271 </div>
  272 +
  273 + <set-answer
  274 + :diaVisible="dialogVisible"
  275 + :questionList="form.questionList"
  276 + :paperId="form.id"
  277 + @saveSuccess="handleSuccess"
  278 + @cancel="cancel"
  279 + />
107 280 </div>
108 281 </template>
109 282  
110 283 <script>
  284 +import { downloadFile } from "@/utils";
111 285 export default {
112 286 data() {
113 287 return {
  288 + dialogVisible: false,
  289 + loading: false,
114 290 id: "",
115 291 type: 1,
116   - tableData: [
117   - {
118   - questionIndex: 1,
119   - questionType: "单选题",
120   - dati: 5,
121   - dadui: 60,
122   - canyu: 50,
123   - banjidadui: 80,
124   - yida: 90,
125   - correctAnswer:"A",
126   - ganrao:"C"
127   - },
128   - {
129   - questionIndex: 2,
130   - questionType: "单选题",
131   - dati: 6,
132   - dadui: 80,
133   - canyu: 60,
134   - banjidadui: 90,
135   - yida: 100,
136   - correctAnswer:"B",
137   - ganrao:"D"
138   - },
139   - ],
  292 + form: {
  293 + id: "",
  294 + questionList: [],
  295 + },
  296 + detail: {},
  297 + tableData: [],
  298 + page: 1,
  299 + size: 20,
  300 + total: 0,
140 301 };
141 302 },
142 303 created() {
143 304 this.id = this.$route.query.id;
144   - // this._QueryData()
  305 + this._QueryData();
  306 + this.periodDetail();
145 307 },
146 308 methods: {
  309 + setType(type) {
  310 + this.type = type;
  311 + this.page = 1;
  312 + this._QueryData();
  313 + },
  314 + setSubPro(type) {
  315 + let tit;
  316 + switch (type) {
  317 + case 2:
  318 + tit = "单选题";
  319 + break;
  320 + case 3:
  321 + tit = "多选题";
  322 + break;
  323 + case 4:
  324 + tit = "判断题";
  325 + break;
  326 + case 5:
  327 + tit = "主观题";
  328 + break;
  329 + default:
  330 + tit = "其他";
  331 + }
  332 + return tit;
  333 + },
  334 + cancel() {
  335 + this.dialogVisible = false;
  336 + },
  337 + handleSuccess() {
  338 + this.dialogVisible = false;
  339 + },
  340 + async edit() {
  341 + if (this.editLoading) return;
  342 + this.editLoading = true;
  343 + const { data, status, info } = await this.$request.periodQuestionList({
  344 + examId: this.id,
  345 + });
  346 + this.editLoading = false;
  347 + if (status === 0) {
  348 + this.form.id = this.id;
  349 + this.form.questionList = (data.list && [...data.list]) || [];
  350 + this.dialogVisible = true;
  351 + } else {
  352 + this.$message.error(info);
  353 + }
  354 + },
  355 + changePage(page) {
  356 + this.page = page;
  357 + this._QueryData();
  358 + },
  359 + async periodDetail() {
  360 + let { data, info, status } = await this.$request.periodDetail({
  361 + periodId: this.id,
  362 + });
  363 + if (status == 0) {
  364 + this.detail = { ...data };
  365 + } else {
  366 + this.$message.error(info);
  367 + }
  368 + },
147 369 async _QueryData() {
148   - let { data, info, status } = this.$request.quizDetail({
149   - id: this.id,
  370 + const queryData =
  371 + this.type == 1
  372 + ? this.$request.periodQuestionReport
  373 + : this.$request.periodStudentReport;
  374 + let query = {};
  375 + if (this.type == 2) {
  376 + query.type = 1;
  377 + } else if (this.type == 3) {
  378 + query.type = 2;
  379 + } else if (this.type == 4) {
  380 + query.type = 3;
  381 + }
  382 + this.loading = true;
  383 + let { data, info, status } = await queryData({
  384 + periodId: this.id,
  385 + page: this.page,
  386 + size: this.size,
  387 + ...query,
150 388 });
  389 + this.loading = false;
  390 + if (status === 0) {
  391 + this.tableData = [...data?.list];
  392 + this.total = data.count;
  393 + } else {
  394 + this.$message.error(info);
  395 + }
  396 + },
  397 + //导出
  398 + async exportData() {
  399 + // if (this.exportLoading = true) return;
  400 + this.exportLoading = true;
  401 + const { data, status, info } = await this.$request.exportData();
  402 + this.exportLoading = false;
  403 + if (data) {
  404 + downloadFile(this.detail.title + "报表", data);
  405 + } else {
  406 + this.$message.error(info);
  407 + }
151 408 },
152 409 },
153 410 };
154 411 </script>
155 412  
156 413 <style lang="scss" scoped>
  414 +.down {
  415 + padding-top: 20px;
  416 + width: 100%;
  417 + display: flex;
  418 + justify-content: space-between;
  419 +}
157 420 .page-content {
158 421 padding: 20px 20px 0;
159 422 }
... ...
src/views/ask/index.vue
... ... @@ -25,7 +25,7 @@
25 25 v-if="role == 'ROLE_BANZHUREN'"
26 26 class="sel"
27 27 multiple
28   - v-model="query.subjectId"
  28 + v-model="query.subjectNames"
29 29 placeholder="选择科目"
30 30 @change="_QueryData"
31 31 >
... ... @@ -40,7 +40,7 @@
40 40 <el-select
41 41 v-else
42 42 class="sel"
43   - v-model="query.subjectId"
  43 + v-model="query.subjectNames"
44 44 placeholder="选择科目"
45 45 @change="_QueryData"
46 46 >
... ... @@ -89,60 +89,78 @@
89 89 </div>
90 90 </div>
91 91 <div class="table-box">
92   - <el-radio-group v-model="tabIndex" style="margin-bottom: 20px">
  92 + <el-radio-group
  93 + v-model="tabIndex"
  94 + @change="tabChange"
  95 + style="margin-bottom: 20px"
  96 + >
93 97 <el-radio-button :label="1">单课时报表</el-radio-button>
94   - <el-radio-button :label="2" v-if="this.role != 'ROLE_BANZHUREN'"
  98 + <!-- <el-radio-button :label="2" v-if="this.role != 'ROLE_BANZHUREN'"
95 99 >阶段问答报表</el-radio-button
  100 + > -->
  101 + <el-radio-button :label="2" v-if="query.startDay != query.endDay"
  102 + >阶段问答报表</el-radio-button
  103 + >
  104 + <el-radio-button :label="3" v-if="query.startDay != query.endDay"
  105 + >阶段互动报表</el-radio-button
96 106 >
97   - <el-radio-button :label="3">阶段互动报表</el-radio-button>
98 107 </el-radio-group>
99   - <p class="table-tit" v-if="tabIndex != 1">
  108 + <!-- <p class="table-tit" v-if="tabIndex != 1">
100 109 <span>总课时数:10</span>
101 110 <span>互动总数:22</span>
102   - </p>
  111 + </p> -->
103 112 <div v-if="tabIndex == 1">
104 113 <el-table
105 114 :data="tableData"
106 115 border
107 116 style="width: 100%"
108   - :default-sort="{ prop: 'canyudu', order: 'descending' }"
  117 + @sort-change="sortChange"
109 118 >
110 119 <el-table-column
111   - prop="keshi"
  120 + prop="title"
112 121 label="课时"
113 122 align="center"
114 123 ></el-table-column>
115 124 <el-table-column
116   - prop="zongshu"
  125 + prop="questionNum"
117 126 label="题目总数"
118 127 align="center"
119 128 width="100"
120 129 ></el-table-column>
121 130 <el-table-column
122   - prop="shijian"
  131 + prop="startTime"
123 132 label="上课时间"
124 133 align="center"
125 134 ></el-table-column>
126 135 <el-table-column
127   - prop="canyudu"
  136 + prop="participationRate"
128 137 label="参与度"
129   - sortable
  138 + sortable="custom"
130 139 align="center"
131   - > <template slot-scope="scoped">{{scoped.row.canyudu}}%</template></el-table-column>
  140 + >
  141 + <template slot-scope="scoped"
  142 + >{{ scoped.row.participationRate }}%</template
  143 + ></el-table-column
  144 + >
132 145 <el-table-column
133   - prop="zhengque"
  146 + prop="answerCorrectRate"
134 147 label="已答总正确率"
135   - sortable
  148 + sortable="custom"
136 149 align="center"
137 150 >
138   - <template slot-scope="scoped">{{scoped.row.zhengque}}%</template>
  151 + <template slot-scope="scoped"
  152 + >{{ scoped.row.answerCorrectRate }}%</template
  153 + >
139 154 </el-table-column>
140 155 <el-table-column
141   - prop="allzheng"
  156 + prop="correctRate"
142 157 label="班级总正确率"
143   - sortable
  158 + sortable="custom"
144 159 align="center"
145   - ><template slot-scope="scoped">{{scoped.row.allzheng}}%</template></el-table-column>
  160 + ><template slot-scope="scoped"
  161 + >{{ scoped.row.correctRate }}%</template
  162 + ></el-table-column
  163 + >
146 164 <el-table-column label="操作" align="center">
147 165 <template slot-scope="scoped">
148 166 <el-tooltip effect="dark" content="详情" placement="top">
... ... @@ -169,56 +187,66 @@
169 187 </div>
170 188 <div v-if="tabIndex == 2">
171 189 <el-table
172   - :data="tableAsk"
  190 + :data="tableData"
173 191 border
174 192 style="width: 100%"
175   - :default-sort="{ prop: 'cishu', order: 'descending' }"
  193 + :default-sort="{ prop: 'answerTimes', order: 'descending' }"
176 194 >
177 195 <el-table-column
178   - prop="xuehao"
  196 + prop="studentCode"
179 197 label="学号"
180 198 align="center"
181 199 ></el-table-column>
182 200 <el-table-column
183   - prop="xingming"
  201 + prop="studentName"
184 202 label="姓名"
185 203 align="center"
186 204 width="100"
187 205 ></el-table-column>
188 206 <el-table-column
189   - prop="cishu"
  207 + prop="answerTimes"
190 208 label="累计答题次数"
191 209 sortable
192 210 align="center"
193 211 ></el-table-column>
194 212 <el-table-column
195   - prop="dadui"
  213 + prop="correctAnswerTimes"
196 214 label="累计答对次数"
197 215 sortable
198 216 align="center"
199 217 ></el-table-column>
200 218 <el-table-column
201   - prop="canyudu"
  219 + prop="participationRate"
202 220 label="总参与度"
203 221 sortable
204 222 align="center"
205   - > <template slot-scope="scoped">{{scoped.row.canyudu}}%</template></el-table-column>
  223 + >
  224 + <template slot-scope="scoped"
  225 + >{{ scoped.row.participationRate }}%</template
  226 + ></el-table-column
  227 + >
206 228 <el-table-column
207   - prop="allzheng"
  229 + prop="correctRate"
208 230 label="总正确率"
209 231 sortable
210 232 align="center"
211   - > <template slot-scope="scoped">{{scoped.row.allzheng}}%</template></el-table-column>
  233 + >
  234 + <template slot-scope="scoped"
  235 + >{{ scoped.row.correctRate }}%</template
  236 + ></el-table-column
  237 + >
212 238 <el-table-column
213   - prop="yidazheng"
  239 + prop="answerCorrectRate"
214 240 label="已答总正确率"
215 241 sortable
216 242 align="center"
217 243 >
218   - <template slot-scope="scoped">{{scoped.row.yidazheng}}%</template>
  244 + <template slot-scope="scoped"
  245 + >{{ scoped.row.answerCorrectRate }}%</template
  246 + >
219 247 </el-table-column>
220 248 <el-table-column
221   - prop="zongpaiming"
  249 + prop="classRank"
222 250 label="总正确率班排名"
223 251 sortable
224 252 align="center"
... ... @@ -227,42 +255,42 @@
227 255 </div>
228 256 <div v-if="tabIndex == 3">
229 257 <el-table
230   - :data="tableAsk"
  258 + :data="tableData"
231 259 border
232 260 style="width: 100%"
233   - :default-sort="{ prop: 'cishu', order: 'descending' }"
  261 + :default-sort="{ prop: 'answerTimes', order: 'descending' }"
234 262 >
235 263 <el-table-column
236   - prop="xuehao"
  264 + prop="studentCode"
237 265 label="学号"
238 266 align="center"
239 267 ></el-table-column>
240 268 <el-table-column
241   - prop="xingming"
  269 + prop="studentName"
242 270 label="姓名"
243 271 align="center"
244 272 width="100"
245 273 ></el-table-column>
246 274 <el-table-column
247   - prop="cishu"
  275 + prop="rushAnswerTimes"
248 276 label="抢答成功次数"
249 277 sortable
250 278 align="center"
251 279 ></el-table-column>
252 280 <el-table-column
253   - prop="dadui"
254   - label="答对次数"
  281 + prop="rushAnswerCorrectTimes"
  282 + label="抢答答对次数"
255 283 sortable
256 284 align="center"
257 285 ></el-table-column>
258 286 <el-table-column
259   - prop="chouda"
  287 + prop="checkAnswerTimes"
260 288 label="抽答次数"
261 289 sortable
262 290 align="center"
263 291 ></el-table-column>
264 292 <el-table-column
265   - prop="choudadui"
  293 + prop="checkAnswerCorrectTimes"
266 294 label="抽答答对次数"
267 295 sortable
268 296 align="center"
... ... @@ -281,218 +309,79 @@
281 309 ></el-table-column>
282 310 </el-table>
283 311 </div>
284   - <p class="down" v-if="tabIndex == 3||tabIndex == 2">
285   - <el-button type="info" plain round icon="fa fa-cloud-download">导出报表</el-button>
  312 + <div class="pagination-box" v-show="tabIndex == 1">
  313 + <el-pagination
  314 + small=""
  315 + layout="total,prev, pager, next"
  316 + :hide-on-single-page="true"
  317 + :total="total"
  318 + @current-change="changePage"
  319 + :current-page="page"
  320 + :page-size="size"
  321 + >
  322 + </el-pagination>
  323 + </div>
  324 + <p class="down" v-if="tabIndex == 3 || tabIndex == 2">
  325 + <el-button
  326 + @click="exportData"
  327 + type="info"
  328 + plain
  329 + round
  330 + icon="fa fa-cloud-download"
  331 + >导出报表</el-button
  332 + >
286 333 </p>
287 334 </div>
288   - <set-answer :diaVisible="dialogVisible" :questionList="form.questionList" :paperId="form.id" @saveSuccess="handleSuccess" @cancel="cancel"/>
  335 + <set-answer
  336 + :diaVisible="dialogVisible"
  337 + :questionList="form.questionList"
  338 + :paperId="form.id"
  339 + @saveSuccess="handleSuccess"
  340 + @cancel="cancel"
  341 + />
289 342 </div>
290 343 </template>
291 344  
292 345 <script>
293   -import { formatDate, deepClone, checkAnswer } from "utils";
  346 +import { formatDate, deepClone, downloadFile } from "utils";
294 347 export default {
295 348 data() {
296 349 return {
297 350 role: "",
298 351 loading: false,
299   - dialogVisible:false,
  352 + dialogVisible: false,
300 353 form: { questionList: [] },
301 354 date: "", //今天-昨天-本周
302 355 query: {
303 356 //搜索条件
304 357 classId: "",
305   - subjectId: "",
  358 + subjectNames: "",
306 359 startDay: "",
307 360 endDay: "",
308 361 day: "",
309 362 },
  363 + custom: {
  364 + //单课时排序
  365 + orderField: null,
  366 + orderType: null,
  367 + },
310 368 classList: [], //班级
311 369 subjectList: [], //科目
312 370 tabIndex: 1, //选项卡
313   - tableData: [
314   - //单课时报表
315   - {
316   - id: 1,
317   - keshi: "课时一",
318   - zongshu: 10,
319   - shijian: "2022-11-9 21:30至22:30",
320   - canyudu: 60,
321   - zhengque: 90,
322   - allzheng: 80,
323   - questionList: [
324   - {
325   - questionTitle: "f",
326   - score: 1,
327   - subQuestions: [
328   - {
329   - questionIndex: 1,
330   - questionType: 2,
331   - score: 1,
332   - partScore: 0,
333   - selectNum: 4,
334   - answerOptions: ["A", "B", "C", "D"],
335   - correctAnswer: "B",
336   - },
337   - {
338   - questionIndex: 2,
339   - questionType: 2,
340   - score: 1,
341   - partScore: 0,
342   - selectNum: 4,
343   - answerOptions: ["A", "B", "C", "D", "E", "F"],
344   - correctAnswer: "A",
345   - },
346   - {
347   - questionIndex: 3,
348   - questionType: 3,
349   - score: 1,
350   - partScore: 0,
351   - selectNum: 4,
352   - answerOptions: ["A", "B", "C", "D", "E", "F"],
353   - correctAnswer: "AB",
354   - },
355   - {
356   - questionIndex: 4,
357   - questionType: 3,
358   - score: 1,
359   - partScore: 0,
360   - selectNum: 4,
361   - answerOptions: ["A", "B", "C", "D", "E", "F"],
362   - correctAnswer: "AB",
363   - },
364   - {
365   - questionIndex: 5,
366   - questionType: 4,
367   - score: 1,
368   - partScore: 0,
369   - selectNum: 0,
370   - answerOptions: [],
371   - correctAnswer: "1",
372   - },
373   - ],
374   - },
375   - {
376   - questionTitle: "f",
377   - score: 1,
378   - subQuestions: [
379   - {
380   - questionIndex: 6,
381   - questionType: 2,
382   - score: 1,
383   - partScore: 0,
384   - selectNum: 4,
385   - answerOptions: ["A", "B", "C", "D"],
386   - correctAnswer: "B",
387   - },
388   - {
389   - questionIndex: 7,
390   - questionType: 2,
391   - score: 1,
392   - partScore: 0,
393   - selectNum: 4,
394   - answerOptions: ["A", "B", "C", "D", "E", "F"],
395   - correctAnswer: "A",
396   - },
397   - {
398   - questionIndex: 8,
399   - questionType: 3,
400   - score: 1,
401   - partScore: 0,
402   - selectNum: 4,
403   - answerOptions: ["A", "B", "C", "D", "E", "F"],
404   - correctAnswer: "AB",
405   - },
406   - {
407   - questionIndex: 9,
408   - questionType: 3,
409   - score: 1,
410   - partScore: 0,
411   - selectNum: 4,
412   - answerOptions: ["A", "B", "C", "D", "E", "F"],
413   - correctAnswer: "AB",
414   - },
415   - {
416   - questionIndex: 10,
417   - questionType: 4,
418   - score: 1,
419   - partScore: 0,
420   - selectNum: 0,
421   - answerOptions: [],
422   - correctAnswer: "1",
423   - },
424   - ],
425   - },
426   - ],
427   - },
428   - {
429   - id: 2,
430   - keshi: "课时二",
431   - zongshu: 8,
432   - shijian: "2022-11-10 21:30至22:30",
433   - canyudu: 70,
434   - zhengque: 80,
435   - allzheng: 60,
436   - questionList: [
437   - {
438   - questionTitle: "a",
439   - score: 1,
440   - subQuestions: [
441   - {
442   - questionIndex: 2,
443   - questionType: 3,
444   - score: 1,
445   - partScore: 0,
446   - selectNum: 4,
447   - answerOptions: ["A", "B", "C", "D"],
448   - correctAnswer: "A,C",
449   - },
450   - ],
451   - },
452   - ],
453   - },
454   - ],
455   - tableAsk: [
456   - {
457   - xuehao: 1,
458   - xingming: "丁芳菲",
459   - cishu: 5,
460   - dadui: 60,
461   - canyudu: 90,
462   - allzheng: 80,
463   - yidazheng: 50,
464   - zongpaiming: 5,
465   - },
466   - {
467   - xuehao: 1,
468   - xingming: "丁芳菲2",
469   - cishu: 3,
470   - dadui: 20,
471   - canyudu: 80,
472   - allzheng: 60,
473   - yidazheng: 65,
474   - zongpaiming: 4,
475   - },
476   - ],
477   - tableStage: [
478   - {
479   - xuehao: 1,
480   - xingming: "丁芳菲",
481   - cishu: 5,
482   - dadui: 60,
483   - chouda: 90,
484   - choudadui: 80,
485   - canyu: 50,
486   - duicuo: 5,
487   - },
488   - ],
  371 + tableData: [],
  372 + page: 1,
  373 + size: 20,
  374 + total: 0,
489 375 };
490 376 },
491 377 async created() {
492   - this.role = this.$store.getters.info.permissions.find(item=>item.roleName == this.$store.getters.info.showRoleName)?.role;
  378 + this.role = this.$store.getters.info.permissions.find(
  379 + (item) => item.roleName == this.$store.getters.info.showRoleName
  380 + )?.role;
  381 + this.query.subjectNames = this.role == "ROLE_BANZHUREN" ? [] : "";
493 382 await this._QueryClassList();
494 383 await this._QuerySubjectList();
495   - // await this.setDate(1);
  384 + await this.setDate(1);
496 385 let startDay = this.query?.startDay;
497 386 if (!startDay) {
498 387 this.query.startDay = new Date();
... ... @@ -509,8 +398,7 @@ export default {
509 398 },
510 399 });
511 400 },
512   -
513   - setDate(index) {
  401 + setDate(index) {
514 402 const that = this;
515 403 this.date = index == this.date ? "" : index;
516 404 let aYear = new Date().getFullYear();
... ... @@ -540,7 +428,7 @@ export default {
540 428 that.query.endDay = formatDate(new Date(), "yyyy-MM-dd");
541 429 break;
542 430 case 4:
543   - if (aMonth > 1 && aMonth < 4) {
  431 + if (aMonth > 0 && aMonth < 4) {
544 432 aMonth = "01";
545 433 } else if (aMonth > 3 && aMonth < 7) {
546 434 aMonth = "04";
... ... @@ -578,23 +466,57 @@ export default {
578 466 }
579 467 }
580 468 },
581   - edit(item) {
582   - this.form = deepClone(item);
583   - this.dialogVisible = true;
  469 + async edit(item) {
  470 + if (this.editLoading) return;
  471 + this.editLoading = true;
  472 + const { data, status, info } = await this.$request.periodQuestionList({
  473 + periodId: item.id,
  474 + });
  475 + this.editLoading = false;
  476 + if (status === 0) {
  477 + this.form.id = item.id;
  478 + this.form.questionList = (data.list && [...data.list]) || [];
  479 + this.dialogVisible = true;
  480 + } else {
  481 + this.$message.error(info);
  482 + }
584 483 },
585   - cancel(){
586   - this.dialogVisible = false
  484 + cancel() {
  485 + this.dialogVisible = false;
587 486 },
588   - handleSuccess(){
589   - this.dialogVisible = false
590   - this._QueryData()
  487 + handleSuccess() {
  488 + this.dialogVisible = false;
  489 + },
  490 + tabChange() {
  491 + this.page = 1;
  492 + this._QueryData();
  493 + },
  494 + sortChange(obj) {
  495 + this.custom.orderField =
  496 + obj.prop == "participationRate"
  497 + ? 1
  498 + : obj.prop == "answerCorrectRate"
  499 + ? 2
  500 + : 3;
  501 + this.custom.orderType = obj.order == "ascending" ? 0 : 1;
  502 + this.page = 1;
  503 + this._QueryData();
  504 + },
  505 + changePage(page) {
  506 + this.page = page;
  507 + this._QueryData();
591 508 },
592 509 async changClazz() {
593 510 await this._QuerySubjectList();
594   - await this.setDate(1);
  511 + // await this.setDate(1);
  512 + this._QueryData()
595 513 },
596 514 async _QueryClassList() {
597   - const { data, status, info } = await this.$request.fetchClassList();
  515 + const fetchClassList =
  516 + this.role == "ROLE_BANZHUREN"
  517 + ? this.$request.cTClassList
  518 + : this.$request.tClassList;
  519 + const { data, status, info } = await fetchClassList();
598 520 if (status === 0) {
599 521 this.classList = data.list.map((item) => {
600 522 return {
... ... @@ -608,43 +530,170 @@ export default {
608 530 }
609 531 },
610 532 async _QuerySubjectList() {
611   - const { data, status, info } = await this.$request.fetchSubjectList(
612   - {classId: this.query.classId,}
613   - );
  533 + const fetchSubjectList =
  534 + this.role == "ROLE_BANZHUREN"
  535 + ? this.$request.cTSubjectList
  536 + : this.$request.tSubjectList;
  537 +
  538 + const { data, status, info } = await fetchSubjectList({
  539 + classId: this.query.classId,
  540 + });
614 541 if (status === 0) {
615   - this.subjectList = data.subjectNames?.map((item) => {
616   - return {
617   - value: item,
618   - label: item,
619   - };
620   - })||[];
  542 + this.subjectList =
  543 + data.subjectNames?.map((item) => {
  544 + return {
  545 + value: item,
  546 + label: item,
  547 + };
  548 + }) || [];
621 549 if (this.role == "ROLE_BANZHUREN") {
622 550 this.subjectList.unshift({
623   - value: "",
  551 + value: "全部",
624 552 label: "全部",
625 553 });
626   - this.query.subjectId = [this.subjectList[0]?.value];
627   - }else{
628   - this.query.subjectId = this.subjectList[0]?.value;
  554 + this.query.subjectNames.push(this.subjectList[0]?.value);
  555 + } else {
  556 + this.query.subjectNames = this.subjectList[0]?.value;
629 557 }
630 558 } else {
631 559 this.$message.error(info);
632 560 }
633 561 },
634 562 async _QueryData() {
  563 + if (this.tabIndex == 1) {
  564 + this.periodReportList();
  565 + } else if (this.tabIndex == 2) {
  566 + this.phaseAnswerReport();
  567 + } else if (this.tabIndex == 3) {
  568 + this.phaseInteractiveReport();
  569 + }
  570 + },
  571 + //分页查询课时报表列表
  572 + async periodReportList() {
635 573 this.loading = true;
636   - //多课时对比
637 574 let query = {};
638 575 for (let key in this.query) {
639 576 if (this.query[key] != "") {
640 577 query[key] = this.query[key];
641 578 }
642 579 }
643   - const { data, status, info } = await this.$request.fetchQuizList({
  580 + if (this.custom.orderField !== null) {
  581 + query = { ...query, ...this.custom };
  582 + }
  583 + if (this.role != "ROLE_BANZHUREN") {
  584 + query.subjectNames = [query.subjectNames];
  585 + } else {
  586 + if (
  587 + query["subjectNames"].length == 1 &&
  588 + query["subjectNames"][0] == "全部"
  589 + ) {
  590 + query["subjectNames"] = this.subjectList.map((item) => {
  591 + return item.value;
  592 + });
  593 + query["subjectNames"].shift();
  594 + }
  595 + }
  596 + const { data, status, info } = await this.$request.periodReportList({
  597 + ...query,
  598 + page: this.page,
  599 + size: this.size,
  600 + });
  601 + this.loading = false;
  602 + if (status === 0) {
  603 + this.tableData = (data?.list && [...data?.list]) || [];
  604 + this.total = data.count;
  605 + } else {
  606 + this.$message.error(info);
  607 + }
  608 + },
  609 + //查询阶段问答报表
  610 + async phaseAnswerReport() {
  611 + this.loading = true;
  612 + let query = {};
  613 + for (let key in this.query) {
  614 + if (this.query[key] != "") {
  615 + if (key == "subjectNames" && this.role != "ROLE_BANZHUREN") {
  616 + query["subjectName"] = this.query[key];
  617 + } else {
  618 + query[key] = this.query[key];
  619 + }
  620 + }
  621 + }
  622 + if (this.role == "ROLE_BANZHUREN") {
  623 + if (
  624 + query["subjectNames"].length == 1 &&
  625 + query["subjectNames"][0] == "全部"
  626 + ) {
  627 + query["subjectNames"] = this.subjectList.map((item) => {
  628 + return item.value;
  629 + });
  630 + query["subjectNames"].shift();
  631 + }
  632 + }
  633 + const phaseAnswerReport =
  634 + this.role == "ROLE_BANZHUREN"
  635 + ? this.$request.cTPhaseAnswerReport
  636 + : this.$request.phaseAnswerReport;
  637 +
  638 + const { data, status, info } = await phaseAnswerReport({
644 639 ...query,
645 640 });
646 641 this.loading = false;
647 642 if (status === 0) {
  643 + this.tableData = (data?.list && [...data?.list]) || [];
  644 + this.total = data.count;
  645 + } else {
  646 + this.$message.error(info);
  647 + }
  648 + },
  649 + //查询阶段互动报表
  650 + async phaseInteractiveReport() {
  651 + this.loading = true;
  652 + let query = {};
  653 + for (let key in this.query) {
  654 + if (this.query[key] != "") {
  655 + if (key == "subjectNames" && this.role != "ROLE_BANZHUREN") {
  656 + query["subjectName"] = this.query[key];
  657 + } else {
  658 + query[key] = this.query[key];
  659 + }
  660 + }
  661 + }
  662 + if (this.role == "ROLE_BANZHUREN") {
  663 + if (
  664 + query["subjectNames"].length == 1 &&
  665 + query["subjectNames"][0] == "全部"
  666 + ) {
  667 + query["subjectNames"] = this.subjectList.map((item) => {
  668 + return item.value;
  669 + });
  670 + query["subjectNames"].shift();
  671 + }
  672 + }
  673 + const phaseInteractiveReport =
  674 + this.role == "ROLE_BANZHUREN"
  675 + ? this.$request.cTPhaseInteractiveReport
  676 + : this.$request.phaseInteractiveReport;
  677 +
  678 + const { data, status, info } = await phaseInteractiveReport({
  679 + ...query,
  680 + });
  681 + this.loading = false;
  682 + if (status === 0) {
  683 + this.tableData = (data?.list && [...data?.list]) || [];
  684 + this.total = data.count;
  685 + } else {
  686 + this.$message.error(info);
  687 + }
  688 + },
  689 + //导出
  690 + async exportData() {
  691 + if ((this.exportLoading = true)) return;
  692 + this.exportLoading = true;
  693 + const { data, status, info } = await this.$request.exportData();
  694 + this.exportLoading = false;
  695 + if (data) {
  696 + downloadFile("报表", data);
648 697 } else {
649 698 this.$message.error(info);
650 699 }
... ... @@ -667,7 +716,6 @@ export default {
667 716 }
668 717 }
669 718  
670   -
671 719 .fa-exchange {
672 720 color: #667ffd;
673 721 cursor: pointer;
... ...
src/views/examinationPaper/add.vue
... ... @@ -836,12 +836,12 @@ export default {
836 836 this.saveLoading = true;
837 837 //添加题目ID、序号
838 838 this.form.questionList.map((item, index) => {
839   - item.questionId = index + 1;
840   - item.questionIndex = index + 1;
  839 + // item.questionId = index + 1;
  840 + // item.questionIndex = index + 1;
841 841 item.questionType = 0;
842 842 item.subQuestions.map((items, indexs) => {
843   - items.questionId = indexs + 1;
844   - items.questionIndex = indexs + 1;
  843 + items.questionId = this.setNum(index,indexs)
  844 + items.questionIndex = this.setNum(index,indexs);
845 845 });
846 846 });
847 847 const { data, status, info } = await this.$request.addPaper({
... ...
src/views/index/mainIndex.vue
... ... @@ -204,10 +204,12 @@ export default {
204 204 });
205 205 if (this.type == "ROLE_XUEXIAO") {
206 206 this.schoolIndex();
207   - } else if (this.type == "ROLE_JIAOSHI" || this.type == "ROLE_BANZHUREN") {
  207 + } else if (this.type == "ROLE_JIAOSHI" ) {
208 208 this.teacherIndex();
209 209 } else if (this.type == "ROLE_JITUAN") {
210 210 this.tenantIndex();
  211 + }else if (this.type == "ROLE_BANZHUREN") {
  212 + this.classIndex();
211 213 }
212 214 },
213 215 methods: {
... ... @@ -243,6 +245,14 @@ export default {
243 245 this.$message.error(info);
244 246 }
245 247 },
  248 + async classIndex() {
  249 + const { data, status, info } = await this.$request.classIndex();
  250 + if (status === 0) {
  251 + this.dataInfo = { ...data };
  252 + } else {
  253 + this.$message.error(info);
  254 + }
  255 + },
246 256 },
247 257 };
248 258 </script>
... ...
src/views/login/index.vue
... ... @@ -93,12 +93,16 @@ export default {
93 93 loginForm: {
94 94 // username: "15911715665",
95 95 // password: "Csiy88888",
96   - username: "13610050254",
97   - password: "Pw050254#",
98   - // username: "18946034886",
99   - // password: "Pw034886#",
  96 + // username: "13610050254",
  97 + // password: "Pw050254#",
100 98 // username: "18332123505",
101 99 // password: "Pw123505#",
  100 + // username: "18946034886",
  101 + // password: "Pw034886#",
  102 + // username: "18893712576",
  103 + // password: "Pw712576#",
  104 + username: "13247726488",
  105 + password: "726488",
102 106  
103 107 },
104 108 loginRules: {
... ... @@ -184,9 +188,9 @@ $cursor: #000;
184 188 border-radius: 0px;
185 189 font-size: 16px;
186 190 color: $light_gray;
187   - height: 52px;
  191 + height:48px;
  192 + line-height: 48px;
188 193 caret-color: $cursor;
189   -
190 194 &:-webkit-autofill {
191 195 box-shadow: 0 0 0px 1000px #e5e5e5 inset !important;
192 196 -webkit-text-fill-color: $cursor !important;
... ...
src/views/setUp/account.vue
... ... @@ -194,11 +194,6 @@
194 194 >
195 195 </el-pagination>
196 196 </div>
197   - <el-empty
198   - v-if="!loading && tableData.length == 0"
199   - content="没有更多数据"
200   - :image-size="100"
201   - ></el-empty>
202 197 </div>
203 198 <el-dialog title="修改账号信息" :visible.sync="diaCount" width="400">
204 199 <el-form
... ... @@ -288,7 +283,7 @@
288 283 </el-select>
289 284 </el-col>
290 285 </el-form-item>
291   - <el-form-item label="选择管辖范围:" prop="regionId">
  286 + <el-form-item label="选择管辖范围:" :prop="formAddCount.roleId == 3?'regionId':'schoolId'">
292 287 <el-col :span="12">
293 288 <el-select
294 289 v-show="formAddCount.roleId == 3"
... ... @@ -385,7 +380,7 @@ export default {
385 380 password: "",
386 381 roleId: "",
387 382 regionId: "",
388   - schoolId:""
  383 + schoolId: "",
389 384 },
390 385 addSelectSchoolList: [],
391 386 ruleAddCount: {
... ... @@ -396,6 +391,9 @@ export default {
396 391 regionId: [
397 392 { required: true, message: "请选择权限区域", trigger: "blur" },
398 393 ],
  394 + schoolId: [
  395 + { required: true, message: "请选择权限区域", trigger: "blur" },
  396 + ],
399 397 },
400 398 };
401 399 },
... ... @@ -460,7 +458,11 @@ export default {
460 458 });
461 459 },
462 460 setCount(obj) {
463   - this.formCount.userId = obj.userId;
  461 + if (this.role != "ROLE_JITUAN") {
  462 + this.formCount.userId = obj.userId;
  463 + } else {
  464 + this.formCount.id = obj.id;
  465 + }
464 466 this.formCount.loginName = obj.loginName;
465 467 this.formCount.realName = obj.realName;
466 468 this.diaCount = true;
... ... @@ -533,19 +535,21 @@ export default {
533 535 }
534 536 },
535 537 async updateUser(obj, type) {
536   - let query = {
537   - userId: obj.id,
538   - type: type,
539   - };
  538 + let query = {};
  539 + console.log(query);
540 540 if (type == 1) {
541 541 query.available = obj.available == 0 ? 1 : 0;
542 542 }
543 543 const { data, status, info } =
544 544 this.role != "ROLE_JITUAN"
545 545 ? await this.$request.updateUser({
  546 + userId: obj.userId,
  547 + type: type,
546 548 ...query,
547 549 })
548 550 : await this.$request.tenantUpdateUser({
  551 + id: obj.id,
  552 + type: type,
549 553 ...query,
550 554 });
551 555 if (status === 0) {
... ...
src/views/setUp/student.vue
... ... @@ -143,7 +143,7 @@
143 143 </el-form-item>
144 144 <el-form-item label="答题器编码:">
145 145 <el-col :span="10">
146   - <el-input maxlength="8" v-model.trim="formStu.clickerSn" />
  146 + <el-input v-model.trim="formStu.clickerSn" />
147 147 </el-col>
148 148 </el-form-item>
149 149 </el-form>
... ...
src/views/setUp/teacher.vue
... ... @@ -252,7 +252,7 @@
252 252 <el-col :span="10">
253 253 <el-input
254 254 type="number"
255   - moninput="if(value.length > 11) value = value.slice(0,11)"
  255 + oninput="if(value.length > 11) value = value.slice(0,11)"
256 256 v-model.trim="formTeacher.loginName"
257 257 />
258 258 </el-col>
... ... @@ -442,7 +442,7 @@ export default {
442 442 teacherName: "",
443 443 loginName: "",
444 444 sex: 1,
445   - managerList: [],
  445 + roleList: [],
446 446 };
447 447 this.diaTeacher = true;
448 448 },
... ...
src/views/test/analysis.vue
1 1 <template>
2   - <div>
  2 + <div class="page-container" :class="dialogVisible ? 'active' : ''">
3 3 <back-box>
4 4 <template slot="title">
5 5 <span>单卷分析</span>
... ... @@ -13,8 +13,10 @@
13 13 }}修改了答案,是否重新记分?
14 14 </p>
15 15 <div class="btn-box">
16   - <el-button type="danger" round size="mini">重新计分</el-button>
17   - <el-button type="danger" round plain size="mini">暂时不计</el-button>
  16 + <el-button type="danger" round @click="_ReScore" size="mini"
  17 + >重新计分</el-button
  18 + >
  19 + <el-button type="danger" round plain size="mini" @click="paperModifyLog.modifiedTime = ''">暂时不计</el-button>
18 20 </div>
19 21 </div>
20 22 <div class="page-content">
... ... @@ -44,54 +46,48 @@
44 46 >作答明细表</span
45 47 >
46 48 </div>
47   - <el-table
48   - v-if="type == 1"
49   - :data="tableData"
50   - border
51   - style="width: 100%"
52   - :default-sort="{ prop: 'dadui', order: 'descending' }"
53   - >
54   - <el-table-column prop="questionIndex" label="题号" align="center"
55   - ><template slot-scope="scoped"
56   - >Q{{ scoped.row.questionIndex }}</template
57   - ></el-table-column
58   - >
  49 + <el-table v-if="type == 1" :data="tableData" border style="width: 100%">
59 50 <el-table-column
60   - prop="questionType"
61   - label="题型"
  51 + prop="questionIndex"
  52 + label="题号"
62 53 align="center"
63 54 ></el-table-column>
  55 + <el-table-column prop="questionType" label="题型" align="center"
  56 + ><template slot-scope="scope">{{
  57 + setSubPro(scope.row.questionType)
  58 + }}</template></el-table-column
  59 + >
64 60 <el-table-column
65   - prop="manfen"
  61 + prop="score"
66 62 label="满分值"
67 63 sortable
68 64 align="center"
69 65 ></el-table-column>
70 66 <el-table-column
71   - prop="zuigao"
  67 + prop="highestScore"
72 68 label="班最高分"
73 69 sortable
74 70 align="center"
75 71 ></el-table-column>
76 72 <el-table-column
77   - prop="zuidi"
  73 + prop="lowestScore"
78 74 label="班最低分"
79 75 sortable
80 76 align="center"
81 77 ></el-table-column>
82 78 <el-table-column
83   - prop="pingjun"
  79 + prop="avgScore"
84 80 label="班平均分"
85 81 sortable
86 82 align="center"
87 83 ></el-table-column>
88 84 <el-table-column
89   - prop="defenlv"
  85 + prop="scoringRate"
90 86 sortable
91 87 label="班级得分率"
92 88 align="center"
93 89 ><template slot-scope="scoped"
94   - >{{ scoped.row.defenlv }}%</template
  90 + >{{ scoped.row.scoringRate }}%</template
95 91 ></el-table-column
96 92 >
97 93 <el-table-column
... ... @@ -100,20 +96,12 @@
100 96 align="center"
101 97 ></el-table-column>
102 98 <el-table-column
103   - prop="x1"
104   - label="选项1"
105   - align="center"
106   - ></el-table-column>
107   - <el-table-column
108   - prop="x2"
109   - label="选项1"
110   - align="center"
111   - ></el-table-column>
112   - <el-table-column
113   - prop="weida"
114   - label="未答"
115   - align="center"
116   - ></el-table-column>
  99 + v-for="(item, index) in optionsList"
  100 + :key="index"
  101 + :label="item.option"
  102 + :prop="item.option"
  103 + >
  104 + </el-table-column>
117 105 </el-table>
118 106 <el-table
119 107 v-if="type == 2"
... ... @@ -123,91 +111,100 @@
123 111 :default-sort="{ prop: 'dadui', order: 'descending' }"
124 112 >
125 113 <el-table-column
126   - prop="xuehao"
  114 + prop="studentCode"
127 115 label="学号"
128 116 align="center"
129 117 fixed
130 118 ></el-table-column>
131 119 <el-table-column
132   - prop="xingming"
  120 + prop="studentName"
133 121 label="姓名"
134 122 fixed
135 123 align="center"
136 124 ></el-table-column>
137 125 <el-table-column
138   - prop="totalScore"
  126 + prop="examPaperScore"
139 127 label="总分"
140 128 sortable
141 129 align="center"
142 130 ></el-table-column>
143 131 <el-table-column
144   - prop="defenlv"
  132 + prop="scoringRate"
145 133 label="得分率"
146 134 sortable
147 135 align="center"
148   - ></el-table-column>
  136 + ><template slot-scope="scope"
  137 + >{{ scope.row.scoringRate }}%</template
  138 + ></el-table-column
  139 + >
149 140 <el-table-column
150   - prop="rank"
  141 + prop="classRank"
151 142 label="班名"
152 143 sortable
153 144 align="center"
154 145 ></el-table-column>
155 146 <el-table-column label="客观题" align="center">
156 147 <el-table-column
157   - prop="defen1"
  148 + prop="objectiveExamScore"
158 149 label="得分"
159 150 align="center"
160 151 ></el-table-column>
161 152 <el-table-column
162   - prop="defenlv1"
  153 + prop="objectiveScoringRate"
163 154 label="得分率"
164 155 align="center"
165   - ></el-table-column>
  156 + ><template slot-scope="scope"
  157 + >{{ scope.row.objectiveScoringRate }}%</template
  158 + ></el-table-column
  159 + >
166 160 </el-table-column>
167 161 <el-table-column label="主观题" align="center">
168 162 <el-table-column
169   - prop="defen2"
  163 + prop="subjectiveExamScore"
170 164 label="得分"
171 165 align="center"
172 166 ></el-table-column>
173 167 <el-table-column
174   - prop="defenlv2"
  168 + prop="subjectiveScoringRate"
175 169 label="得分率"
176 170 align="center"
177   - ></el-table-column>
  171 + ><template slot-scope="scope"
  172 + >{{ scope.row.subjectiveScoringRate }}%</template
  173 + ></el-table-column
  174 + >
178 175 </el-table-column>
179 176 </el-table>
180 177 <el-table
181 178 v-if="type == 3"
182   - :data="tableData3"
  179 + :data="tableData2"
183 180 border
184 181 style="width: 100%"
185 182 :default-sort="{ prop: '', order: 'descending' }"
186 183 >
187 184 <el-table-column
188   - prop="xuehao"
  185 + prop="studentCode"
189 186 label="学号"
190 187 align="center"
191 188 ></el-table-column>
192 189 <el-table-column
193   - prop="xingming"
  190 + prop="studentName"
194 191 label="姓名"
195 192 align="center"
196 193 ></el-table-column>
197 194 <el-table-column
198   - prop="totalScore"
  195 + prop="examPaperScore"
199 196 label="总分"
200 197 sortable
201 198 align="center"
202 199 ></el-table-column>
203 200 <el-table-column label="分数组成" align="center">
204 201 <el-table-column
205   - prop="keguan"
  202 + prop="objectiveScore"
206 203 label="客观题分"
207 204 align="center"
208 205 ></el-table-column>
209 206 <el-table-column
210   - prop="zhuguan"
  207 + prop="subjectiveScore"
211 208 label="主观题分"
212 209 align="center"
213 210 ></el-table-column>
... ... @@ -216,43 +213,35 @@
216 213 align="center"
217 214 v-for="(item, index) in questionList"
218 215 :key="index"
219   - :label="item.title"
220   -
  216 + :label="'题目' + item.id"
  217 + :prop="'score' + item.id"
221 218 >
222   - <template v-for="items in item.subQuestions">
223   - <el-table-column
224   - :key="items.questionIndex"
225   - :prop="'score' + items.questionIndex"
226   - :label="`${items.questionIndex}`"
227   - align="center"
228   - ></el-table-column>
229   - </template>
230 219 </el-table-column>
231 220 </el-table>
232 221 <el-table
233 222 v-if="type == 4"
234   - :data="tableData4"
  223 + :data="tableData2"
235 224 border
236 225 style="width: 100%"
237 226 :default-sort="{ prop: '', order: 'descending' }"
238 227 >
239 228 <el-table-column
240   - prop="xuehao"
  229 + prop="studentCode"
241 230 label="学号"
242 231 align="center"
243 232 ></el-table-column>
244 233 <el-table-column
245   - prop="xingming"
  234 + prop="studentName"
246 235 label="姓名"
247 236 align="center"
248 237 ></el-table-column>
249 238 <el-table-column
250   - prop="banji"
  239 + prop="className"
251 240 label="班级"
252 241 align="center"
253 242 ></el-table-column>
254 243 <el-table-column
255   - prop="totalScore"
  244 + prop="examPaperScore"
256 245 label="总分"
257 246 sortable
258 247 align="center"
... ... @@ -261,129 +250,306 @@
261 250 align="center"
262 251 v-for="(item, index) in questionList"
263 252 :key="index"
264   - :label="item.title"
  253 + :label="'题目' + item.id"
265 254 >
266   - <template v-for="items in item.subQuestions">
267   - <el-table-column
268   - :key="items.questionIndex"
269   - :prop="'daan' + items.questionIndex"
270   - :label="`${items.questionIndex}`"
271   - align="center"
272   - ></el-table-column>
  255 + <template slot-scope="scope">
  256 + <span
  257 + v-if="scope.row['answer' + item.id]"
  258 + :class="scope.row['isRight' + item.id] ? '' : 'error'"
  259 + >
  260 + {{ scope.row["answer" + item.id] }}
  261 + </span>
  262 + <span
  263 + v-else
  264 + :class="scope.row['questionType' + item.id] == 5 ? '' : 'error'"
  265 + >
  266 + {{ scope.row["questionType" + item.id] == 5 ? "*" : "-" }}
  267 + </span>
273 268 </template>
274 269 </el-table-column>
275 270 </el-table>
  271 + <div class="pagination-box" v-show="type == 1">
  272 + <el-pagination
  273 + small=""
  274 + layout="total,prev, pager, next"
  275 + :hide-on-single-page="true"
  276 + :total="total"
  277 + @current-change="changePage"
  278 + :current-page="page"
  279 + :page-size="size"
  280 + >
  281 + </el-pagination>
  282 + </div>
  283 + <div class="down">
  284 + <el-button
  285 + @click="exportData"
  286 + type="info"
  287 + plain
  288 + round
  289 + icon="fa fa-cloud-download"
  290 + >导出报表</el-button
  291 + >
  292 + <div>
  293 + <el-button
  294 + @click="diaUp = true"
  295 + type="primary"
  296 + round
  297 + v-loading="exportLoading"
  298 + >导入主观题分数</el-button
  299 + >
  300 + <el-button @click="edit" type="primary" round>设置答案</el-button>
  301 + </div>
  302 + </div>
  303 + <div class="edit-dia" v-show="dialogVisible" height="100%">
  304 + <editAnswer
  305 + :id="id"
  306 + :title="title"
  307 + :score="score"
  308 + @cancel="cancel"
  309 + @saveSuccess="saveSuccess"
  310 + />
  311 + </div>
  312 + <el-dialog title="导入主观题分数" :visible.sync="diaUp" width="600">
  313 + <up-load :url="url" :examId="id" fileName="教师名单">
  314 + <template slot="down">
  315 + <p class="down-txt">
  316 + 第一步:下载模板并编辑完成学生分数
  317 + <el-link type="danger" @click="downExcel">模板下载</el-link> 。
  318 + </p>
  319 + <p class="down-txt">第二步:上传完成编辑的模板文件并导入。</p>
  320 + </template>
  321 + </up-load>
  322 + <div class="dialog-footer" slot="footer">
  323 + <el-button @click="diaUp = false">取 消</el-button>
  324 + </div>
  325 + </el-dialog>
276 326 </div>
277 327 </div>
278 328 </template>
279 329  
280 330 <script>
  331 +import { downloadFile } from "@/utils";
  332 +import editAnswer from "./editAnswer.vue";
281 333 export default {
  334 + components: { editAnswer },
282 335 data() {
283 336 return {
  337 + loading: false,
  338 + exportLoading: false,
  339 + diaUp: false,
  340 + dialogVisible: false,
  341 + url: "/api_html/teaching/importSubjectiveScore",
284 342 id: "",
  343 + title: "",
  344 + score: "",
285 345 type: 1,
286 346 paperModifyLog: {
287   - realName: "张老师",
288   - modifiedTime: "12-20",
  347 + realName: "",
  348 + modifiedTime: "",
289 349 },
290   - tableData: [
291   - {
292   - questionIndex: 1,
293   - questionType: "单选题",
294   - manfen: 100,
295   - zuigao: 100,
296   - zuidi: 20,
297   - pingjun: 80,
298   - defenlv: 90,
299   - correctAnswer: "A",
300   - x1: "A",
301   - x2: "B",
302   - weida: "",
303   - },
304   - {
305   - questionIndex: 2,
306   - questionType: "单选题",
307   - manfen: 100,
308   - zuigao: 99,
309   - zuidi: 50,
310   - pingjun: 90,
311   - defenlv: 100,
312   - correctAnswer: "B",
313   - x1: "A",
314   - x2: "B",
315   - weida: "",
316   - },
317   - ],
318   - tableData2: [
319   - {
320   - xuehao: 1,
321   - xingming: "丁芳菲",
322   - totalScore: 5,
323   - defenlv: 50,
324   - rank: 1,
325   - defen1: 1,
326   - defenlv1: 1,
327   - defen2: 1,
328   - defenlv2: 1,
329   - },
330   - ],
331   - tableData3: [
332   - {
333   - xuehao: 1,
334   - xingming: "丁芳菲",
335   - totalScore: 5,
336   - rank: 1,
337   - keguan: 20,
338   - zhuguan: 20,
339   - score1: 1,
340   - score2: 2,
341   - score3: 3,
342   - score4: 4,
343   - },
344   - ],
345   - tableData4: [
346   - {
347   - xuehao: 1,
348   - xingming: "丁芳菲",
349   - banji: 'xx',
350   - totalScore: 5,
351   - daan1: 1,
352   - daan2: 2,
353   - daan3: 3,
354   - daan4: 4,
355   - },
356   - ],
357   - questionList: [{
358   - title:'大题1',
359   - subQuestions:[
360   - {questionIndex:1, daan:1},
361   - {questionIndex:2, daan:1},
362   - ]
363   - },{
364   - title:'大题2',
365   - subQuestions:[
366   - {questionIndex:3, daan:2},
367   - {questionIndex:4, daan:2},
368   - ]
369   - }],
  350 + tableData: [],
  351 + optionsList: [],
  352 + tableData2: [],
  353 + questionList: [],
  354 + page: 1,
  355 + size: 20,
  356 + total: 0,
370 357 };
371 358 },
372 359 created() {
373 360 this.id = this.$route.query.id;
374   - // this._QueryData()
  361 + this.title = this.$route.query.title || "";
  362 + this.score = this.$route.query.score || "";
  363 + this._QueryData();
375 364 },
376 365 methods: {
  366 + setSubPro(type) {
  367 + let tit;
  368 + switch (type) {
  369 + case 2:
  370 + tit = "单选题";
  371 + break;
  372 + case 3:
  373 + tit = "多选题";
  374 + break;
  375 + case 4:
  376 + tit = "判断题";
  377 + break;
  378 + case 5:
  379 + tit = "主观题";
  380 + break;
  381 + }
  382 + return tit;
  383 + },
  384 + edit() {
  385 + this.dialogVisible = true;
  386 + },
  387 + cancel() {
  388 + this.dialogVisible = false;
  389 + },
  390 + saveSuccess() {
  391 + this.dialogVisible = false;
  392 + this._QueryData();
  393 + },
  394 + changePage(page) {
  395 + this.page = page;
  396 + this.examQuestionReport();
  397 + },
  398 + async downExcel() {
  399 + let data = await this.$request.subjectiveScoreTemplate({
  400 + examId: this.id,
  401 + });
  402 + if (data && !data.code) {
  403 + let blob = new Blob([data], {
  404 + type: "application/vnd.ms-excel;charset=utf-8",
  405 + });
  406 + downloadFile(`主观题模版.xlsx`, blob);
  407 + } else {
  408 + this.$message.error(data.message);
  409 + }
  410 + },
377 411 async _QueryData() {
378   - let { data, info, status } = this.$request.quizDetail({
379   - id: this.id,
  412 + this.examDetail();
  413 + this.examStudentReport();
  414 + this.examQuestionReport();
  415 + },
  416 + async examDetail() {
  417 + //详情
  418 + this.loading = true;
  419 + let { data, info, status } = await this.$request.examDetail({
  420 + examId: this.id,
380 421 });
  422 + this.loading = false;
  423 + if (status === 0) {
  424 + if (data.paperModifyLog) {
  425 + this.paperModifyLog = { ...data.paperModifyLog };
  426 + }
  427 + } else {
  428 + this.$message.error(info);
  429 + }
  430 + },
  431 + async _ReScore() {
  432 + //重新记分
  433 + this.loading = true;
  434 + let { data, info, status } = await this.$request.reScore({
  435 + examId: this.id,
  436 + });
  437 + this.loading = false;
  438 + if (status === 0) {
  439 + this.$message.success(info);
  440 + this._QueryData()
  441 + this.paperModifyLog.modifiedTime=""
  442 + this.paperModifyLog.realName=""
  443 + } else {
  444 + this.$message.error(info);
  445 + }
  446 + },
  447 + async examStudentReport() {
  448 + //成绩排名-小题分-作答明细
  449 + this.loading = true;
  450 + let { data, info, status } = await this.$request.examStudentReport({
  451 + examId: this.id,
  452 + });
  453 + this.loading = false;
  454 + if (status === 0) {
  455 + let optionsList = [];
  456 + this.tableData2 = data?.list.map((item) => {
  457 + let params = {};
  458 +
  459 + const detail = JSON.parse(item.detail);
  460 + if (detail.length > optionsList.length) {
  461 + optionsList = [...detail];
  462 + }
  463 + console.log(detail);
  464 + detail.map((items, index) => {
  465 + params["que" + items.id] = items.id;
  466 + params["score" + items.id] = items.score;
  467 + params["answer" + items.id] = items.answer;
  468 + params["isRight" + items.id] = items.isRight;
  469 + params["questionType" + items.id] = items.questionType;
  470 + });
  471 + return {
  472 + ...item,
  473 + ...params,
  474 + };
  475 + });
  476 + this.questionList = [...optionsList];
  477 + } else {
  478 + this.$message.error(info);
  479 + }
  480 + },
  481 + async examQuestionReport() {
  482 + //试题分析
  483 + this.loading = true;
  484 + let { data, info, status } = await this.$request.examQuestionReport({
  485 + examId: this.id,
  486 + page: this.page,
  487 + size: this.size,
  488 + });
  489 + this.loading = false;
  490 + if (status === 0) {
  491 + let optionsList = [];
  492 + this.tableData = data?.list.map((item) => {
  493 + let params = {};
  494 +
  495 + const detail = JSON.parse(item.detail);
  496 + if (detail.length > optionsList.length) {
  497 + optionsList = [...detail];
  498 + }
  499 + console.log(detail);
  500 + detail.map((items, index) => {
  501 + params[items.option] = items.count;
  502 + });
  503 + return {
  504 + ...item,
  505 + ...params,
  506 + };
  507 + });
  508 + this.optionsList = [...optionsList];
  509 + this.total = data.count;
  510 + } else {
  511 + this.$message.error(info);
  512 + }
  513 + },
  514 + //导出
  515 + async exportData() {
  516 + if ((this.exportLoading = true)) return;
  517 + this.exportLoading = true;
  518 + const { data, status, info } = await this.$request.exportData();
  519 + this.exportLoading = false;
  520 + if (data) {
  521 + downloadFile(this.title + "报表", data);
  522 + } else {
  523 + this.$message.error(info);
  524 + }
381 525 },
382 526 },
383 527 };
384 528 </script>
385 529  
386 530 <style lang="scss" scoped>
  531 +.page-container {
  532 + position: relative;
  533 + &.active {
  534 + height: 100%;
  535 + overflow: hidden;
  536 + }
  537 + .edit-dia {
  538 + position: absolute;
  539 + left: 0;
  540 + top: 0;
  541 + right: 0;
  542 + bottom: 0;
  543 + width: 100%;
  544 + height: calc(100vh - 70px);
  545 + background: #fff;
  546 + overflow-y: auto;
  547 + z-index: 10;
  548 + }
  549 +}
  550 +.error {
  551 + color: #f30;
  552 +}
387 553 .page-content {
388 554 padding: 20px 20px 0;
389 555 }
... ... @@ -431,4 +597,10 @@ export default {
431 597 }
432 598 }
433 599 }
  600 +.down {
  601 + padding-top: 20px;
  602 + width: 100%;
  603 + display: flex;
  604 + justify-content: space-between;
  605 +}
434 606 </style>
435 607 \ No newline at end of file
... ...
src/views/test/editAnswer.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <div class="back">
  4 + <div class="back-l" @click="cancel">
  5 + <i class="fa fa-mail-reply-all"></i>
  6 + <p>修改答案</p>
  7 + </div>
  8 + </div>
  9 + <div class="form-box">
  10 + <div class="answer-title">
  11 + <p class="name">{{ title }}</p>
  12 + <p class="totals">卷面总分:{{ score }}分</p>
  13 + </div>
  14 + <div v-if="questionList && questionList.length">
  15 + <template v-if="questionList[0].subQuestions">
  16 + <div v-for="(question, index) in questionList" :key="index">
  17 + <p class="question-title">
  18 + <span>{{ setBigNum(index) }}、</span>
  19 + <span class="title-txt">{{ question.questionTitle }}</span>
  20 + <span>共 {{ question.score }} 分</span>
  21 + </p>
  22 + <ul class="questions-ul">
  23 + <li class="sub-questions">
  24 + <div class="qs-num">题号</div>
  25 + <div class="qs-type">题型</div>
  26 + <div class="qs-score">分数</div>
  27 + <div class="qs-partScore">漏选得分</div>
  28 + <div class="qs-options qs-options2">选项设置</div>
  29 + </li>
  30 + <li
  31 + v-for="(subQuestions, indexs) in question.subQuestions"
  32 + :key="indexs"
  33 + >
  34 + <p
  35 + class="set-ans-btn"
  36 + v-if="
  37 + subQuestions.qusType &&
  38 + subQuestions.subNum &&
  39 + subQuestions.subNum > 4
  40 + "
  41 + >
  42 + <el-button type="primary" @click="setFormAns(indexs, index)"
  43 + >批量设置答案</el-button
  44 + >
  45 + </p>
  46 + <div v-else class="sub-questions">
  47 + <div class="qs-num">{{ subQuestions.questionIndex }}</div>
  48 + <div class="qs-type">
  49 + {{ setSubPro(subQuestions.questionType) }}
  50 + </div>
  51 + <div class="qs-score">
  52 + {{ subQuestions.score }}
  53 + </div>
  54 + <div class="qs-partScore">
  55 + <p v-if="subQuestions.questionType != 3">--</p>
  56 + <p v-else>{{ subQuestions.partScore }}</p>
  57 + </div>
  58 + <div class="qs-options qs-options2">
  59 + <p v-if="subQuestions.questionType == 5">--</p>
  60 + <p v-if="subQuestions.questionType == 4" class="answer-box">
  61 + <span
  62 + class="answer-s"
  63 + :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
  64 + @click="subQuestions.correctAnswer = 1"
  65 + >✓</span
  66 + >
  67 + <span
  68 + class="answer-s"
  69 + :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
  70 + @click="subQuestions.correctAnswer = 2"
  71 + >✗</span
  72 + >
  73 + </p>
  74 + <p v-if="subQuestions.questionType == 3" class="answer-box">
  75 + <template
  76 + v-for="option in subQuestions.answerOptions.split(',')"
  77 + >
  78 + <span
  79 + v-if="option"
  80 + class="answer-s"
  81 + :class="
  82 + subQuestions.correctAnswer.includes(option)
  83 + ? 'active'
  84 + : ''
  85 + "
  86 + :key="option"
  87 + @click="changAnswer(subQuestions, option)"
  88 + >{{ option }}</span
  89 + >
  90 + </template>
  91 + </p>
  92 + <p v-if="subQuestions.questionType == 2" class="answer-box">
  93 + <template
  94 + v-for="option in subQuestions.answerOptions.split(',')"
  95 + >
  96 + <span
  97 + class="answer-s"
  98 + v-if="option"
  99 + :class="
  100 + subQuestions.correctAnswer == option ? 'active' : ''
  101 + "
  102 + :key="option"
  103 + @click="subQuestions.correctAnswer = option"
  104 + >{{ option }}</span
  105 + >
  106 + </template>
  107 + </p>
  108 + </div>
  109 + </div>
  110 + </li>
  111 + </ul>
  112 + </div>
  113 + </template>
  114 + <ul class="questions-ul" v-else>
  115 + <li class="sub-questions">
  116 + <div class="qs-num">题号</div>
  117 + <div class="qs-type">题型</div>
  118 + <div class="qs-score">分数</div>
  119 + <div class="qs-partScore">漏选得分</div>
  120 + <div class="qs-options qs-options2">选项设置</div>
  121 + </li>
  122 + <li v-for="(subQuestions, indexs) in questionList" :key="indexs">
  123 + <p
  124 + class="set-ans-btn"
  125 + v-if="
  126 + subQuestions.qusType &&
  127 + subQuestions.subNum &&
  128 + subQuestions.subNum > 4
  129 + "
  130 + >
  131 + <el-button type="primary" @click="setFormAns(indexs, index)"
  132 + >批量设置答案</el-button
  133 + >
  134 + </p>
  135 + <div v-else class="sub-questions">
  136 + <div class="qs-num">{{ subQuestions.questionIndex }}</div>
  137 + <div class="qs-type">
  138 + {{ setSubPro(subQuestions.questionType) }}
  139 + </div>
  140 + <div class="qs-score">
  141 + {{ subQuestions.score }}
  142 + </div>
  143 + <div class="qs-partScore">
  144 + <p v-if="subQuestions.questionType != 3">--</p>
  145 + <p v-else>{{ subQuestions.partScore }}</p>
  146 + </div>
  147 + <div class="qs-options qs-options2">
  148 + <p v-if="subQuestions.questionType == 5">--</p>
  149 + <p v-if="subQuestions.questionType == 4" class="answer-box">
  150 + <span
  151 + class="answer-s"
  152 + :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
  153 + @click="subQuestions.correctAnswer = 1"
  154 + >✓</span
  155 + >
  156 + <span
  157 + class="answer-s"
  158 + :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
  159 + @click="subQuestions.correctAnswer = 2"
  160 + >✗</span
  161 + >
  162 + </p>
  163 + <p v-if="subQuestions.questionType == 3" class="answer-box">
  164 + <template
  165 + v-for="option in subQuestions.answerOptions.split(',')"
  166 + >
  167 + <span
  168 + v-if="option"
  169 + class="answer-s"
  170 + :class="
  171 + subQuestions.correctAnswer.includes(option)
  172 + ? 'active'
  173 + : ''
  174 + "
  175 + :key="option"
  176 + @click="changAnswer(subQuestions, option)"
  177 + >{{ option }}</span
  178 + >
  179 + </template>
  180 + </p>
  181 + <p v-if="subQuestions.questionType == 2" class="answer-box">
  182 + <template
  183 + v-for="option in subQuestions.answerOptions.split(',')"
  184 + >
  185 + <span
  186 + class="answer-s"
  187 + v-if="option"
  188 + :class="
  189 + subQuestions.correctAnswer == option ? 'active' : ''
  190 + "
  191 + :key="option"
  192 + @click="subQuestions.correctAnswer = option"
  193 + >{{ option }}</span
  194 + >
  195 + </template>
  196 + </p>
  197 + </div>
  198 + </div>
  199 + </li>
  200 + </ul>
  201 + </div>
  202 + <div class="btn-box">
  203 + <el-button type="danger" plain round @click="cancel"
  204 + >取消</el-button
  205 + >
  206 + <el-button type="primary" round @click="saveAnswer">保存</el-button>
  207 + </div>
  208 + </div>
  209 + <el-dialog
  210 + title="批量设置答案"
  211 + :visible.sync="diaSetAns"
  212 + width="400"
  213 + :modal-append-to-body="false"
  214 + >
  215 + <div class="qs-options">
  216 + <p class="dia-tips">
  217 + 请点击选项按钮设置答案,多选题题目之间用“,”隔开,若添加5道题:“AC,AD,BD,AC,CD”
  218 + </p>
  219 + <p>{{ setSubPro(formAns.qusType) }}:</p>
  220 + <p class="ipt">
  221 + <el-input
  222 + v-model="formAns.answerList"
  223 + @keydown.native="keydownAnswer($event)"
  224 + ></el-input>
  225 + </p>
  226 + <p class="answer-box">
  227 + <template v-if="formAns.qusType == 4">
  228 + <span
  229 + class="answer-s active"
  230 + @click="
  231 + formAns.answerList.length < formAns.subNum
  232 + ? (formAns.answerList += '✓')
  233 + : ''
  234 + "
  235 + >✓</span
  236 + >
  237 + <span
  238 + class="answer-s active"
  239 + @click="
  240 + formAns.answerList.length < formAns.subNum
  241 + ? (formAns.answerList += '✗')
  242 + : ''
  243 + "
  244 + >✗</span
  245 + >
  246 + </template>
  247 + <template v-if="formAns.qusType == 3">
  248 + <span
  249 + class="answer-s active"
  250 + v-for="option in formAns.answerOptions.split(',')"
  251 + :key="option"
  252 + @click="setMultiple(formAns, option)"
  253 + >{{ option }}</span
  254 + >
  255 + <span
  256 + class="answer-s active"
  257 + @click="
  258 + formAns.answerList.split(',').length < formAns.subNum
  259 + ? (formAns.answerList += ',')
  260 + : ''
  261 + "
  262 + >,</span
  263 + >
  264 + </template>
  265 + <template v-if="formAns.qusType == 2" class="answer-box">
  266 + <span
  267 + class="answer-s active"
  268 + v-for="option in formAns.answerOptions.split(',')"
  269 + :key="option"
  270 + @click="
  271 + formAns.answerList.length < formAns.subNum
  272 + ? (formAns.answerList += option)
  273 + : ''
  274 + "
  275 + >{{ option }}</span
  276 + >
  277 + </template>
  278 + <span
  279 + class="answer-s delButton"
  280 + @click="formAns.answerList = formAns.answerList.slice(0, -1)"
  281 + >x</span
  282 + >
  283 + </p>
  284 + </div>
  285 + <div class="dialog-footer" slot="footer">
  286 + <el-button @click="saveFormAns">确 定</el-button>
  287 + <el-button @click="diaSetAns = false">取 消</el-button>
  288 + </div>
  289 + </el-dialog>
  290 + </div>
  291 +</template>
  292 +
  293 +<script>
  294 +import { deepClone, checkAnswer } from "utils";
  295 +export default {
  296 + props: {
  297 + id: "",
  298 + title: "",
  299 + score: "",
  300 + },
  301 + watch: {
  302 + id: {
  303 + handler: function (val) {
  304 + if (val) {
  305 + this.edit();
  306 + }
  307 + },
  308 + immediate: true,
  309 + },
  310 + },
  311 + data() {
  312 + return {
  313 + diaSetAns: false,
  314 + form: {},
  315 + questionList: [],
  316 + formAns: {
  317 + listIndex: 0, //大题位置
  318 + endIndex: 0, //相同题目最后一位题目的questionIndex
  319 + qusType: "", //题目类型
  320 + subNum: 0, //数量
  321 + answerOptions: [], //答案选项
  322 + answerList: "", //答案列表-字符串
  323 + },
  324 + };
  325 + },
  326 + created() {
  327 + // this.edit();
  328 + },
  329 + methods: {
  330 + cancel() {
  331 + this.$emit("cancel");
  332 + },
  333 + setSubPro(type) {
  334 + let tit;
  335 + switch (type) {
  336 + case 2:
  337 + tit = "单选题";
  338 + break;
  339 + case 3:
  340 + tit = "多选题";
  341 + break;
  342 + case 4:
  343 + tit = "判断题";
  344 + break;
  345 + case 5:
  346 + tit = "主观题";
  347 + break;
  348 + }
  349 + return tit;
  350 + },
  351 + setBigNum(num) {
  352 + let txt = "";
  353 + let bigNum = [
  354 + "一",
  355 + "二",
  356 + "三",
  357 + "四",
  358 + "五",
  359 + "六",
  360 + "七",
  361 + "八",
  362 + "九",
  363 + "十",
  364 + "十一",
  365 + "十二",
  366 + "十三",
  367 + "十四",
  368 + "十五",
  369 + "十六",
  370 + "十七",
  371 + "十八",
  372 + "十九",
  373 + "二十",
  374 + ];
  375 + txt = bigNum[num];
  376 +
  377 + return txt;
  378 + },
  379 + keydownAnswer(event) {
  380 + //快速答案设置禁止输入
  381 + if (
  382 + event.key == "Meta" ||
  383 + event.key == "CapsLock" ||
  384 + event.key == "Shift" ||
  385 + event.key == "Enter" ||
  386 + event.key == "Alt" ||
  387 + event.key == "Backspace" ||
  388 + event.key == "Delete" ||
  389 + event.key == "ArrowUp" ||
  390 + event.key == "ArrowDown" ||
  391 + event.key == "ArrowLeft" ||
  392 + event.key == "v" ||
  393 + event.key == "V" ||
  394 + event.key == "ArrowRight"
  395 + ) {
  396 + return;
  397 + } else {
  398 + event.returnValue = "";
  399 + }
  400 + },
  401 + setAnswer(type, ans) {
  402 + let txt = "";
  403 + if (type == 2) {
  404 + txt = ans;
  405 + } else if (type == 3) {
  406 + txt = ans + ",";
  407 + } else if (type == 4) {
  408 + txt = ans == 1 ? "✓" : "✗";
  409 + }
  410 + return txt;
  411 + },
  412 + setMultiple(obj, answer) {
  413 + //多选答案设置
  414 + obj.answerList += answer;
  415 + let str = obj.answerList;
  416 + let str2 = checkAnswer(
  417 + str,
  418 + 3,
  419 + obj.answerOptions.split(",").length,
  420 + obj.answerList.length
  421 + );
  422 + obj.answerList = str2;
  423 + },
  424 + changAnswer(sub, option) {
  425 + //设置多选答案
  426 + let str = new RegExp(option, "g");
  427 + if (sub.correctAnswer?.includes(option)) {
  428 + sub.correctAnswer = sub.correctAnswer.replace(str, "");
  429 + } else {
  430 + let arrs = (sub.correctAnswer && sub.correctAnswer.split("")) || [];
  431 + arrs.push(option);
  432 + sub.correctAnswer = arrs.sort().join("");
  433 + }
  434 + },
  435 + setFormAns(indexs, index) {
  436 + //初始化要修改的答案
  437 + if (this.questionList[0].subQuestions) {
  438 + this.formAns = { ...this.questionList[index].subQuestions[indexs] };
  439 + this.formAns.listIndex = index;
  440 + } else {
  441 + this.formAns = { ...this.questionList[indexs] };
  442 + this.formAns.listIndex = indexs;
  443 + }
  444 + this.diaSetAns = true;
  445 + },
  446 + saveFormAns() {
  447 + //批量修改答案
  448 + let EndIndex;
  449 + let subNum = this.formAns.subNum - 1;
  450 + if (this.questionList[this.formAns.listIndex].subQuestions) {
  451 + this.questionList[this.formAns.listIndex].subQuestions.some(
  452 + (item, index) => {
  453 + if (this.formAns.endIndex == item.questionIndex) {
  454 + EndIndex = index;
  455 + return;
  456 + }
  457 + }
  458 + );
  459 + } else {
  460 + this.questionList.some((item, index) => {
  461 + if (this.formAns.endIndex == item.questionIndex) {
  462 + EndIndex = index;
  463 + return;
  464 + }
  465 + });
  466 + }
  467 +
  468 + for (let i = 0; i <= subNum; i++) {
  469 + let correctAnswer = "";
  470 + if (this.formAns.qusType == 2) {
  471 + correctAnswer = this.formAns.answerList[subNum - i];
  472 + } else if (this.formAns.qusType == 3) {
  473 + correctAnswer = this.formAns.answerList.split(",")[subNum - i];
  474 +
  475 + console.log(this.formAns.answerList.split(",")[subNum - i]);
  476 + } else if (this.formAns.qusType == 4) {
  477 + correctAnswer = this.formAns.answerList[subNum - i] == "✓" ? 1 : 2;
  478 + }
  479 + if (this.questionList[0].subQuestions) {
  480 + this.questionList[this.formAns.listIndex].subQuestions[
  481 + EndIndex - i
  482 + ].correctAnswer = correctAnswer;
  483 + } else {
  484 + this.questionList[EndIndex - i].correctAnswer = correctAnswer;
  485 + }
  486 + }
  487 + this.diaSetAns = false;
  488 + },
  489 + async edit() {
  490 + //修改答案
  491 + const { data, status, info } = await this.$request.examQuestionList({
  492 + examId: this.id,
  493 + });
  494 + if (status == 0) {
  495 + this.questionList = deepClone(data?.list || []);
  496 + } else {
  497 + this.$message.error(info);
  498 + }
  499 + if (!!this.questionList[0].subQuestions) {
  500 + this.questionList?.map((item) => {
  501 + let types = [{}];
  502 + let addndex = 0;
  503 + item.subQuestions.map((sub, index) => {
  504 + if (!!sub.questionType) {
  505 + if (sub.questionType == types[addndex].qusType) {
  506 + //同类型批量答案+1
  507 + types[addndex].subNum += 1;
  508 + if (
  509 + types[addndex].answerOptions.length < sub.answerOptions.length
  510 + ) {
  511 + types[addndex].answerOptions = sub.answerOptions;
  512 + }
  513 + types[addndex].answerList += this.setAnswer(
  514 + sub.questionType,
  515 + sub.correctAnswer
  516 + );
  517 + if (index == item.subQuestions.length - 1) {
  518 + //循环最后类型数量大于等于5,保存批量答案
  519 + if (types[addndex].subNum && types[addndex].subNum >= 5) {
  520 + types[addndex].endIndex = sub.questionIndex;
  521 + types[addndex].index = index;
  522 + }
  523 + }
  524 + } else {
  525 + if (types[addndex].subNum && types[addndex].subNum >= 5) {
  526 + //不同类型时如果原有类型数量大于等于5,保存批量答案
  527 + types[addndex].endIndex =
  528 + item.subQuestions[index - 1].questionIndex;
  529 + types[addndex].index = index;
  530 + addndex += 1;
  531 + types[addndex] = {};
  532 + }
  533 + //不同类型初始化批量答案
  534 + types[addndex].qusType = sub.questionType;
  535 + types[addndex].subNum = 1;
  536 + types[addndex].answerOptions = sub.answerOptions;
  537 + types[addndex].answerList = this.setAnswer(
  538 + sub.questionType,
  539 + sub.correctAnswer
  540 + );
  541 + }
  542 + }
  543 + });
  544 + for (let i = 0; i < types.length; i++) {
  545 + if (types[i].qusType == 3) {
  546 + types[i].answerList = types[i].answerList.slice(0, -1);
  547 + }
  548 + if (types[i].subNum >= 5) {
  549 + item.subQuestions.splice(
  550 + types[i].index + i + 1,
  551 + 0,
  552 + deepClone(types[i])
  553 + );
  554 + }
  555 + }
  556 + });
  557 + } else {
  558 + let types = [{}];
  559 + let addndex = 0;
  560 + this.questionList?.map((sub, index) => {
  561 + if (!!sub.questionType) {
  562 + if (sub.questionType == types[addndex].qusType) {
  563 + //同类型批量答案+1
  564 + types[addndex].subNum += 1;
  565 + if (
  566 + types[addndex].answerOptions.length < sub.answerOptions.length
  567 + ) {
  568 + types[addndex].answerOptions = sub.answerOptions;
  569 + }
  570 + types[addndex].answerList += this.setAnswer(
  571 + sub.questionType,
  572 + sub.correctAnswer
  573 + );
  574 + if (index == this.questionList.length - 1) {
  575 + //循环最后类型数量大于等于5,保存批量答案
  576 + if (types[addndex].subNum && types[addndex].subNum >= 5) {
  577 + types[addndex].endIndex = sub.questionIndex;
  578 + types[addndex].index = index;
  579 + }
  580 + }
  581 + } else {
  582 + if (types[addndex].subNum && types[addndex].subNum >= 5) {
  583 + //不同类型时如果原有类型数量大于等于5,保存批量答案
  584 + types[addndex].endIndex =
  585 + this.questionList[index - 1].questionIndex;
  586 + types[addndex].index = index;
  587 + addndex += 1;
  588 + types[addndex] = {};
  589 + }
  590 + //不同类型初始化批量答案
  591 + types[addndex].qusType = sub.questionType;
  592 + types[addndex].subNum = 1;
  593 + types[addndex].answerOptions = sub.answerOptions;
  594 + types[addndex].answerList = this.setAnswer(
  595 + sub.questionType,
  596 + sub.correctAnswer
  597 + );
  598 + }
  599 + }
  600 + });
  601 + for (let i = 0; i < types.length; i++) {
  602 + if (types[i].qusType == 3) {
  603 + types[i].answerList = types[i].answerList.slice(0, -1);
  604 + }
  605 + if (types[i].subNum >= 5) {
  606 + item.subQuestions.splice(
  607 + types[i].index + i + 1,
  608 + 0,
  609 + deepClone(types[i])
  610 + );
  611 + }
  612 + }
  613 + }
  614 +
  615 + this.dialogVisible = true;
  616 + },
  617 + async saveAnswer() {
  618 + //保存答案
  619 + for (let i = 0; i < this.questionList.length; i++) {
  620 + if (this.questionList[0].subQuestions) {
  621 + for (let j = 0; j < this.questionList[i].subQuestions.length; j++) {
  622 + if (this.questionList[i].subQuestions[j].qusType) {
  623 + this.questionList[i].subQuestions.splice(j, 1);
  624 + }
  625 + }
  626 + } else {
  627 + if (this.questionList[i].qusType) {
  628 + this.questionList.splice(i, 1);
  629 + i--
  630 + }
  631 + }
  632 + }
  633 + const { data, status, message } = await this.$request.setExamAnswer({
  634 + examId: this.id,
  635 + questionList: [...this.questionList],
  636 + });
  637 + if (status == 0) {
  638 + this.$emit("saveSuccess");
  639 + } else {
  640 + this.$message.error(message);
  641 + }
  642 + },
  643 + },
  644 +};
  645 +</script>
  646 +
  647 +<style lang="scss" scoped>
  648 +.back {
  649 + width: 100%;
  650 + height: 56px;
  651 + border-bottom: 1px solid #e2e2e2;
  652 + display: flex;
  653 + align-items: center;
  654 + padding: 0 20px;
  655 + box-sizing: border-box;
  656 + .back-l {
  657 + display: flex;
  658 + align-items: center;
  659 + cursor: pointer;
  660 + flex-shrink: 0;
  661 + font-size: 18px;
  662 + font-weight: 500;
  663 + }
  664 + .fa-mail-reply-all {
  665 + font-size: 28px;
  666 + color: #b3b3b3;
  667 + margin-right: 12px;
  668 + }
  669 +}
  670 +.form-box {
  671 + padding: 20px;
  672 +}
  673 +.answer-title {
  674 + text-align: center;
  675 + font-size: 20px;
  676 + color: #333;
  677 + font-weight: 700;
  678 + padding-bottom: 20px;
  679 + .totals {
  680 + font-size: 16px;
  681 + color: #888;
  682 + font-weight: normal;
  683 + }
  684 +}
  685 +.question-title {
  686 + line-height: 40px;
  687 + .ipt {
  688 + width: 300px;
  689 + margin: 0 16px 0 10px;
  690 + :deep(.el-input__inner) {
  691 + border-radius: 20px;
  692 + border-color: #667ffd;
  693 + background: rgba($color: #667ffd, $alpha: 0.05);
  694 + }
  695 + }
  696 + .delete {
  697 + margin-right: 8px;
  698 + }
  699 + .title-txt {
  700 + margin-right: 20px;
  701 + font-size: 16px;
  702 + font-weight: 700;
  703 + }
  704 +}
  705 +.questions-ul {
  706 + border-left: 1px solid #e2e2e2;
  707 + border-top: 1px solid #e2e2e2;
  708 + margin: 12px 0;
  709 +}
  710 +.sub-questions {
  711 + width: 100%;
  712 + display: flex;
  713 + border-bottom: 1px solid #e2e2e2;
  714 + & > div {
  715 + min-height: 40px;
  716 + padding: 5px;
  717 + flex-shrink: 0;
  718 + border-right: 1px solid #e2e2e2;
  719 + display: flex;
  720 + justify-content: center;
  721 + align-items: center;
  722 + }
  723 + .qs-num {
  724 + width: 80px;
  725 + }
  726 + .qs-type {
  727 + width: 160px;
  728 + }
  729 + .qs-score,
  730 + .qs-partScore {
  731 + width: 160px;
  732 + }
  733 + .qs-options {
  734 + flex: 1;
  735 + }
  736 + .qs-set {
  737 + width: 80px;
  738 + }
  739 + .qs-options2 {
  740 + text-align: left;
  741 + justify-content: flex-start;
  742 + padding-left: 20px;
  743 + .answer-s {
  744 + cursor: pointer;
  745 + }
  746 + }
  747 + :deep(.el-select) {
  748 + .el-input__inner {
  749 + border-radius: 20px;
  750 + border-color: #667ffd;
  751 + width: 150px;
  752 + height: 32px;
  753 + line-height: 32px;
  754 + background: rgba($color: #667ffd, $alpha: 0.05);
  755 + }
  756 + .el-input__icon {
  757 + line-height: 32px;
  758 + }
  759 + }
  760 +}
  761 +.set-ans-btn {
  762 + width: 100%;
  763 + padding: 10px 0 10px 630px;
  764 + box-sizing: border-box;
  765 + border-bottom: 1px solid #e2e2e2;
  766 +}
  767 +.fa-exchange {
  768 + color: #667ffd;
  769 + cursor: pointer;
  770 + font-size: 16px;
  771 + margin-left: 10px;
  772 +}
  773 +.dia-btn {
  774 + border-radius: 20px;
  775 + margin: 0 20px;
  776 + padding: 10px 20px;
  777 +}
  778 +.dia-tips {
  779 + padding-bottom: 10px;
  780 +}
  781 +.answer-s {
  782 + width: 32px;
  783 + height: 28px;
  784 + cursor: pointer;
  785 + user-select: none;
  786 +}
  787 +.set-questions {
  788 + display: flex;
  789 + margin-bottom: 12px;
  790 + width: 100%;
  791 + .qs-num {
  792 + flex-shrink: 0;
  793 + margin-right: 10px;
  794 + }
  795 +}
  796 +.qs-options {
  797 + flex: 1;
  798 + .ipt {
  799 + margin-bottom: 5px;
  800 + }
  801 + .delButton {
  802 + border-color: #ff6868;
  803 + background: #ff6868 url("../../assets/images/arrow.png") no-repeat center;
  804 + background-size: 19px;
  805 + cursor: pointer;
  806 + color: transparent;
  807 + }
  808 + .ac {
  809 + border-color: #ff6868;
  810 + background: #ff6868;
  811 + color: #fff;
  812 + }
  813 +}
  814 +</style>
0 815 \ No newline at end of file
... ...
src/views/test/index.vue
1 1 <template>
2   - <div class="page-container">
  2 + <div class="page-container" :class="dialogVisible ? 'active' : ''">
3 3 <back-box>
4 4 <template slot="title">
5 5 <span>即时测-数据报表</span>
... ... @@ -25,7 +25,7 @@
25 25 v-if="role == 'ROLE_BANZHUREN'"
26 26 class="sel"
27 27 multiple
28   - v-model="query.subjectId"
  28 + v-model="query.subjectNames"
29 29 placeholder="选择科目"
30 30 @change="_QueryData"
31 31 >
... ... @@ -40,7 +40,7 @@
40 40 <el-select
41 41 v-else
42 42 class="sel"
43   - v-model="query.subjectId"
  43 + v-model="query.subjectNames"
44 44 placeholder="选择科目"
45 45 @change="_QueryData"
46 46 >
... ... @@ -89,87 +89,86 @@
89 89 </div>
90 90 </div>
91 91 <div class="table-box">
92   - <el-radio-group v-model="tabIndex" style="margin-bottom: 20px">
  92 + <el-radio-group
  93 + v-model="tabIndex"
  94 + @change="changeTab"
  95 + style="margin-bottom: 20px"
  96 + >
93 97 <el-radio-button :label="1">单卷测练报表</el-radio-button>
94 98 <el-radio-button :label="2">阶段测练报表</el-radio-button>
95 99 </el-radio-group>
96   - <div v-if="tabIndex == 1">
97   - <el-table
98   - :data="tableData"
99   - border
100   - style="width: 100%"
101   - :default-sort="{ prop: '', order: 'descending' }"
102   - >
  100 + <div v-if="tabIndex == 1" v-loading="loading">
  101 + <el-table :data="tableData" border style="width: 100%">
103 102 <el-table-column
104 103 prop="title"
105 104 label="试卷名称"
106 105 align="center"
107 106 ></el-table-column>
108 107 <el-table-column
109   - prop="totalScore"
  108 + prop="examPaperScore"
110 109 label="卷面分"
111 110 align="center"
112 111 width="100"
113 112 ></el-table-column>
114 113 <el-table-column
115   - prop="ceyan"
  114 + prop="answeredNum"
116 115 label="测验人数"
117 116 align="center"
118 117 ></el-table-column>
119 118 <el-table-column
120   - prop="shijian"
  119 + prop="examStartTime"
121 120 label="测验时间"
122 121 align="center"
123 122 ></el-table-column>
124 123 <el-table-column
125   - prop="pingjun"
  124 + prop="avgScore"
126 125 label="班平均分"
127 126 align="center"
128 127 ></el-table-column>
129 128 <el-table-column
130   - prop="zuigao"
  129 + prop="highestScore"
131 130 label="班最高分"
132 131 align="center"
133 132 ></el-table-column>
134 133 <el-table-column
135   - prop="zuidi"
  134 + prop="lowestScore"
136 135 label="班最低分"
137 136 align="center"
138 137 ></el-table-column>
139 138 <el-table-column
140   - prop="youxiu"
  139 + prop="excellenRate"
141 140 label="优秀数(率)"
142 141 sortable
143 142 align="center"
144 143 ><template slot-scope="scoped"
145   - >{{ scoped.row.youxiu }}%</template
  144 + >{{ scoped.row.excellenRate }}%</template
146 145 ></el-table-column
147 146 >
148 147 <el-table-column
149   - prop="lianghao"
  148 + prop="goodRate"
150 149 label="良好数(率)"
151 150 sortable
152 151 align="center"
153 152 ><template slot-scope="scoped"
154   - >{{ scoped.row.lianghao }}%</template
  153 + >{{ scoped.row.goodRate }}%</template
155 154 ></el-table-column
156 155 >
157 156 <el-table-column
158   - prop="jige"
  157 + prop="passRate"
159 158 label="及格数(率)"
160 159 sortable
161 160 align="center"
162 161 ><template slot-scope="scoped"
163   - >{{ scoped.row.jige }}%</template
  162 + >{{ scoped.row.passRate }}%</template
164 163 ></el-table-column
165 164 >
166 165 <el-table-column
167   - prop="bujige"
  166 + prop="failedRate"
168 167 label="不及格数(率)"
169 168 sortable
170 169 align="center"
171 170 ><template slot-scope="scoped"
172   - >{{ scoped.row.bujige }}%</template
  171 + >{{ scoped.row.failedRate }}%</template
173 172 ></el-table-column
174 173 >
175 174 <el-table-column label="操作" align="center">
... ... @@ -195,38 +194,33 @@
195 194 </template>
196 195 </el-table-column>
197 196 </el-table>
  197 + <div class="pagination-box">
  198 + <el-pagination
  199 + small=""
  200 + layout="total,prev, pager, next"
  201 + :hide-on-single-page="true"
  202 + :total="total"
  203 + @current-change="changePage"
  204 + :current-page="page"
  205 + :page-size="size"
  206 + >
  207 + </el-pagination>
  208 + </div>
198 209 </div>
199   - <div v-if="tabIndex == 2">
200   - <el-table
201   - :data="tableStage"
202   - border
203   - style="width: 100%"
204   - :default-sort="{ prop: '', order: 'descending' }"
205   - >
  210 + <div v-if="tabIndex == 2" v-loading="loading">
  211 + <el-table :data="tableData" border style="width: 100%">
206 212 <el-table-column
207   - prop="xuehao"
  213 + prop="studentCode"
208 214 label="学号"
209 215 align="center"
210 216 fixed
211 217 ></el-table-column>
212 218 <el-table-column
213   - prop="xingming"
  219 + prop="studentName"
214 220 label="姓名"
215 221 fixed
216 222 align="center"
217 223 ></el-table-column>
218   - <el-table-column label="阶段汇总" align="center">
219   - <el-table-column
220   - prop="totalScore"
221   - label="总分"
222   - align="center"
223   - ></el-table-column>
224   - <el-table-column
225   - prop="rank"
226   - label="排名"
227   - align="center"
228   - ></el-table-column>
229   - </el-table-column>
230 224 <el-table-column
231 225 align="center"
232 226 v-for="(item, index) in answerList"
... ... @@ -234,12 +228,12 @@
234 228 :label="item.title"
235 229 >
236 230 <el-table-column
237   - :prop="item.title + 'totalScore'"
238   - label="成绩"
  231 + :prop="'score' + index"
  232 + label="总分/成绩"
239 233 align="center"
240 234 ></el-table-column>
241 235 <el-table-column
242   - :prop="item.title + 'rank'"
  236 + :prop="'classRank' + index"
243 237 label="班名"
244 238 align="center"
245 239 ></el-table-column>
... ... @@ -253,227 +247,37 @@
253 247 </p>
254 248 </div>
255 249 <div class="edit-dia" v-show="dialogVisible" height="100%">
256   - <div class="back">
257   - <div class="back-l" @click="dialogVisible = false">
258   - <i class="fa fa-mail-reply-all"></i>
259   - <p>修改答案</p>
260   - </div>
261   - </div>
262   - <div class="form-box">
263   - <div class="answer-title">
264   - <p class="name">{{ form.title }}</p>
265   - <p class="totals">卷面总分:{{ form.score }}分</p>
266   - </div>
267   - <div v-if="questionList && questionList.length">
268   - <div v-for="(question, index) in questionList" :key="index">
269   - <p class="question-title">
270   - <span>{{ setBigNum(index) }}、</span>
271   - <span class="title-txt">{{ question.questionTitle }}</span>
272   - <span>共 {{ question.score }} 分</span>
273   - </p>
274   - <ul class="questions-ul">
275   - <li class="sub-questions">
276   - <div class="qs-num">题号</div>
277   - <div class="qs-type">题型</div>
278   - <div class="qs-score">分数</div>
279   - <div class="qs-partScore">漏选得分</div>
280   - <div class="qs-options qs-options2">选项设置</div>
281   - </li>
282   - <li
283   - v-for="(subQuestions, indexs) in question.subQuestions"
284   - :key="indexs"
285   - >
286   - <p
287   - class="set-ans-btn"
288   - v-if="
289   - subQuestions.qusType &&
290   - subQuestions.subNum &&
291   - subQuestions.subNum > 4
292   - "
293   - >
294   - <el-button type="primary" @click="setFormAns(index, indexs)"
295   - >批量设置答案</el-button
296   - >
297   - </p>
298   - <div v-else class="sub-questions">
299   - <div class="qs-num">{{ subQuestions.questionIndex }}</div>
300   - <div class="qs-type">
301   - {{ setSubPro(subQuestions.questionType) }}
302   - </div>
303   - <div class="qs-score">
304   - {{ subQuestions.score }}
305   - </div>
306   - <div class="qs-partScore">
307   - <p v-if="subQuestions.questionType != 3">--</p>
308   - <p v-else>{{ subQuestions.partScore }}</p>
309   - </div>
310   - <div class="qs-options qs-options2">
311   - <p v-if="subQuestions.questionType == 5">--</p>
312   - <p v-if="subQuestions.questionType == 4" class="answer-box">
313   - <span
314   - class="answer-s"
315   - :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
316   - @click="subQuestions.correctAnswer = 1"
317   - >✓</span
318   - >
319   - <span
320   - class="answer-s"
321   - :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
322   - @click="subQuestions.correctAnswer = 2"
323   - >✗</span
324   - >
325   - </p>
326   - <p v-if="subQuestions.questionType == 3" class="answer-box">
327   - <template
328   - v-for="option in subQuestions.answerOptions.split(',')"
329   - >
330   - <span
331   - v-if="option"
332   - class="answer-s"
333   - :class="
334   - subQuestions.correctAnswer.includes(option)
335   - ? 'active'
336   - : ''
337   - "
338   - :key="option"
339   - @click="changAnswer(subQuestions, option)"
340   - >{{ option }}</span
341   - >
342   - </template>
343   - </p>
344   - <p v-if="subQuestions.questionType == 2" class="answer-box">
345   - <template
346   - v-for="option in subQuestions.answerOptions.split(',')"
347   - >
348   - <span
349   - class="answer-s"
350   - v-if="option"
351   - :class="
352   - subQuestions.correctAnswer == option ? 'active' : ''
353   - "
354   - :key="option"
355   - @click="subQuestions.correctAnswer = option"
356   - >{{ option }}</span
357   - >
358   - </template>
359   - </p>
360   - </div>
361   - </div>
362   - </li>
363   - </ul>
364   - </div>
365   - </div>
366   - <div class="btn-box">
367   - <el-button type="danger" plain round @click="dialogVisible = false"
368   - >取消</el-button
369   - >
370   - <el-button type="primary" round @click="saveAnswer">保存</el-button>
371   - </div>
372   - </div>
  250 + <editAnswer
  251 + :id="form.id"
  252 + :title="form.title"
  253 + :score="form.examPaperScore"
  254 + @cancel="cancel"
  255 + @saveSuccess="saveSuccess"
  256 + />
373 257 </div>
374   - <el-dialog title="批量设置答案" :visible.sync="diaSetAns" width="400">
375   - <div class="qs-options">
376   - <p class="dia-tips">
377   - 请点击选项按钮设置答案,多选题题目之间用“,”隔开,若添加5道题:“AC,AD,BD,AC,CD”
378   - </p>
379   - <p>{{ setSubPro(formAns.qusType) }}:</p>
380   - <p class="ipt">
381   - <el-input
382   - v-model="formAns.answerList"
383   - @keydown.native="keydownAnswer($event)"
384   - ></el-input>
385   - </p>
386   - <p class="answer-box">
387   - <template v-if="formAns.qusType == 4">
388   - <span
389   - class="answer-s active"
390   - @click="
391   - formAns.answerList.length < formAns.subNum
392   - ? (formAns.answerList += '✓')
393   - : ''
394   - "
395   - >✓</span
396   - >
397   - <span
398   - class="answer-s active"
399   - @click="
400   - formAns.answerList.length < formAns.subNum
401   - ? (formAns.answerList += '✗')
402   - : ''
403   - "
404   - >✗</span
405   - >
406   - </template>
407   - <template v-if="formAns.qusType == 3">
408   - <span
409   - class="answer-s active"
410   - v-for="option in formAns.answerOptions"
411   - :key="option"
412   - @click="setMultiple(formAns, option)"
413   - >{{ option }}</span
414   - >
415   - <span
416   - class="answer-s active"
417   - @click="
418   - formAns.answerList.split(',').length < formAns.subNum
419   - ? (formAns.answerList += ',')
420   - : ''
421   - "
422   - >,</span
423   - >
424   - </template>
425   - <template v-if="formAns.qusType == 2" class="answer-box">
426   - <span
427   - class="answer-s active"
428   - v-for="option in formAns.answerOptions"
429   - :key="option"
430   - @click="
431   - formAns.answerList.length < formAns.subNum
432   - ? (formAns.answerList += option)
433   - : ''
434   - "
435   - >{{ option }}</span
436   - >
437   - </template>
438   - <span
439   - class="answer-s delButton"
440   - @click="formAns.answerList = formAns.answerList.slice(0, -1)"
441   - >x</span
442   - >
443   - </p>
444   - </div>
445   - <div class="dialog-footer" slot="footer">
446   - <el-button @click="saveFormAns">确 定</el-button>
447   - <el-button @click="diaSetAns = false">取 消</el-button>
448   - </div>
449   - </el-dialog>
450 258 </div>
451 259 </template>
452 260  
453 261 <script>
454   -import { formatDate, deepClone, checkAnswer } from "utils";
  262 +import { formatDate } from "utils";
  263 +import editAnswer from "./editAnswer.vue";
455 264 export default {
  265 + components: { editAnswer },
456 266 data() {
457 267 return {
458 268 role: "",
459 269 loading: false,
460 270 dialogVisible: false,
461   - diaSetAns: false,
462   - form: {},
463   - questionList: [],
464   - formAns: {
465   - listIndex: 0, //大题位置
466   - endIndex: 0, //相同题目最后一位题目的questionIndex
467   - qusType: "", //题目类型
468   - subNum: 0, //数量
469   - answerOptions: [], //答案选项
470   - answerList: "", //答案列表-字符串
  271 + form: {
  272 + id: "",
  273 + title: "",
  274 + examPaperScore: "",
471 275 },
472 276 date: "", //今天-昨天-本周
473 277 query: {
474 278 //搜索条件
475 279 classId: "",
476   - subjectId: "",
  280 + subjectNames: "",
477 281 startDay: "",
478 282 endDay: "",
479 283 day: "",
... ... @@ -481,207 +285,11 @@ export default {
481 285 classList: [], //班级
482 286 subjectList: [], //科目
483 287 tabIndex: 1, //选项卡
484   - tableData: [
485   - {
486   - title: "试卷一",
487   - totalScore: 10,
488   - ceyan: "40/50",
489   - shijian: "2022-11-9 21:30至22:30",
490   - pingjun: 60,
491   - zuigao: 90,
492   - zuidi: 50,
493   - youxiu: 50,
494   - lianghao: 40,
495   - jige: 30,
496   - bujige: 20,
497   - questionList: [
498   - {
499   - questionTitle: "f",
500   - score: 1,
501   - subQuestions: [
502   - {
503   - questionIndex: 1,
504   - questionType: 2,
505   - score: 1,
506   - partScore: 0,
507   - selectNum: 4,
508   - answerOptions: "A, B, C, D",
509   - correctAnswer: "B",
510   - },
511   - {
512   - questionIndex: 2,
513   - questionType: 2,
514   - score: 1,
515   - partScore: 0,
516   - selectNum: 4,
517   - answerOptions: "A, B, C, D,E,F",
518   - correctAnswer: "A",
519   - },
520   - {
521   - questionIndex: 3,
522   - questionType: 2,
523   - score: 1,
524   - partScore: 0,
525   - selectNum: 4,
526   - answerOptions: "A, B, C, D,E,F",
527   - correctAnswer: "A",
528   - },
529   - {
530   - questionIndex: 4,
531   - questionType: 2,
532   - score: 1,
533   - partScore: 0,
534   - selectNum: 4,
535   - answerOptions: "A, B, C, D,E,F",
536   - correctAnswer: "A",
537   - },
538   - {
539   - questionIndex: 5,
540   - questionType: 2,
541   - score: 1,
542   - partScore: 0,
543   - selectNum: 4,
544   - answerOptions: "A, B, C, D,E,F",
545   - correctAnswer: "A",
546   - },
547   - {
548   - questionIndex: 6,
549   - questionType: 3,
550   - score: 1,
551   - partScore: 0,
552   - selectNum: 4,
553   - answerOptions: "A, B, C, D,E,F",
554   - correctAnswer: "AB",
555   - },
556   - {
557   - questionIndex: 7,
558   - questionType: 4,
559   - score: 1,
560   - partScore: 0,
561   - selectNum: 0,
562   - answerOptions: [],
563   - correctAnswer: "1",
564   - },
565   - {
566   - questionIndex: 8,
567   - questionType: 3,
568   - score: 1,
569   - partScore: 0,
570   - selectNum: 4,
571   - answerOptions: "A, B, C, D,E,F",
572   - correctAnswer: "AB",
573   - },
574   - {
575   - questionIndex: 9,
576   - questionType: 3,
577   - score: 1,
578   - partScore: 0,
579   - selectNum: 4,
580   - answerOptions: "A, B, C, D,E,F",
581   - correctAnswer: "AB",
582   - },
583   - {
584   - questionIndex: 10,
585   - questionType: 3,
586   - score: 1,
587   - partScore: 0,
588   - selectNum: 4,
589   - answerOptions: "A, B, C, D,E,F",
590   - correctAnswer: "AB",
591   - },
592   - {
593   - questionIndex: 11,
594   - questionType: 3,
595   - score: 1,
596   - partScore: 0,
597   - selectNum: 4,
598   - answerOptions: "A, B, C, D,E,F",
599   - correctAnswer: "AB",
600   - },
601   - {
602   - questionIndex: 12,
603   - questionType: 3,
604   - score: 1,
605   - partScore: 0,
606   - selectNum: 4,
607   - answerOptions: "A, B, C, D,E,F",
608   - correctAnswer: "AB",
609   - },
610   - {
611   - questionIndex: 13,
612   - questionType: 4,
613   - score: 1,
614   - partScore: 0,
615   - selectNum: 0,
616   - answerOptions: [],
617   - correctAnswer: "1",
618   - },
619   - ],
620   - },
621   - ],
622   - },
623   - {
624   - title: "试卷二",
625   - totalScore: 20,
626   - ceyan: "30/50",
627   - shijian: "2022-11-9 21:30至22:30",
628   - pingjun: 80,
629   - zuigao: 92,
630   - zuidi: 53,
631   - youxiu: 45,
632   - lianghao: 56,
633   - jige: 20,
634   - bujige: 30,
635   - },
636   - ],
637   - tableStage: [
638   - {
639   - xuehao: 1,
640   - xingming: "丁芳菲",
641   - totalScore: 5,
642   - rank: 1,
643   - 周测卷20221130totalScore: 10,
644   - 周测卷20221130rank: 0,
645   - 周测卷20221131totalScore: 11,
646   - 周测卷20221131rank: 1,
647   - 周测卷20221132totalScore: 12,
648   - 周测卷20221132rank: 2,
649   - 周测卷20221132totalScore: 13,
650   - 周测卷20221132rank: 3,
651   - },
652   - {
653   - xuehao: 2,
654   - xingming: "丁芳",
655   - totalScore: 4,
656   - rank: 2,
657   - 周测卷20221130totalScore: 20,
658   - 周测卷20221130rank: 3,
659   - 周测卷20221131totalScore: 21,
660   - 周测卷20221131rank: 4,
661   - 周测卷20221132totalScore: 22,
662   - 周测卷20221132rank: 5,
663   - 周测卷20221132totalScore: 22,
664   - 周测卷20221132rank: 5,
665   - },
666   - ],
667   - answerList: [
668   - //设置多卷内容供tableStage表格数据用
669   - {
670   - title: "周测卷20221130",
671   - totalScore: 6,
672   - rank: 2,
673   - },
674   - {
675   - title: "周测卷20221131",
676   - totalScore: 7,
677   - rank: 3,
678   - },
679   - {
680   - title: "周测卷20221132",
681   - totalScore: 8,
682   - rank: 4,
683   - },
684   - ],
  288 + tableData: [],
  289 + answerList: [], //设置多卷内容供tableStage表格数据用
  290 + page: 1,
  291 + size: 20,
  292 + total: 0,
685 293 };
686 294 },
687 295 async created() {
... ... @@ -690,7 +298,7 @@ export default {
690 298 )?.role;
691 299 await this._QueryClassList();
692 300 await this._QuerySubjectList();
693   - // await this.setDate(1);
  301 + await this.setDate(1);
694 302 let startDay = this.query?.startDay;
695 303 if (!startDay) {
696 304 this.query.startDay = new Date();
... ... @@ -704,54 +312,17 @@ export default {
704 312 path: "/testAnalysis",
705 313 query: {
706 314 id: obj.id,
  315 + title: obj.title,
  316 + score: obj.examPaperScore,
707 317 },
708 318 });
709 319 },
710   - setSubPro(type) {
711   - let tit;
712   - switch (type) {
713   - case 2:
714   - tit = "单选题";
715   - break;
716   - case 3:
717   - tit = "多选题";
718   - break;
719   - case 4:
720   - tit = "判断题";
721   - break;
722   - case 5:
723   - tit = "主观题";
724   - break;
725   - }
726   - return tit;
  320 + cancel() {
  321 + this.dialogVisible = false;
727 322 },
728   - setBigNum(num) {
729   - let txt = "";
730   - let bigNum = [
731   - "一",
732   - "二",
733   - "三",
734   - "四",
735   - "五",
736   - "六",
737   - "七",
738   - "八",
739   - "九",
740   - "十",
741   - "十一",
742   - "十二",
743   - "十三",
744   - "十四",
745   - "十五",
746   - "十六",
747   - "十七",
748   - "十八",
749   - "十九",
750   - "二十",
751   - ];
752   - txt = bigNum[num];
753   -
754   - return txt;
  323 + saveSuccess() {
  324 + this.dialogVisible = false;
  325 + this._QueryData();
755 326 },
756 327 setDate(index) {
757 328 const that = this;
... ... @@ -783,7 +354,7 @@ export default {
783 354 that.query.endDay = formatDate(new Date(), "yyyy-MM-dd");
784 355 break;
785 356 case 4:
786   - if (aMonth > 1 && aMonth < 4) {
  357 + if (aMonth > 0 && aMonth < 4) {
787 358 aMonth = "01";
788 359 } else if (aMonth > 3 && aMonth < 7) {
789 360 aMonth = "04";
... ... @@ -821,175 +392,29 @@ export default {
821 392 }
822 393 }
823 394 },
824   - keydownAnswer(event) {
825   - //快速答案设置禁止输入
826   - if (
827   - event.key == "Meta" ||
828   - event.key == "CapsLock" ||
829   - event.key == "Shift" ||
830   - event.key == "Enter" ||
831   - event.key == "Alt" ||
832   - event.key == "Backspace" ||
833   - event.key == "Delete" ||
834   - event.key == "ArrowUp" ||
835   - event.key == "ArrowDown" ||
836   - event.key == "ArrowLeft" ||
837   - event.key == "v" ||
838   - event.key == "V" ||
839   - event.key == "ArrowRight"
840   - ) {
841   - return;
842   - } else {
843   - event.returnValue = "";
844   - }
845   - },
846   - setAnswer(type, ans) {
847   - let txt = "";
848   - if (type == 2) {
849   - txt = ans;
850   - } else if (type == 3) {
851   - txt = ans + ",";
852   - } else if (type == 4) {
853   - txt = ans == 1 ? "✓" : "✗";
854   - }
855   - return txt;
856   - },
857   - setMultiple(obj, answer) {
858   - //多选答案设置
859   - obj.answerList += answer;
860   - let str = obj.answerList;
861   - let str2 = checkAnswer(
862   - str,
863   - 3,
864   - obj.answerOptions.split(",").length,
865   - obj.answerList.length
866   - );
867   - obj.answerList = str2;
  395 + changePage(page) {
  396 + this.page = page;
  397 + this._QueryData();
868 398 },
869 399 edit(item) {
870   - //修改答案
871   - this.form = deepClone(item);
872   - this.questionList = deepClone(item?.questionList || []);
873   - this.questionList?.map((item) => {
874   - let types = [{}];
875   - let addndex = 0;
876   - item.subQuestions.map((sub, index) => {
877   - if (!!sub.questionType) {
878   - if (sub.questionType == types[addndex].qusType) {
879   - //同类型批量答案+1
880   - types[addndex].subNum += 1;
881   - if (
882   - types[addndex].answerOptions.length < sub.answerOptions.length
883   - ) {
884   - types[addndex].answerOptions = sub.answerOptions;
885   - }
886   - types[addndex].answerList += this.setAnswer(
887   - sub.questionType,
888   - sub.correctAnswer
889   - );
890   - if (index == item.subQuestions.length - 1) {
891   - //循环最后类型数量大于等于5,保存批量答案
892   - if (types[addndex].subNum && types[addndex].subNum >= 5) {
893   - types[addndex].endIndex = sub.questionIndex;
894   - types[addndex].index = index;
895   - }
896   - }
897   - } else {
898   - if (types[addndex].subNum && types[addndex].subNum >= 5) {
899   - //不同类型时如果原有类型数量大于等于5,保存批量答案
900   - types[addndex].endIndex =
901   - item.subQuestions[index - 1].questionIndex;
902   - types[addndex].index = index;
903   - addndex += 1;
904   - types[addndex] = {};
905   - }
906   - //不同类型初始化批量答案
907   - types[addndex].qusType = sub.questionType;
908   - types[addndex].subNum = 1;
909   - types[addndex].answerOptions = sub.answerOptions;
910   - types[addndex].answerList = this.setAnswer(
911   - sub.questionType,
912   - sub.correctAnswer
913   - );
914   - }
915   - }
916   - });
917   - for (let i = 0; i < types.length; i++) {
918   - if (types[i].qusType == 3) {
919   - types[i].answerList = types[i].answerList.slice(0, -1);
920   - }
921   - if (types[i].subNum >= 5) {
922   - item.subQuestions.splice(
923   - types[i].index + i,
924   - 0,
925   - deepClone(types[i])
926   - );
927   - }
928   - }
929   - });
  400 + this.form = { ...item };
930 401 this.dialogVisible = true;
931 402 },
932   - setFormAns(index, indexs) {
933   - //初始化要修改的答案
934   - this.formAns = { ...this.questionList[index].subQuestions[indexs] };
935   - this.formAns.listIndex = index;
936   - this.diaSetAns = true;
937   - },
938   - saveFormAns() {
939   - //批量修改答案
940   - let EndIndex;
941   - let subNum = this.formAns.subNum - 1;
942   - this.questionList[this.formAns.listIndex].subQuestions.some(
943   - (item, index) => {
944   - if (this.formAns.endIndex == item.questionIndex) {
945   - EndIndex = index;
946   - return;
947   - }
948   - }
949   - );
950   - for (let i = 0; i <= subNum; i++) {
951   - let correctAnswer = "";
952   - if (this.formAns.qusType == 2) {
953   - correctAnswer = this.formAns.answerList[subNum - i];
954   - } else if (this.formAns.qusType == 3) {
955   - correctAnswer = this.formAns.answerList.split(",")[subNum - i];
956   -
957   - console.log(this.formAns.answerList.split(",")[subNum - i]);
958   - } else if (this.formAns.qusType == 4) {
959   - correctAnswer = this.formAns.answerList[subNum - i] == "✓" ? 1 : 2;
960   - }
961   - this.questionList[this.formAns.listIndex].subQuestions[
962   - EndIndex - i
963   - ].correctAnswer = correctAnswer;
964   - }
965   - this.diaSetAns = false;
966   - },
967   - async saveAnswer() {
968   - //保存答案
969   - for (let i = 0; i < this.questionList.length; i++) {
970   - for (let j = 0; j < this.questionList[i].subQuestions.length; j++) {
971   - if (this.questionList[i].subQuestions[j].qusType) {
972   - this.questionList[i].subQuestions.splice(j, 1);
973   - }
974   - }
975   - }
976   - const { data, status, message } = await this.$request.modifyPaper({
977   - paperId: this.form.id,
978   - questionList: [...this.questionList],
979   - });
980   - if (status == 0) {
981   - this._QueryData();
982   - } else {
983   - this.$message.error(message);
984   - }
  403 + changeTab() {
  404 + this.page = 1;
  405 + this._QueryData();
985 406 },
986   -
987 407 async changClazz() {
  408 + this.page = 1;
988 409 await this._QuerySubjectList();
989   - await this.setDate(1);
  410 + await this._QueryData();
990 411 },
991 412 async _QueryClassList() {
992   - const { data, status, info } = await this.$request.fetchClassList();
  413 + const fetchClassList =
  414 + this.role == "ROLE_BANZHUREN"
  415 + ? this.$request.cTClassList
  416 + : this.$request.tClassList;
  417 + const { data, status, info } = await fetchClassList();
993 418 if (status === 0) {
994 419 this.classList = data.list.map((item) => {
995 420 return {
... ... @@ -1003,7 +428,12 @@ export default {
1003 428 }
1004 429 },
1005 430 async _QuerySubjectList() {
1006   - const { data, status, info } = await this.$request.fetchSubjectList({
  431 + const fetchSubjectList =
  432 + this.role == "ROLE_BANZHUREN"
  433 + ? this.$request.cTSubjectList
  434 + : this.$request.tSubjectList;
  435 +
  436 + const { data, status, info } = await fetchSubjectList({
1007 437 classId: this.query.classId,
1008 438 });
1009 439 if (status === 0) {
... ... @@ -1016,31 +446,135 @@ export default {
1016 446 }) || [];
1017 447 if (this.role == "ROLE_BANZHUREN") {
1018 448 this.subjectList.unshift({
1019   - value: "",
  449 + value: "全部",
1020 450 label: "全部",
1021 451 });
1022   - this.query.subjectId = [this.subjectList[0]?.value];
  452 + this.query.subjectNames.push(this.subjectList[0]?.value);
1023 453 } else {
1024   - this.query.subjectId = this.subjectList[0]?.value;
  454 + this.query.subjectNames = this.subjectList[0]?.value;
1025 455 }
1026 456 } else {
1027 457 this.$message.error(info);
1028 458 }
1029 459 },
1030 460 async _QueryData() {
  461 + this.tableData = [];
  462 + if (this.tabIndex == 1) {
  463 + this.examReportList();
  464 + } else {
  465 + this.phaseExamReport();
  466 + }
  467 + },
  468 + //单卷测练
  469 + async examReportList() {
1031 470 this.loading = true;
1032   - //多课时对比
1033 471 let query = {};
1034 472 for (let key in this.query) {
1035 473 if (this.query[key] != "") {
1036 474 query[key] = this.query[key];
1037 475 }
1038 476 }
1039   - const { data, status, info } = await this.$request.fetchQuizList({
  477 + if (this.role != "ROLE_BANZHUREN") {
  478 + query.subjectNames = [query.subjectNames];
  479 + } else {
  480 + if (
  481 + query["subjectNames"].length == 1 &&
  482 + query["subjectNames"][0] == "全部"
  483 + ) {
  484 + query["subjectNames"] = this.subjectList.map((item) => {
  485 + return item.value;
  486 + });
  487 + query["subjectNames"].shift();
  488 + }
  489 + }
  490 + const { data, status, info } = await this.$request.examReportList({
1040 491 ...query,
  492 + page: this.page,
  493 + size: this.size,
1041 494 });
1042 495 this.loading = false;
1043 496 if (status === 0) {
  497 + this.tableData = (data?.list && [...data?.list]) || [];
  498 + this.total = data.count;
  499 + } else {
  500 + this.$message.error(info);
  501 + }
  502 + },
  503 + //多卷测练
  504 + async phaseExamReport() {
  505 + this.loading = true;
  506 + let query = {};
  507 + for (let key in this.query) {
  508 + if (this.query[key] != "") {
  509 + if (key == "subjectNames" && this.role != "ROLE_BANZHUREN") {
  510 + query["subjectName"] = this.query[key];
  511 + } else {
  512 + query[key] = this.query[key];
  513 + }
  514 + }
  515 + }
  516 + if (this.role == "ROLE_BANZHUREN") {
  517 + if (
  518 + query["subjectNames"].length == 1 &&
  519 + query["subjectNames"][0] == "全部"
  520 + ) {
  521 + query["subjectNames"] = this.subjectList.map((item) => {
  522 + return item.value;
  523 + });
  524 + query["subjectNames"].shift();
  525 + }
  526 + }
  527 + const phaseExamReport =
  528 + this.role == "ROLE_BANZHUREN"
  529 + ? this.$request.cTPhaseExamReport
  530 + : this.$request.phaseExamReport;
  531 + const { data, status, info } = await phaseExamReport({
  532 + ...query,
  533 + });
  534 + this.loading = false;
  535 + if (status === 0) {
  536 + this.total = data.count;
  537 + let dataIdsList = [],
  538 + dataList = [];
  539 + data?.list.map((item) => {
  540 + item.examList.map((items) => {
  541 + if (this.role == "ROLE_JITUAN") {
  542 + // if (!dataIdsList.includes(items.grade)) {
  543 + // dataIdsList.push(items.grade);
  544 + // dataList.push(items);
  545 + // }
  546 + } else {
  547 + if (!dataIdsList.includes(items.title)) {
  548 + dataIdsList.push(items.title);
  549 + dataList.push(items);
  550 + }
  551 + }
  552 + });
  553 + });
  554 + console.log(dataList);
  555 + this.tableData = data?.list.map((item) => {
  556 + let params = {};
  557 + dataIdsList.map((ids, index) => {
  558 + params["score" + index] = "--";
  559 + params["classRank" + index] = "--";
  560 + item.examList.map((items) => {
  561 + if (this.role == "ROLE_JITUAN") {
  562 + if (items.title == ids) {
  563 + }
  564 + } else {
  565 + if (items.title == ids) {
  566 + params["score" + index] = items.score;
  567 + params["classRank" + index] = items.classRank;
  568 + }
  569 + }
  570 + });
  571 + });
  572 + return {
  573 + ...item,
  574 + ...params,
  575 + };
  576 + });
  577 + this.answerList = dataList;
1044 578 } else {
1045 579 this.$message.error(info);
1046 580 }
... ... @@ -1049,7 +583,24 @@ export default {
1049 583 };
1050 584 </script>
1051 585  
  586 +<style>
  587 +div::-webkit-scrollbar {
  588 + width: 3px;
  589 + height: 10px;
  590 +}
  591 +div::-webkit-scrollbar-thumb {
  592 + border-radius: 10px;
  593 + background-color: #ccc;
  594 +}
  595 +</style>
1052 596 <style lang="scss" scoped>
  597 +.page-container {
  598 + position: relative;
  599 + &.active {
  600 + height: 100%;
  601 + overflow: hidden;
  602 + }
  603 +}
1053 604 .table-box {
1054 605 margin: 0 20px;
1055 606 padding: 16px;
... ... @@ -1062,60 +613,9 @@ export default {
1062 613 padding-left: 2px;
1063 614 }
1064 615 }
1065   -
1066   -.fa-exchange {
1067   - color: #667ffd;
1068   - cursor: pointer;
1069   - font-size: 16px;
1070   - margin-left: 10px;
1071   -}
1072   -.dia-btn {
1073   - border-radius: 20px;
1074   - margin: 0 20px;
1075   - padding: 10px 20px;
1076   -}
1077   -.dia-tips {
1078   - padding-bottom: 10px;
1079   -}
1080   -.answer-s {
1081   - width: 32px;
1082   - height: 28px;
1083   - cursor: pointer;
1084   - user-select: none;
1085   -}
1086   -.set-questions {
1087   - display: flex;
1088   - margin-bottom: 12px;
1089   - width: 100%;
1090   - .qs-num {
1091   - flex-shrink: 0;
1092   - margin-right: 10px;
1093   - }
1094   -}
1095   -.qs-options {
1096   - flex: 1;
1097   - .ipt {
1098   - margin-bottom: 5px;
1099   - }
1100   - .delButton {
1101   - border-color: #ff6868;
1102   - background: #ff6868 url("../../assets/images/arrow.png") no-repeat center;
1103   - background-size: 19px;
1104   - cursor: pointer;
1105   - color: transparent;
1106   - }
1107   - .ac {
1108   - border-color: #ff6868;
1109   - background: #ff6868;
1110   - color: #fff;
1111   - }
1112   -}
1113 616 .down {
1114 617 padding-top: 16px;
1115 618 }
1116   -.page-container {
1117   - position: relative;
1118   -}
1119 619 .edit-dia {
1120 620 position: absolute;
1121 621 left: 0;
... ... @@ -1123,128 +623,9 @@ export default {
1123 623 right: 0;
1124 624 bottom: 0;
1125 625 width: 100%;
1126   - height: calc(100vh - 80px);
  626 + height: calc(100vh - 70px);
1127 627 background: #fff;
1128 628 overflow-y: auto;
1129 629 z-index: 10;
1130   - .back {
1131   - width: 100%;
1132   - height: 56px;
1133   - border-bottom: 1px solid #e2e2e2;
1134   - display: flex;
1135   - align-items: center;
1136   - padding: 0 20px;
1137   - box-sizing: border-box;
1138   - .back-l {
1139   - display: flex;
1140   - align-items: center;
1141   - cursor: pointer;
1142   - flex-shrink: 0;
1143   - font-size: 18px;
1144   - font-weight: 500;
1145   - }
1146   - .fa-mail-reply-all {
1147   - font-size: 28px;
1148   - color: #b3b3b3;
1149   - margin-right: 12px;
1150   - }
1151   - }
1152   - .form-box {
1153   - padding: 20px;
1154   - }
1155   - .answer-title {
1156   - text-align: center;
1157   - font-size: 20px;
1158   - color: #333;
1159   - font-weight: 700;
1160   - padding-bottom: 20px;
1161   - .totals {
1162   - font-size: 16px;
1163   - color: #888;
1164   - font-weight: normal;
1165   - }
1166   - }
1167   - .question-title {
1168   - line-height: 40px;
1169   - .ipt {
1170   - width: 300px;
1171   - margin: 0 16px 0 10px;
1172   - :deep(.el-input__inner) {
1173   - border-radius: 20px;
1174   - border-color: #667ffd;
1175   - background: rgba($color: #667ffd, $alpha: 0.05);
1176   - }
1177   - }
1178   - .delete {
1179   - margin-right: 8px;
1180   - }
1181   - .title-txt {
1182   - margin-right: 20px;
1183   - font-size: 16px;
1184   - font-weight: 700;
1185   - }
1186   - }
1187   - .questions-ul {
1188   - border-left: 1px solid #e2e2e2;
1189   - border-top: 1px solid #e2e2e2;
1190   - margin: 12px 0;
1191   - }
1192   - .sub-questions {
1193   - width: 100%;
1194   - display: flex;
1195   - border-bottom: 1px solid #e2e2e2;
1196   - & > div {
1197   - min-height: 40px;
1198   - padding: 5px;
1199   - flex-shrink: 0;
1200   - border-right: 1px solid #e2e2e2;
1201   - display: flex;
1202   - justify-content: center;
1203   - align-items: center;
1204   - }
1205   - .qs-num {
1206   - width: 80px;
1207   - }
1208   - .qs-type {
1209   - width: 160px;
1210   - }
1211   - .qs-score,
1212   - .qs-partScore {
1213   - width: 160px;
1214   - }
1215   - .qs-options {
1216   - flex: 1;
1217   - }
1218   - .qs-set {
1219   - width: 80px;
1220   - }
1221   - .qs-options2 {
1222   - text-align: left;
1223   - justify-content: flex-start;
1224   - padding-left: 20px;
1225   - .answer-s {
1226   - cursor: pointer;
1227   - }
1228   - }
1229   - :deep(.el-select) {
1230   - .el-input__inner {
1231   - border-radius: 20px;
1232   - border-color: #667ffd;
1233   - width: 150px;
1234   - height: 32px;
1235   - line-height: 32px;
1236   - background: rgba($color: #667ffd, $alpha: 0.05);
1237   - }
1238   - .el-input__icon {
1239   - line-height: 32px;
1240   - }
1241   - }
1242   - }
1243   - .set-ans-btn {
1244   - width: 100%;
1245   - padding: 10px 0 10px 630px;
1246   - box-sizing: border-box;
1247   - border-bottom: 1px solid #e2e2e2;
1248   - }
1249 630 }
1250 631 </style>
1251 632 \ No newline at end of file
... ...