studentReport.vue 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448
  1. <template>
  2. <!-- 学生报告 -->
  3. <!-- v-loading="loading" element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.5)" :element-loading-text="loadingText" -->
  4. <BookFlip :book-pages="bookPageImages" bookBg="student" :requestLoading="loading" :openLoading="openLoading" :coverTitle="`${stuClasName}${studentName}分析报告册`" subtitle="供参考学生使用" ref="bookFlipBox" @OpenBookImages="OpenBookImages" @PdfLoadEnd="PdfLoadEnd">
  5. <!-- 自定义每页内容 -->
  6. <template #default="slotProps">
  7. <template v-if="slotProps.type == 'web_mode'">
  8. <div class="area_page" style="position: absolute;top: -9999999px;z-index: -10;">
  9. <!-- 用于获取div的高度 默认隐藏不显示 -->
  10. <div class="area_title" ref="areaReportTitle">
  11. <p>{{ reportTitle }}</p>
  12. <p>{{ stuClasName }}{{ studentName }}分析报告</p>
  13. </div>
  14. <div class="area_module" ref="standardScoreChartDes">
  15. <div class="area_module_describe" v-if="multiSubjectData.maxSubject || multiSubjectData.minSubject" style="margin-top: 0;">
  16. 说明:从标准分情况来看,这次考试<template v-if="multiSubjectData.maxSubject"><span style="color: #3ba272">{{ multiSubjectData.maxSubject }}</span>表现突出,请继续保持</template><template v-if="multiSubjectData.minSubject">;<span style="color: #ee6666">{{ multiSubjectData.minSubject }}</span>标准分明显低于其他学科,可能会对总体排名造成影响,可结合错题梳理核心知识点,精准定位薄弱环节,制定针对性的提升计划,以实现各科均衡发展,进一步巩固整体成绩</template>。
  17. </div>
  18. </div>
  19. <div class="area_module" ref="multiSuggestionModule">
  20. <div class="area_module_title">总结建议</div>
  21. <div class="area_module_describe" style="margin-top: 0;" v-html="suggestionHtml"></div>
  22. <div class="pring_jg"></div>
  23. </div>
  24. <template v-for="(subject,subKey) in multiSubjectData.singleSubject">
  25. <div class="area_module" :ref="`singleSubjectSuggestion_${subKey}`" v-if="singleSubjectData?.[subKey]?.suggestionHtml">
  26. <div class="area_module_title">总结建议</div>
  27. <div class="area_module_describe" style="margin-top: 0;" v-html="singleSubjectData?.[subKey]?.suggestionHtml"></div>
  28. <div class="pring_jg"></div>
  29. </div>
  30. </template>
  31. </div>
  32. <div class="area_page web_area_page" v-for="page in pageCount" :key="`${pageKey}_${page}`">
  33. <template v-if="page == 1">
  34. <div class="area_title">
  35. <p>{{ reportTitle }}</p>
  36. <p>{{ stuClasName }}{{ studentName }}分析报告</p>
  37. </div>
  38. <div class="area_header bg_purple">
  39. <img :src="headerLeftIcon" class="header_icon_left" />
  40. 总分成绩分析
  41. <img :src="headerRightIcon" class="header_icon_right" />
  42. </div>
  43. <div class="pring_jg"></div>
  44. </template>
  45. <template v-for="(tableData,index) in multiSubjectData.tableList">
  46. <template v-for="(itemTable,itemIndex) in tableData">
  47. <div class="area_module" v-if="multiSubjectData.tablePagesNum[index][itemIndex] == page && itemTable.length > 0">
  48. <div class="area_module_title">成绩单</div>
  49. <div class="area_module_table">
  50. <el-table border :data="itemTable" stripe align="center">
  51. <el-table-column v-for="header in (multiSubjectData?.staticHeaderData ?? [])" align="center" :label="header.name" min-width="100" show-overflow-tooltip>
  52. <template slot-scope="scope">
  53. {{ scope.row?.[header.prop] || '-' }}
  54. </template>
  55. </el-table-column>
  56. <el-table-column v-for="header in (multiSubjectData?.headerList?.[index]?.[itemIndex] ?? [])" align="center" :label="header.name" min-width="100" show-overflow-tooltip>
  57. <template slot-scope="scope">
  58. <template v-if="header.prop == 'score'">
  59. <!-- * 1-得分显示分数,小题分显示分数,2-得分显示分数,小题分显示对错
  60. * 3-得分显示对错,小题分显示分数,4-得分显示对错,小题分显示对错
  61. * 5-得分显示等级,小题分显示分数,6-得分显示等级,小题分显示对错 -->
  62. <template v-if="multiSubjectData.studentOpenness == 3 || multiSubjectData.studentOpenness == 4">
  63. <template v-if="!isNaN(scope.row?.[header.prop])">
  64. <img class="right_or_wrong_icon" v-if="scope.row.fullScore == scope.row?.[header.prop]" src="@/assets/report/score_yes_icon.webp" />
  65. <img class="right_or_wrong_icon" v-else-if="scope.row?.[header.prop] == 0" src="@/assets/report/score_no_icon.webp" />
  66. <img class="right_or_wrong_icon" v-else src="@/assets/report/score_dimidiate_icon.webp" />
  67. </template>
  68. <template v-else>{{ scope.row?.[header.prop] ?? '-' }}</template>
  69. </template>
  70. <template v-else>{{ scope.row?.[header.prop] ?? '-' }}</template>
  71. </template>
  72. <template v-else>{{ scope.row?.[header.prop] ?? '-' }}</template>
  73. </template>
  74. </el-table-column>
  75. </el-table>
  76. </div>
  77. </div>
  78. <template v-if="multiSubjectData.tablePagesNum[index][itemIndex] == page && itemTable.length > 0">
  79. <div class="pring_jg" style="height: 29px;border-bottom: 1px solid #F3F3F3;box-sizing: border-box;"></div>
  80. <div class="pring_jg"></div>
  81. </template>
  82. </template>
  83. </template>
  84. <div class="area_module" v-if="multiSubjectData.chartPagesNum==page && ((multiSubjectData.standardScoreAnalysisStatus === 0 && schoolType == 2) || schoolType == 1) && multiSubjectData.datay.length>0">
  85. <div class="area_module_title">标准分分析图</div>
  86. <div class="area_module_chart">
  87. <DifferenceChart v-if="multiSubjectData.datay.length" :datax="multiSubjectData.datax" unit="" :datay="multiSubjectData.datay" :isClick="false" :rate="0" :gridLeft="0" :gridRight="0" :gridTop="20" :fontSize="14" :fontColor="'#333333'" :showDataZoom="false" style="height: 270px !important;min-height: 270px !important;"></DifferenceChart>
  88. </div>
  89. <div class="area_module_describe" v-if="multiSubjectData.maxSubject || multiSubjectData.minSubject">
  90. 说明:从标准分情况来看,这次考试<template v-if="multiSubjectData.maxSubject"><span style="color: #3ba272">{{ multiSubjectData.maxSubject }}</span>表现突出,请继续保持</template><template v-if="multiSubjectData.minSubject">;<span style="color: #ee6666">{{ multiSubjectData.minSubject }}</span>标准分明显低于其他学科,可能会对总体排名造成影响,可结合错题梳理核心知识点,精准定位薄弱环节,制定针对性的提升计划,以实现各科均衡发展,进一步巩固整体成绩</template>。
  91. </div>
  92. <div class="pring_jg"></div>
  93. </div>
  94. <!-- <div class="area_module" v-if="historyExamData.pageNum==page && historyExamData.chartData.length > 0">
  95. <div class="area_module_title">历次标准分追踪分析图</div>
  96. <div class="area_module_chart">
  97. <LineChart v-if="historyExamData.datay.length>0" :datax="historyExamData.datax" :datay="historyExamData.datay" :title="historyExamData.title"
  98. :extraText="false" :showBackground="false" :isShowLabel="true" labelColor="#333333" :legendList="historyExamData.legendList" :tooltipData="historyExamData.tooltipData" :gridLeft="0" :gridRight="0" :gridTop="25" :fontSize="14" :fontColor="'#333333'" :showCheckBox="false" reportHeight="270px" style="min-height:270px!important;">
  99. </LineChart>
  100. </div>
  101. <div class="pring_jg"></div>
  102. </div> -->
  103. <div class="area_module" v-if="suggestionHtml && multiSuggestionPageNum == page">
  104. <div class="area_module_title">总结建议</div>
  105. <div class="area_module_describe" style="margin-top: 0;" v-html="suggestionHtml"></div>
  106. <div class="pring_jg"></div>
  107. </div>
  108. <!-- 单科 -->
  109. <template v-for="(subject,subKey) in multiSubjectData.singleSubject">
  110. <template v-if="singleSubjectData?.[subKey]?.titlePageNum == page">
  111. <div class="area_header bg_purple">
  112. <img :src="headerLeftIcon" class="header_icon_left" />
  113. {{subject.subjectName}}成绩分析
  114. <img :src="headerRightIcon" class="header_icon_right" />
  115. </div>
  116. <div class="pring_jg"></div>
  117. </template>
  118. <!-- 成绩单 -->
  119. <template v-for="(tableData,index) in (singleSubjectData?.[subKey]?.scrolTableList || [])">
  120. <template v-for="(itemTable,itemIndex) in tableData">
  121. <div class="area_module" v-if="singleSubjectData?.[subKey]?.scrolTablePagesNum?.[index]?.[itemIndex] == page && itemTable.length > 0">
  122. <div class="area_module_title">成绩单</div>
  123. <div class="area_module_table">
  124. <el-table border :data="itemTable" stripe align="center">
  125. <el-table-column v-for="header in (singleSubjectData?.[subKey]?.scrolHeaderList?.[index]?.[itemIndex] ?? [])" align="center" :label="header.name" min-width="100" show-overflow-tooltip>
  126. <template slot-scope="scope">
  127. <template v-if="header.prop=='score'">
  128. <!-- * 1-得分显示分数,小题分显示分数,2-得分显示分数,小题分显示对错
  129. * 3-得分显示对错,小题分显示分数,4-得分显示对错,小题分显示对错
  130. * 5-得分显示等级,小题分显示分数,6-得分显示等级,小题分显示对错 -->
  131. <template v-if="(scope.row.studentOpenness == 3 || scope.row.studentOpenness == 4) && scope.row?.score">
  132. <template v-if="!isNaN(scope?.row?.score)">
  133. <img class="right_or_wrong_icon" v-if="scope.row.fullScore == scope.row.score" src="@/assets/report/score_yes_icon.webp" />
  134. <img class="right_or_wrong_icon" v-else-if="scope.row.score === 0" src="@/assets/report/score_no_icon.webp" />
  135. <img class="right_or_wrong_icon" v-else src="@/assets/report/score_dimidiate_icon.webp" />
  136. </template>
  137. <template v-else>{{ scope.row.score }}</template>
  138. </template>
  139. <template v-else>{{ scope?.row?.[header.prop] ?? '-' }}</template>
  140. </template>
  141. <template v-else>{{ scope?.row?.[header.prop] ?? '-' }}</template>
  142. </template>
  143. </el-table-column>
  144. </el-table>
  145. </div>
  146. </div>
  147. <template v-if="singleSubjectData?.[subKey]?.scrolTablePagesNum?.[index]?.[itemIndex] == page && itemTable.length > 0">
  148. <div class="pring_jg" style="height: 29px;border-bottom: 1px solid #F3F3F3;box-sizing: border-box;"></div>
  149. <div class="pring_jg"></div>
  150. </template>
  151. </template>
  152. </template>
  153. <!-- 小题分 大题 知识点 能力要素 自定义分组 -->
  154. <template v-for="group in (singleSubjectData?.[subKey]?.groupQuestionData || [])">
  155. <div class="area_module" v-if="group.chartPagesNum == page && group.datay.length > 0 && group.type!='smallQuestionData'">
  156. <div class="area_module_title">{{group.groupName}}分析图</div>
  157. <div class="area_module_chart" v-if="group.datay.length > 0">
  158. <BarChart v-if="group.type=='bigQuestionData'" :datax="group.datax" :datay="group.datay" unit="" typeName="" :showNuitY="false" :unit="'%'" :showTooltip="false" :isShowMarkLine="false" :gridLeft="0" :gridRight="0" :gridTop="20" :fontSize="14" :fontColor="'#333333'" :showDataZoom="false" style="height: 270px;"></BarChart>
  159. <RadarCharts v-else :showLegend="false" :reportHeight="`300px`" :showDataLabel="true" :showTooltip="false" :data="group.radarChartData" :unit="'%'" :legendList="[]" legendLeft="center" :showCheckBox="false" :openShowAllLegend="false" :showRadiusAxis="false" :fontSize="14" :fontColor="'#333333'" :style="{height: 'auto',minHeight:'100% !important'}"></RadarCharts>
  160. </div>
  161. <div class="pring_jg"></div>
  162. </div>
  163. <template v-for="(tableData,index) in group.tableList">
  164. <template v-for="(itemTable,itemIndex) in tableData">
  165. <div class="area_module" v-if="group.tablePagesNum[index][itemIndex] == page && itemTable.length > 0">
  166. <div class="area_module_title">{{group.groupName}}分析表</div>
  167. <div class="area_module_table">
  168. <el-table border :data="itemTable" stripe align="center">
  169. <el-table-column v-for="header in (group?.staticHeader ?? [])" align="center" :label="header.name" :min-width="header.prop=='smallQuestionNames'?120:90" show-overflow-tooltip>
  170. <template slot-scope="scope">
  171. {{ scope.row[header.prop] || '-' }}
  172. </template>
  173. </el-table-column>
  174. <el-table-column v-for="header in (group?.headerList?.[index]?.[itemIndex] ?? [])" align="center" :label="header.name" :min-width="header.prop=='smallQuestionNames'?120:90" show-overflow-tooltip>
  175. <template slot-scope="scope">
  176. <template v-if="header.prop == 'score'">
  177. <!-- * 1-得分显示分数,小题分显示分数,2-得分显示分数,小题分显示对错
  178. * 3-得分显示对错,小题分显示分数,4-得分显示对错,小题分显示对错
  179. * 5-得分显示等级,小题分显示分数,6-得分显示等级,小题分显示对错 -->
  180. <template v-if="group.studentOpenness == 2 || group.studentOpenness == 4 || group.studentOpenness == 6">
  181. <template v-if="!isNaN(scope?.row?.score)">
  182. <img class="right_or_wrong_icon" v-if="scope.row.fullScore == scope.row.score" src="@/assets/report/score_yes_icon.webp" />
  183. <img class="right_or_wrong_icon" v-else-if="scope.row.score == 0" src="@/assets/report/score_no_icon.webp" />
  184. <img class="right_or_wrong_icon" v-else src="@/assets/report/score_dimidiate_icon.webp" />
  185. </template>
  186. <template v-else>{{ scope?.row?.score ?? '-' }}</template>
  187. </template>
  188. <template v-else>{{ scope.row.score || '-' }}</template>
  189. </template>
  190. <!-- 包含小题 -->
  191. <template v-else-if="header.prop == 'smallQuestionNames' && scope?.row?.[header.prop] && Object.prototype.toString.call(scope.row[header.prop]) == '[object Array]'">
  192. {{ scope.row[header.prop].join('、') }}
  193. </template>
  194. <template v-else-if="header.prop=='scoreRateStr'">
  195. <template v-if="scope?.row?.scoreRate && !isNaN(scope?.row?.scoreRate)">
  196. <span style="color:#EE6666;" v-if="Number(scope?.row?.scoreRate) < 60">{{ scope?.row?.[header.prop] }}</span>
  197. <span style="color:#FAC858;" v-else-if="Number(scope?.row?.scoreRate) >= 60 && Number(scope?.row?.scoreRate) < 80">{{ scope?.row?.[header.prop] }}</span>
  198. <span style="color:#3BA272;" v-else-if="Number(scope?.row?.scoreRate) >= 80 && Number(scope?.row?.scoreRate) <= 100">{{ scope?.row?.[header.prop] }}</span>
  199. <span v-else>{{ scope?.row?.[header.prop] ?? '-'}}</span>
  200. </template>
  201. <template v-else>{{ scope?.row?.[header.prop] ?? '-'}}</template>
  202. </template>
  203. <template v-else-if="header.prop == 'difficultyName'">
  204. <span :class="GetDifficultyClass(scope.row[header.prop])"></span>
  205. <span>{{ GetDifficultyName(scope.row[header.prop]) }}</span>
  206. </template>
  207. <template v-else>{{ scope.row[header.prop] || '-' }}</template>
  208. </template>
  209. </el-table-column>
  210. </el-table>
  211. </div>
  212. </div>
  213. <template v-if="group.tablePagesNum[index][itemIndex] == page && itemTable.length > 0">
  214. <div class="pring_jg" style="height: 29px;border-bottom: 1px solid #F3F3F3;box-sizing: border-box;"></div>
  215. <div class="pring_jg"></div>
  216. </template>
  217. </template>
  218. </template>
  219. </template>
  220. <!-- 历次 -->
  221. <!-- <div class="area_module" v-if="singleSubjectData?.[subKey]?.historyExamData?.pageNum==page && singleSubjectData[subKey].historyExamData.chartData.length > 0">
  222. <div class="area_module_title">历次标准分追踪分析图</div>
  223. <div class="area_module_chart">
  224. <LineChart v-if="singleSubjectData?.[subKey]?.historyExamData?.datay.length>0" :datax="singleSubjectData[subKey].historyExamData.datax" :datay="singleSubjectData[subKey].historyExamData.datay" :title="singleSubjectData[subKey].historyExamData.title"
  225. :extraText="false" :showBackground="false" :isShowLabel="true" labelColor="#333333" :legendList="singleSubjectData[subKey].historyExamData.legendList" :tooltipData="singleSubjectData[subKey].historyExamData.tooltipData" :gridLeft="0" :gridRight="0" :gridTop="25" :fontSize="14" :fontColor="'#333333'" :showCheckBox="false" reportHeight="270px" style="min-height:270px!important;">
  226. </LineChart>
  227. </div>
  228. <div class="pring_jg"></div>
  229. </div> -->
  230. <div class="area_module" v-if="singleSubjectData?.[subKey]?.suggestionHtml && singleSubjectData?.[subKey]?.suggestionPageNum == page">
  231. <div class="area_module_title">总结建议</div>
  232. <div class="area_module_describe" style="margin-top: 0;" v-html="singleSubjectData?.[subKey]?.suggestionHtml"></div>
  233. <div class="pring_jg"></div>
  234. </div>
  235. <!-- 答题卡 -->
  236. <template v-for="(paperItem,paperIndex) in (singleSubjectData?.[subKey]?.paperImageList || [])">
  237. <div class="area_module area_module_img" v-if="singleSubjectData?.[subKey]?.paperImagePageNum?.[paperIndex] == page">
  238. <PaperImage v-if="paperItem.picUrl" :paperImgUrl="paperItem.picUrl" :usedCardType="singleSubjectData?.[subKey]?.usedCardType" :drawData="paperItem.questionVOS || []" :isDrag="false" :isWheel="false" :isShowContextMenu="false" rotateDeg="-90"></PaperImage>
  239. </div>
  240. </template>
  241. </template>
  242. <div class="area_page_number">第 {{ page }} 页</div>
  243. </div>
  244. </template>
  245. <template v-else>
  246. <!-- 生成翻书效果 -->
  247. <div class="gradient"></div>
  248. <img :src="slotProps.content" style="width: 100%;height: 100%;" />
  249. </template>
  250. </template>
  251. </BookFlip>
  252. </template>
  253. <script>
  254. import BookFlip from './components/bookFlip.vue';
  255. import BarChart from "@/views/analysisReport/components/dCharts/barChart"; //单柱状图组件
  256. import RadarCharts from "@/views/analysisReport/components/dCharts/radarCharts";//G10-G1雷达图
  257. import DifferenceChart from "@/views/analysisReport/components/dCharts/differenceChart"; //率差图
  258. import LineChart from "@/views/analysisReport/components/dCharts/lineChart";//折线图
  259. import PaperImage from '@/components/PaperImage.vue';//答题卡
  260. import { mapGetters } from "vuex";
  261. import {getApiName} from '@/utils/common';
  262. // import { jsPDF } from "jspdf";
  263. import html2canvas from "html2canvas";
  264. export default {
  265. components: { BookFlip, BarChart, RadarCharts, DifferenceChart, LineChart,PaperImage},
  266. data() {
  267. return {
  268. pageKey:1,
  269. headerLeftIcon: require("@/assets/report/header_left_student.webp"),
  270. headerRightIcon: require("@/assets/report/header_right_student.webp"),
  271. // 书页数据(长度为4,偶数页)
  272. colors: this.$global.getScorePerformanceAnalysis(),//按顺序显示的20个颜色值
  273. pageCount:15,//页数 第一页不处理
  274. printPageHeight:1245,//A4纸高度 去掉边距 40
  275. chartHeight:270,//echart 高度
  276. moduleHeightData:[],//每个模块的高度
  277. modulePageData:[],//每个模块对应的页码
  278. stuClasName:'',
  279. multiSubjectData: {
  280. tablePagesNum:[],
  281. tableList:[],
  282. headerList:[],
  283. staticHeaderData:[],
  284. singleSubject:[],
  285. standardScoreAnalysisStatus: 0,
  286. studentOpenness: '', //学生信息
  287. datax: [], //图数据
  288. datay: [], //图数据
  289. tooltipData: [],
  290. maxSubject: '',
  291. minSubject: ''
  292. },//总分成绩分析
  293. historyExamData: {
  294. pageNum:'',
  295. chartData: [],
  296. datax: [],
  297. datay: [],
  298. title: [],
  299. legendList: [],
  300. tooltipData:[]
  301. }, //总分历次信息(联考)
  302. suggestionHtml: null,//总结建议
  303. multiSuggestionPageNum:'',//总分 总结建议
  304. singleSubjectData:[],//单科数据
  305. bookPageImages:[],//生成的图片地址
  306. // showReportLoading:false,
  307. targetProgress:0,
  308. timer:null,
  309. loading:true,
  310. loadingText:'拼命加载中(1%)……',
  311. openLoading:false,
  312. };
  313. },
  314. computed: {
  315. reportTitle() {
  316. return this?.$store?.state?.report?.examSelectItem?.examName ?? '';
  317. },
  318. reportParam() {
  319. return {
  320. examLevel: this.$store.state.report.examLevel, // 任务等级联考还是单校
  321. // schoolId: this.$store.state.report.studentReportFilterObject.schoolId, // 学校id
  322. // contrastExamIds: this.$store.state.report.lastExamSelectIds, //多次考试任务对比ID,不包含当前任务ID
  323. // examId: this.$store.state.report.examId, // 当前考试ID
  324. // subjectCode: this.$store.state.report.studentReportFilterObject.subjectCode, //科目code
  325. // subjectGroupType: this.$store.state.report.filterObject.subjectGroupType, // 科目是否为组合
  326. // isTotal: this.$store.state.report.filterObject.isTotal, //是否为总分科目 1为总分 0为非总分
  327. // classIdCode: this.$store.state.report.studentReportFilterObject.classIdCode, // 班级idcode
  328. // classGroupName: this.$store.state.report.studentReportFilterObject.classGroupName, // 班级名称
  329. // registrationName: this.$store.state.report.studentReportFilterObject.registrationName, // 学籍名称
  330. // studentName:this.$store.state.report.studentReportFilterObject.studentName, //学生名称
  331. // registrationCode:this.$store.state.report.studentReportFilterObject.registrationCode //学生学籍号
  332. examLevel: this.$store.state.report.filterObject.examLevel, //1-联考 2-单校
  333. contrastExamIds: this.$store.state.report.filterObject.contrastExamIds, //多次考试任务对比ID,不包含当前任务ID
  334. examId: this.$store.state.report.filterObject.examId, //考试id
  335. subjectCode: this.$store.state.report.filterObject.subjectCode, //科目code
  336. subjectGroupType: this.$store.state.report.filterObject.subjectGroupType, //是否为组合科目 1为组合科目 0为非组合科目
  337. isTotal: this.$store.state.report.filterObject.isTotal //是否为总分科目 1为总分 0为非总分
  338. }
  339. },//分析报告公共参数变量
  340. ...mapGetters(["userInfo"]),
  341. studentName() {
  342. return this.userInfo.userName;
  343. },
  344. schoolType() {
  345. return sessionStorage.getItem('schoolType') //1:单校 2:联校
  346. },
  347. },
  348. watch: {
  349. // 监听 filterObject 对象变化(注意要开启深度监听)
  350. async reportParam() {
  351. // clearTimeout(this.timer); // 清除定时器,停止重复执行
  352. // this.timer = null;
  353. this.PageInit();//初始加载数据
  354. },//监听筛选数据变化
  355. },
  356. async created() {
  357. this.setHtmlFontSize();
  358. // 监听窗口缩放,实时更新
  359. window.addEventListener('resize', this.setHtmlFontSize);
  360. // 可选:监听页面加载完成后再设置一次(避免初始渲染问题)
  361. window.addEventListener('load', this.setHtmlFontSize);
  362. this.PageInit();//页面初始加载数据
  363. },
  364. destroyed(){
  365. // 根组件卸载时销毁监听
  366. window.removeEventListener('resize', this.setHtmlFontSize);
  367. document.documentElement.style.fontSize = '';
  368. },
  369. methods: {
  370. //初始化设置
  371. setHtmlFontSize(){
  372. // 设计稿宽度(根据实际设计稿调整,例如 1920px)
  373. const designWidth = 1920;
  374. // 设计稿中 1rem 对应的 px 值(例如 16px)
  375. const baseFontSize = 16;
  376. // 获取当前浏览器窗口宽度
  377. const windowWidth = document.documentElement.clientWidth || window.innerWidth;
  378. // 计算当前窗口下的 html font-size(按设计稿比例缩放)
  379. const htmlFontSize = (windowWidth / designWidth) * baseFontSize;
  380. // 应用到 html 元素
  381. document.documentElement.style.fontSize = `${htmlFontSize}px`;
  382. },
  383. async PageInit() {
  384. // let currentProgress = 1;
  385. // this.loadingText = `拼命加载中(1%)……`;
  386. // this.timer = setInterval(() => {
  387. // currentProgress++;
  388. // this.loadingText = `拼命加载中(${currentProgress}%)……`;
  389. // }, 500);
  390. this.loading = true;
  391. this.openLoading = false;
  392. this.bookPageImages = [];
  393. // this.targetProgress = 1;
  394. // this.showReportLoading = true;
  395. this.pageCount = 15;
  396. this.$nextTick(()=>{
  397. const titleHeight = this.$refs?.areaReportTitle?.offsetHeight || 0;
  398. const reportTitleHeight = titleHeight + 82;
  399. this.moduleHeightData = [reportTitleHeight];//每个模块的高度 初始标题高度
  400. })
  401. this.modulePageData = [1];
  402. this.multiSuggestionPageNum = '';//总分 总结建议
  403. this.singleSubjectData = [];//单科数据
  404. this.pageKey += 1;
  405. //多科成绩总览 科目标准分分析
  406. await this.QueryMultiSubjectData();
  407. //学生端查询总分,多科历次信息(联考)
  408. // await this.QueryHistoryExamData();
  409. // 学生端查询总分,多科总结建议信息(联考)
  410. await this.QuerySuggestionData();
  411. let index = 0;
  412. for (const element of this.multiSubjectData.singleSubject){
  413. //单科每个模块标题分页
  414. this.singleSubjectData.push({
  415. titlePageNum:this.SingleChartPage(82),
  416. scrolTablePagesNum:[],//成绩单
  417. scrolTableList:[],
  418. scrolHeaderList:[],
  419. groupQuestionData:[],//小题分组、大题分组、知识点、自定义分组
  420. historyExamData:{
  421. pageNum:'',
  422. chartData: [],
  423. datax: [],
  424. datay: [],
  425. title: [],
  426. legendList: [],
  427. tooltipData:[]
  428. },
  429. suggestionPageNum:'',//总结建议分页
  430. suggestionHtml: '',//总结建议
  431. paperImageList:[],//答题卡
  432. paperImagePageNum:[],//答题卡页码
  433. })
  434. await this.QueryOneSubjectData(element.subjectCode,index);
  435. await this.QueryOneSubjectSmallQuestionData(element.subjectCode,index);
  436. await this.QueryOneSubjectGroupQuestionData(element.subjectCode,index);
  437. await this.QueryOneSubjectCustomGroupQuestion(element.subjectCode,index);
  438. //学生端查询单科-历次查询(联考)
  439. // await this.QueryOneSubjectHistoryExamData(element.subjectCode,index);
  440. await this.QueryOneSubjectSuggestionData(element.subjectCode,index);
  441. await this.FindStudentCard(element.subjectCode,index);
  442. index++; // 每次循环后索引+1
  443. }
  444. this.pageCount = this.modulePageData.length > 0 ? Math.max(...this.modulePageData) : 1;
  445. this.loading = false;
  446. this.$emit('isPdfDataLoadEnd');//是否显示下载pdf按钮
  447. console.log(this.pageCount,this.modulePageData,this.moduleHeightData,777777)
  448. // this.$nextTick(()=>{
  449. // setTimeout(()=>{
  450. // // clearTimeout(this.timer); // 清除定时器,停止重复执行
  451. // // this.GetPageImages(currentProgress);
  452. // this.GetPageImages();
  453. // },2000)
  454. // })
  455. },
  456. //下载预览图片
  457. OpenBookImages(){
  458. if(this.bookPageImages.length){
  459. this.$refs.bookFlipBox.showFullScreen()
  460. }else{
  461. this.openLoading = true;
  462. this.$nextTick(()=>{
  463. setTimeout(()=>{
  464. this.GetPageImages();
  465. },2000)
  466. })
  467. }
  468. },
  469. //获取图片
  470. async GetPageImages(){
  471. //获取所有的area_page 元素
  472. const elements = document.querySelectorAll(".web_mode .web_area_page");
  473. // const stepLens = elements?.length || 1;
  474. // const remainingProgress = 100 - progress;//剩余进度
  475. // const perStepProgress = Math.floor(remainingProgress / stepLens) || 1; // 每次增加的进度 向下取整
  476. // const pdf = new jsPDF("p", "pt", "a4"); // 'p'表示纵向,'a4'表示A4纸张尺寸
  477. // const pdfWidth = pdf.internal.pageSize.getWidth(); //获取pdf的宽度
  478. // const pdfHeight = pdf.internal.pageSize.getHeight(); //获取pdf的高度
  479. // let yPos = 0; //当前图像在pdf页面上的垂直位置的变量
  480. let i = 1;
  481. // let currentProgress = progress;
  482. for (const element of elements) {
  483. await html2canvas(element, {
  484. scale: 2, // 增加缩放比例
  485. useCORS: true, // 允许跨域
  486. logging: false, // 是否打印调试日志(开发时开启,生产关闭)
  487. letterRendering: true, // 文字抗锯齿 启用字母渲染
  488. }).then(async (canvas) => {
  489. // const imgData = canvas.toDataURL("image/png");
  490. const blob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
  491. const imgUrl = URL.createObjectURL(blob);
  492. console.log(imgUrl,89999)
  493. this.bookPageImages.push(imgUrl);
  494. // currentProgress = Math.min(Math.round((i / stepLens) * 100),100);
  495. // currentProgress = Math.min(progress + i * perStepProgress,100);
  496. // this.targetProgress = currentProgress
  497. // this.loadingText = `拼命加载中(${currentProgress}%)……`;
  498. // const imgProps = pdf.getImageProperties(imgData); // 获取图像的属性,包括宽度和高度
  499. // const imgWidth = imgProps.width;
  500. // const imgHeight = imgProps.height;
  501. // const ratio = Math.min(pdfWidth / imgWidth, pdfHeight / imgHeight); //计算图片的缩放比例
  502. // const adjustWidth = imgWidth * ratio;
  503. // const adjustHeight = imgHeight * ratio;
  504. // // 在添加每个图像之前,检查当前页面的高度是否足够。如果不够,则添加新页面,并将 yPos 重置为 0
  505. // if (yPos + adjustHeight > pdfHeight) {
  506. // pdf.addPage();
  507. // yPos = 0;
  508. // }
  509. // // 将图像添加到pdf中
  510. // pdf.addImage(imgData, "PNG", 0, yPos, adjustWidth, adjustHeight);
  511. // yPos += adjustHeight;
  512. // // 如果添加图像后剩余空间不足一页,则添加新页面
  513. // if (yPos > pdfHeight) {
  514. // pdf.addPage();
  515. // yPos = 0;
  516. // }
  517. i++;
  518. })
  519. }
  520. // if(currentProgress < 100){
  521. // this.loadingText = `拼命加载中(100%)……`;
  522. // }
  523. // 保存pdf文件
  524. // pdf.save("联校报告册.pdf");
  525. // this.showReportLoading = false;
  526. setTimeout(()=>{
  527. // this.loading = false;
  528. this.openLoading = false;
  529. this.$refs.bookFlipBox.showFullScreen()
  530. },500)
  531. },
  532. //总分成绩分析
  533. async QueryMultiSubjectData() {
  534. await this.$api.reportStudent[getApiName()].queryMultiSubjectData({
  535. ...this.reportParam,
  536. subjectGroupType: 1, // 科目是否为组合
  537. isTotal: 1, //是否为总分科目 1为总分 0为非总分
  538. }).then(res => {
  539. if (res.code == 200 && res.data) {
  540. const titleData = res?.data?.titleData || [];
  541. this.multiSubjectData.studentOpenness = res?.data?.studentOpenness ?? '';
  542. const headerData = titleData.filter(item=>item.prop!='imgUrlList' && item.prop!='subjectName');
  543. const staticHeaderData = titleData.filter(item=>item.prop=='subjectName');
  544. const tableData = res?.data?.tableData || [];
  545. this.stuClasName = tableData?.find(item=>item.subjectCode==0)?.className || '';
  546. //表格分页
  547. const pageTableData = this.TableRowAndColumnPage(headerData,tableData,7,1);//8列一个表
  548. this.multiSubjectData.tablePagesNum = pageTableData.tablePagesNum;
  549. this.multiSubjectData.tableList = pageTableData.tableList;
  550. this.multiSubjectData.headerList = pageTableData.headerList;
  551. this.multiSubjectData.staticHeaderData = staticHeaderData;//静态表头
  552. //标准分分析图
  553. this.multiSubjectData.datax = []
  554. this.multiSubjectData.datay = []
  555. this.multiSubjectData.tooltipData = []
  556. this.multiSubjectData.standardScoreAnalysisStatus = res?.data?.standardScoreAnalysisStatus ?? 1;
  557. //总分
  558. const totalScore = tableData.filter(item => item.isTotal == 1)
  559. //组合
  560. const subjectGroup = tableData.filter(
  561. item => item.isTotal == 0 && item.subjectGroupType == 1
  562. )
  563. //单科
  564. const singleSubject = tableData.filter(
  565. item => item.isTotal == 0 && item.subjectGroupType == 0
  566. )
  567. this.multiSubjectData.singleSubject = singleSubject;//单科
  568. const chartData = [...totalScore, ...subjectGroup, ...singleSubject];
  569. let datax = [],datay = [];
  570. chartData.forEach(item => {
  571. this.multiSubjectData.datax.push(item?.subjectName ?? '-')
  572. this.multiSubjectData.datay.push(!item?.standardScore || item?.standardScore == '-' ? 0 : item?.standardScore)
  573. if (item.isTotal == 0 && item.subjectGroupType == 0) {
  574. datax.push(item?.subjectName ?? '')
  575. datay.push(item?.standardScore ?? 0)
  576. }
  577. })
  578. let maxSubject = [],minSubject = []
  579. datay.forEach((item, k) => {
  580. if (Number(item) > 0) {
  581. maxSubject.push(datax[k])
  582. }
  583. if (Number(item) < 0) {
  584. minSubject.push(datax[k])
  585. }
  586. })
  587. this.multiSubjectData.maxSubject = maxSubject.join('、')
  588. this.multiSubjectData.minSubject = minSubject.join('、')
  589. //标准分分析图分页
  590. this.$nextTick(()=>{
  591. if((this.multiSubjectData.standardScoreAnalysisStatus === 0 && this.schoolType == 2) || this.schoolType == 1){
  592. const desHeight = this.$refs?.standardScoreChartDes?.offsetHeight || 0;
  593. const divHeight = 404 + desHeight;
  594. this.multiSubjectData.chartPagesNum = this.SingleChartPage(this.multiSubjectData.datay.length > 0 ? divHeight : 0);
  595. }else{
  596. this.multiSubjectData.chartPagesNum = this.SingleChartPage(0);
  597. }
  598. // console.log(divHeight,desHeight,this.multiSubjectData.chartPagesNum,13322133)
  599. })
  600. } else {
  601. this.multiSubjectData.studentOpenness = '';
  602. this.multiSubjectData.tablePagesNum = [];
  603. this.multiSubjectData.tableList = [];
  604. this.multiSubjectData.headerList = [];
  605. this.multiSubjectData.singleSubject = [];
  606. // 标准分分析
  607. this.multiSubjectData.datax = []
  608. this.multiSubjectData.datay = []
  609. this.multiSubjectData.tooltipData = []
  610. this.multiSubjectData.standardScoreAnalysisStatus = 1;
  611. this.multiSubjectData.maxSubject = []
  612. this.multiSubjectData.minSubject = []
  613. this.multiSubjectData.chartPagesNum = '';//标准分分析图分页
  614. }
  615. })
  616. },
  617. //总分,多科历次信息
  618. async QueryHistoryExamData() {
  619. await this.$api.reportStudent[getApiName()].queryHistoryExamData({
  620. ...this.reportParam,
  621. subjectGroupType: 1, // 科目是否为组合
  622. isTotal: 1, //是否为总分科目 1为总分 0为非总分
  623. }).then(res => {
  624. if (res.code == 200 && res.data) {
  625. const detailData = (res.data?.detailData || []).reverse();
  626. this.historyExamData.chartData = detailData;
  627. const selectNames = res.data.selectNames || [];
  628. const selectVal = selectNames?.[0]?.prop ?? '';
  629. this.historyExamData.datax = [];
  630. let datay = [],tooltipData = [];
  631. detailData.forEach(item => {
  632. this.historyExamData.datax.push(item.examName)
  633. datay.push(item[selectVal])
  634. tooltipData.push({
  635. name: selectNames?.[0]?.name ?? '',
  636. value: item[selectVal]
  637. })
  638. })
  639. this.historyExamData.datay = [datay];
  640. this.historyExamData.tooltipData = [tooltipData];
  641. this.historyExamData.pageNum = this.SingleChartPage(this.historyExamData.chartData.length > 0 ? 363 : 0);
  642. } else {
  643. this.historyExamData.chartData = [];
  644. this.historyExamData.tooltipData = [];
  645. this.historyExamData.datax = [];
  646. this.historyExamData.datay = [];
  647. this.historyExamData.pageNum = '';
  648. }
  649. })
  650. },
  651. // 学生端查询总分,多科总结建议信息(联考)
  652. async QuerySuggestionData() {
  653. await this.$api.reportStudent[getApiName()].querySuggestionData({
  654. ...this.reportParam,
  655. subjectGroupType: 1, // 科目是否为组合
  656. isTotal: 1, //是否为总分科目 1为总分 0为非总分
  657. }).then(res => {
  658. if (res.code == 200 && res.data) {
  659. const data = res.data;
  660. const upSubjectList = data.upSubjectData || [];
  661. const downSubjectList = data.downSubjectData || [];
  662. const upSubjectData = upSubjectList.map(item => {
  663. if (data.studentOpenness == 1 || data.studentOpenness == 2) {
  664. return `${item.subjectName}(得分${item.score})`
  665. } else {
  666. return `${item.subjectName}(${item.score})`
  667. }}).join('、')
  668. const downSubjectData = downSubjectList.map(item => {
  669. if (data.studentOpenness == 1 || data.studentOpenness == 2) {
  670. return `${item.subjectName}(得分${item.score})`
  671. } else {
  672. return `${item.subjectName}(${item.score})`
  673. }}).join('、')
  674. if(data?.fullScore && data?.fullScore!='-'){
  675. const scoreText = data?.studentOpenness == 1 || data?.studentOpenness == 2 ? '总分' : '总分标准分为'
  676. const unit = data?.studentOpenness == 1 || data?.studentOpenness == 2 ? '分' : '';
  677. this.suggestionHtml = `${data?.studentName || ''}同学,本次考试${scoreText}<span style="color: #2e64fa">${data?.fullScore}</span>${unit},整体处于${data?.summarySuggestionLevel},`;
  678. if(upSubjectData){
  679. this.suggestionHtml += `<span style="color: #3ba272">${upSubjectData}</span>是你的优势学科,建议通过提分练习进行强化,继续保持这类学科的优势性${downSubjectData ? ';' : '。'}`;
  680. }
  681. if(downSubjectData){
  682. this.suggestionHtml += `<span style="color: #f56c6c">${downSubjectData}</span>是你的劣势学科,建议先加强学习,熟练掌握薄弱知识点的基础,然后通过提分练习进行巩固和强化,争取下次考试获得更优异的成绩!`;
  683. }
  684. }else{
  685. this.suggestionHtml = null
  686. }
  687. } else {
  688. this.suggestionHtml = null
  689. }
  690. this.$nextTick(()=>{
  691. const suggestionHeight = this.$refs?.multiSuggestionModule?.offsetHeight || 0;
  692. // console.log(suggestionHeight,99888)
  693. this.multiSuggestionPageNum = this.SingleChartPage(this.suggestionHtml?suggestionHeight:0);
  694. })
  695. })
  696. },
  697. //学生端查询单科-我的成绩
  698. async QueryOneSubjectData(subjectCode,index) {
  699. await this.$api.reportStudent[getApiName()].queryOneSubjectData({
  700. ...this.reportParam,
  701. subjectGroupType: 0, // 科目是否为组合
  702. isTotal: 0, //是否为总分科目 1为总分 0为非总分
  703. subjectCode:subjectCode
  704. }).then(res => {
  705. if (res.code == 200 && res.data) {
  706. const headData = [{
  707. name:'班级',
  708. prop:'className',
  709. display:true
  710. },{
  711. name:'原始分',
  712. prop:'score',
  713. display:res?.data?.scoreStatus === 0 //0-显示,1-不显示
  714. },{
  715. name:'赋分',
  716. prop:'rateScore',
  717. display:res?.data?.rateScoreStatus === 0 //0-显示,1-不显示
  718. },{
  719. name:'班排',
  720. prop:'classRank',
  721. display:res?.data?.classRankStatus === 0
  722. },{
  723. name:'年排',
  724. prop:'schoolRank',
  725. display:res?.data?.schoolRankStatus === 0
  726. },{
  727. name:'联排',
  728. prop:'examRank',
  729. display:res?.data?.examRankStatus === 0 && this.reportParam.examLevel == 1 && this.schoolType == 2
  730. },{
  731. name:'区排',
  732. prop:'regionRank',
  733. display:res?.data?.regionRankStatus === 0
  734. },{
  735. name:'赋分等级',
  736. prop:'rateScoreName',
  737. display:res?.data?.rateScoreStatus === 0
  738. },{
  739. name:'标准分',
  740. prop:'standardScore',
  741. display:(res?.data?.standardScoreStatus === 0 && this.schoolType == 2) || this.schoolType == 1
  742. },{
  743. name:'学业等级',
  744. prop:'gradeName',
  745. display:(res?.data?.gradeNameStatus === 0 && this.schoolType == 2) || this.schoolType == 1
  746. },{
  747. name:'得分率',
  748. prop:'scoreRate',
  749. display:res?.data?.scoreRateStatus === 0
  750. },{
  751. name:'班级最高分',
  752. prop:'classMaxScore',
  753. display:res?.data?.classMaxScoreStatus === 0 && this.schoolType == 2
  754. },{
  755. name:'年级最高分',
  756. prop:'gradeMaxScore',
  757. display:res?.data?.gradeMaxScoreStatus === 0 && this.schoolType == 2
  758. },{
  759. name:'联校最高分',
  760. prop:'examMaxScore',
  761. display:res?.data?.examMaxScoreStatus === 0 && this.schoolType == 2
  762. },{
  763. name:'班级均分',
  764. prop:'classAvgScore',
  765. display:res?.data?.classAvgScoreStatus === 0 && this.schoolType == 2
  766. },{
  767. name:'年级均分',
  768. prop:'gradeAvgScore',
  769. display:res?.data?.gradeAvgScoreStatus === 0 && this.schoolType == 2
  770. },{
  771. name:'联校均分',
  772. prop:'examAvgScore',
  773. display:res?.data?.examAvgScoreStatus === 0 && this.schoolType == 2
  774. }]
  775. const tableData = [res.data] || [];
  776. const headerList = headData.filter(item=>item.display);
  777. const pageTableData = this.TableRowAndColumnPage(headerList,tableData,8,1);//8列一个表
  778. this.singleSubjectData[index].scrolTablePagesNum = pageTableData.tablePagesNum;
  779. this.singleSubjectData[index].scrolTableList = pageTableData.tableList;
  780. this.singleSubjectData[index].scrolHeaderList = pageTableData.headerList;//表头
  781. } else {
  782. this.singleSubjectData[index].scrolTablePagesNum = [];
  783. this.singleSubjectData[index].scrolTableList = [];
  784. this.singleSubjectData[index].scrolHeaderList = [];//表头
  785. }
  786. })
  787. },
  788. //学生端查询单科-小题分析(表格-图表)
  789. async QueryOneSubjectSmallQuestionData(subjectCode,index) {
  790. await this.$api.reportStudent[getApiName()].queryOneSubjectSmallQuestionData({
  791. ...this.reportParam,
  792. subjectGroupType: 0, // 科目是否为组合
  793. isTotal: 0, //是否为总分科目 1为总分 0为非总分
  794. subjectCode:subjectCode
  795. }).then(res => {
  796. if (res.code == 200 && res?.data?.tableData?.length > 0) {
  797. const tableData = res.data.tableData || [];
  798. const titleData = res.data.titleData || [];
  799. const studentOpenness = res.data?.studentOpenness ?? '';//控制得分显示对错或值
  800. this.TableChartData(tableData, titleData, studentOpenness, index,'smallQuestionData','小题');
  801. }
  802. })
  803. },
  804. //学生端查询单科-大题分析,知识点分析,能力要素分析(联考)
  805. async QueryOneSubjectGroupQuestionData(subjectCode,index) {
  806. await this.$api.reportStudent[getApiName()].queryOneSubjectGroupQuestionData({
  807. ...this.reportParam,
  808. subjectGroupType: 0, // 科目是否为组合
  809. isTotal: 0, //是否为总分科目 1为总分 0为非总分
  810. subjectCode:subjectCode
  811. }).then(res => {
  812. if (res.code == 200 && res.data) {
  813. const { bigQuestion, knowledgePointQuestion, abilityQuestion } = res.data
  814. if (bigQuestion && bigQuestion?.tableData?.length > 0) {
  815. const tableData = bigQuestion.tableData || [];
  816. const titleData = bigQuestion.titleData || [];
  817. const studentOpenness = bigQuestion?.studentOpenness ?? '';
  818. this.TableChartData(tableData, titleData, studentOpenness, index,'bigQuestionData','大题');
  819. }
  820. if (knowledgePointQuestion && knowledgePointQuestion?.tableData?.length > 0) {
  821. const tableData = knowledgePointQuestion.tableData || [];
  822. const titleData = knowledgePointQuestion.titleData || [];
  823. const studentOpenness = knowledgePointQuestion?.studentOpenness ?? '';
  824. this.TableChartData(tableData, titleData, studentOpenness, index,'knowledgePointQuestionData','知识点');
  825. }
  826. if (abilityQuestion && abilityQuestion?.tableData?.length > 0) {
  827. const tableData = abilityQuestion.tableData || [];
  828. const titleData = abilityQuestion.titleData || [];
  829. const studentOpenness = abilityQuestion?.studentOpenness ?? '';
  830. this.TableChartData(tableData, titleData, studentOpenness, index,'abilityQuestionData','能力要素');
  831. }
  832. }
  833. })
  834. },
  835. //学生端查询单科-自定义分组(联考)
  836. async QueryOneSubjectCustomGroupQuestion(subjectCode,index) {
  837. await this.$api.reportStudent[getApiName()].queryOneSubjectCustomGroupQuestion({
  838. ...this.reportParam,
  839. subjectGroupType: 0, // 科目是否为组合
  840. isTotal: 0, //是否为总分科目 1为总分 0为非总分
  841. subjectCode:subjectCode
  842. }).then(res => {
  843. if (res.code == 200 && res.data) {
  844. const customQuestionData = res?.data?.customQuestionData ?? []
  845. if (customQuestionData && customQuestionData.length > 0) {
  846. customQuestionData.forEach((item, key) => {
  847. const tableData = item?.questionData?.tableData || []
  848. const titleData = item?.questionData?.titleData || []
  849. const studentOpenness = res.data?.studentOpenness ?? ''
  850. this.TableChartData(tableData, titleData, studentOpenness, index,`customQuestionData${key}`,item.customName);
  851. })
  852. }
  853. }
  854. })
  855. },
  856. //学生端查询单科-历次查询(联考)
  857. async QueryOneSubjectHistoryExamData(subjectCode,index) {
  858. await this.$api.reportStudent[getApiName()].queryOneSubjectHistoryExamData({
  859. ...this.reportParam,
  860. subjectGroupType: 0, // 科目是否为组合
  861. isTotal: 0, //是否为总分科目 1为总分 0为非总分
  862. subjectCode:subjectCode
  863. }).then(res => {
  864. if (res.code == 200 && res.data) {
  865. const detailData = (res.data?.detailData || []).reverse();
  866. // console.log(this.singleSubjectData[index],98899)
  867. this.singleSubjectData[index].historyExamData.chartData = detailData;
  868. const selectNames = res.data.selectNames || [];
  869. const selectVal = selectNames?.[0]?.prop ?? '';
  870. this.singleSubjectData[index].datax = [];
  871. let datay = [],tooltipData = [];
  872. detailData.forEach(item => {
  873. this.singleSubjectData[index].historyExamData.datax.push(item.examName)
  874. datay.push(item[selectVal])
  875. tooltipData.push({
  876. name: selectNames?.[0]?.name ?? '',
  877. value: item[selectVal]
  878. })
  879. })
  880. this.singleSubjectData[index].historyExamData.datay = [datay];
  881. this.singleSubjectData[index].historyExamData.tooltipData = [tooltipData];
  882. this.singleSubjectData[index].historyExamData.pageNum = this.SingleChartPage(this.singleSubjectData[index].historyExamData.chartData.length > 0 ? 363 : 0);
  883. }
  884. })
  885. },
  886. //学生端查询单科-总结建议
  887. async QueryOneSubjectSuggestionData(subjectCode,index) {
  888. await this.$api.reportStudent[getApiName()].queryOneSubjectSuggestionData({
  889. ...this.reportParam,
  890. subjectGroupType: 0, // 科目是否为组合
  891. isTotal: 0, //是否为总分科目 1为总分 0为非总分
  892. subjectCode:subjectCode
  893. }).then(res => {
  894. if (res.code == 200 && res.data) {
  895. const data = res.data
  896. //* 1-得分显示分数,小题分显示分数,2-得分显示分数,小题分显示对错
  897. //* 3-得分显示对错,小题分显示分数,4-得分显示对错,小题分显示对错
  898. //* 5-得分显示等级,小题分显示分数,6-得分显示等级,小题分显示对错
  899. const upSubjectList = data?.upSubjectData || [];
  900. const downSubjectList = data?.downSubjectData || [];
  901. const upSubjectData = upSubjectList.map(item => {
  902. if (data.studentOpenness == 1 || data.studentOpenness == 2) {
  903. return `${item.subjectName}得分<span style="color: #3BA272;">${item.score}</span>分`
  904. } else {
  905. return `${item.subjectName}标准分为<span style="color: #3BA272;">${item.score}</span>`
  906. }
  907. }).join('、')
  908. const downSubjectData = downSubjectList.map(item => {
  909. if (data.studentOpenness == 1 || data.studentOpenness == 2) {
  910. return `${item.subjectName}得分<span style="color: #EE6666;">${item.score}</span>分`
  911. } else {
  912. return `${item.subjectName}标准分为<span style="color: #EE6666;">${item.score}</span>`
  913. }
  914. }).join('、')
  915. this.singleSubjectData[index].suggestionHtml = '';
  916. if (data.studentName && (upSubjectData || downSubjectData)) {
  917. this.singleSubjectData[index].suggestionHtml = `${data.studentName}同学,本次考试`
  918. }
  919. if (upSubjectData) {
  920. this.singleSubjectData[index].suggestionHtml += `${upSubjectData},是你的优势学科,建议通过提分练习进行强化,继续保持这类学科的优势性!`
  921. }
  922. if (downSubjectData) {
  923. this.singleSubjectData[index].suggestionHtml += `${downSubjectData},是你的劣势学科,建议先加强学习,熟练掌握薄弱知识点的基础,然后通过提分练习进行巩固和强化,争取下次考试获得更优异的成绩!`
  924. }
  925. this.$nextTick(()=>{
  926. const suggestionHeight = this.$refs?.[`singleSubjectSuggestion_${index}`]?.[0]?.offsetHeight || 0;
  927. // console.log(suggestionHeight,8999111)
  928. this.singleSubjectData[index].suggestionPageNum = this.SingleChartPage(this.singleSubjectData[index].suggestionHtml?suggestionHeight:0);
  929. })
  930. } else {
  931. this.singleSubjectData[index].suggestionHtml = ''
  932. }
  933. })
  934. },
  935. //答题卡
  936. async FindStudentCard(subjectCode,index){
  937. await this.$api.reportStudent[getApiName()].findStudentCard({
  938. examId:this.reportParam.examId,
  939. subjectCode:subjectCode,
  940. registrationCode:this.reportParam.registrationCode
  941. }).then(res => {
  942. if (res.code == 200 && res.data) {
  943. let paperImageList = res.data.pageVOS || [];
  944. //先添加总分数据
  945. let totalScore = {
  946. questionName: '总分',
  947. fullScore: res?.data?.fullScore || '',
  948. score: res?.data?.levelName ?? res?.data?.totalScore,
  949. displayType: res.data.displayType, //显示类型 0-分数 1-对错 2-等级
  950. displayName: res.data.displayName, //显示值
  951. correctType: res.data.correctType, //显示对错的时候 0-错 1-半对 2-全对
  952. questionAnswer: '',
  953. answer: '',
  954. samplingPosition: '{"x":195,"y":247,"page":1}'
  955. }
  956. if (paperImageList.length > 0 && paperImageList[0].questionVOS) {
  957. paperImageList[0].questionVOS.unshift(totalScore)
  958. }
  959. this.singleSubjectData[index].paperImageList = paperImageList;
  960. this.singleSubjectData[index].usedCardType = res?.data?.usedCardType ?? 1;
  961. for(let i = 0;i<paperImageList.length;i++){
  962. const pageNum = this.SingleChartPage(this.printPageHeight);
  963. this.singleSubjectData[index].paperImagePageNum.push(pageNum);
  964. }
  965. }
  966. })
  967. },
  968. //处理数据
  969. TableChartData(tableData, titleData, studentOpenness, index,type,groupName) {
  970. //柱状图
  971. let datax = [],datay = [],radarChart = []
  972. tableData.forEach(item => {
  973. datax.push(item.questionName)
  974. const scoreRate = item?.scoreRate ?? ''
  975. datay.push(scoreRate)
  976. radarChart.push([item.questionName, scoreRate])
  977. })
  978. //雷达图
  979. const radarChartData = [['group', '得分率'], ...radarChart]
  980. let chartHeight = 0;//小题分析只显示table 不显示图
  981. if(type=='bigQuestionData'){
  982. chartHeight = datay.length > 0 ? 363 : 0; //柱状图
  983. }else if (type == 'smallQuestionData'){
  984. chartHeight = 0;
  985. } else{
  986. chartHeight = datay.length > 0 ? 393 : 0;//雷达图
  987. }
  988. const chartPagesNum = this.SingleChartPage(chartHeight);
  989. const staticHeader = titleData.slice(0,1);//固定表头
  990. const dynamicHeader = titleData.slice(1);//动态分组标头
  991. const pageTableData = this.TableRowAndColumnPage(dynamicHeader,tableData,7,1);//8列一个表
  992. const tablePagesNum = pageTableData.tablePagesNum;
  993. const tableList = pageTableData.tableList;
  994. const headerList = pageTableData.headerList;//表头
  995. this.singleSubjectData[index].groupQuestionData.push({
  996. type:type,
  997. groupName:groupName,
  998. studentOpenness:studentOpenness,
  999. staticHeader:staticHeader,
  1000. headerList:headerList,
  1001. tableList:tableList,
  1002. tablePagesNum:tablePagesNum,
  1003. chartPagesNum:chartPagesNum,
  1004. datax:datax,
  1005. datay:datay,
  1006. radarChartData:radarChartData
  1007. })
  1008. },
  1009. //按照原始顺序累加,当总和超过A4高度1285时,将当前元素放入下一组
  1010. groupByThreshold(arr, threshold) {
  1011. const result = [];
  1012. let currentGroup = [];
  1013. let currentSum = 0;
  1014. for (let i = 0; i < arr.length; i++) {
  1015. const num = arr[i];
  1016. // 如果当前组为空,直接添加
  1017. if (currentGroup.length === 0) {
  1018. currentGroup.push(num);
  1019. currentSum += num;
  1020. }
  1021. // 如果加上当前元素会超过阈值,则创建新组
  1022. else if (currentSum + num > threshold) {
  1023. result.push(currentGroup);
  1024. currentGroup = [num];
  1025. currentSum = num;
  1026. }
  1027. // 否则添加到当前组
  1028. else {
  1029. currentGroup.push(num);
  1030. currentSum += num;
  1031. }
  1032. }
  1033. // 添加最后一组
  1034. if (currentGroup.length > 0) {
  1035. result.push(currentGroup);
  1036. }
  1037. return result;
  1038. },
  1039. /*
  1040. *对表格横向和竖向分页
  1041. *dynamicHeader 动态表头
  1042. *tableData 表格数据
  1043. *groupSize 动态表头分页大小
  1044. *headNum 表头行数
  1045. */
  1046. TableRowAndColumnPage(dynamicHeader,tableData,groupSize,headNum){
  1047. /*
  1048. * 每个模块的高度
  1049. */
  1050. const tableTitle = 49;//表格标题高度
  1051. const tableHeadHeight = 41;//表头高度
  1052. const tableGap = 49;//表格和图表之间的间距
  1053. //对表格横向分页
  1054. const groupDynamicHeader = [];
  1055. for (let i = 0; i < dynamicHeader.length; i += groupSize) {
  1056. const group = dynamicHeader.slice(i, i + groupSize);
  1057. //表格补充
  1058. if(group.length > 0 && group.length!=groupSize && i > 0){
  1059. const tdLens = groupSize - group.length;
  1060. for(let j = 0; j < tdLens; j ++){
  1061. group.push({})
  1062. }
  1063. }
  1064. groupDynamicHeader.push(group)
  1065. }
  1066. let tablePagesNum = [],tableList = [],headerList = [];//当前模块所有table页码 表格 表格高度
  1067. for (let i = 0; i < groupDynamicHeader.length; i ++) {
  1068. let itemTablePagesNum = [],itemTableList = [],itemHeadder= [], moduleHeightData = [] ,isShowSplitLine = [];//每个table的页码 表格 表格高度 isShowSplitLine:表格是否显示分割线
  1069. //计算最后一页模块的高度
  1070. let lastPageDataSum = 0;
  1071. const lastPageNum = this.modulePageData.length > 0 ? this.modulePageData[this.modulePageData.length - 1] : 1;//最后一页页码
  1072. this.modulePageData.forEach((item,p)=>{
  1073. if(item == lastPageNum){
  1074. lastPageDataSum += this.moduleHeightData[p];
  1075. }
  1076. })
  1077. const remainHeight = this.printPageHeight - lastPageDataSum - (tableHeadHeight * headNum) - tableTitle - 41;//41 是距离底部的边距
  1078. const remainTableRow = Math.floor(remainHeight / 40);//剩余可放多少行
  1079. if(remainTableRow > 1){
  1080. const tableLens = tableData.length ?? 0;//表格行数量
  1081. if(tableLens > remainTableRow){//判断第二页是否有值
  1082. const pageTableHeight = this.printPageHeight - (tableHeadHeight * headNum) - tableTitle - 41;// 一页能放下的table的高度 41 是距离底部的边距
  1083. const tableRowNum = Math.floor(pageTableHeight / 40);//一页可放多少行
  1084. //第一页数据
  1085. const firstTableData = tableData.slice(0,remainTableRow);
  1086. itemTableList.push(firstTableData)
  1087. itemHeadder.push(groupDynamicHeader[i])
  1088. isShowSplitLine.push(false);//是否显示表格底部的分割线 第一页不显示
  1089. //第一页页码
  1090. // this.modulePageData.push(lastPageNum);
  1091. //当前表格第一页页码
  1092. itemTablePagesNum.push(lastPageNum);//图表分页页码
  1093. // 第一页高度
  1094. const tableHeight1 = firstTableData.length > 0 ? (tableHeadHeight * headNum) + tableTitle + tableGap + firstTableData.length * 40 : 0;
  1095. moduleHeightData.push(tableHeight1)
  1096. const otherTableData = tableData.slice(remainTableRow);//接取完上一页剩下的表格数据
  1097. // 按步长遍历,每次截取 表格行数 元素
  1098. for (let j = 0; j < otherTableData.length; j += tableRowNum) {
  1099. const group = otherTableData.slice(j, j + tableRowNum);
  1100. const key = j/tableRowNum;
  1101. //表格数据
  1102. itemTableList.push(group);
  1103. itemHeadder.push(groupDynamicHeader[i])
  1104. isShowSplitLine.push(false);//是否显示表格底部的分割线
  1105. //页码
  1106. // this.modulePageData.push(lastPageNum + key + 1);
  1107. //当前表格分页页码
  1108. itemTablePagesNum.push(lastPageNum + key + 1);
  1109. //高度
  1110. const tableHeight = group.length > 0 ? (tableHeadHeight * headNum) + tableTitle + tableGap + group.length * 40 : 0;
  1111. moduleHeightData.push(tableHeight)
  1112. }
  1113. }else{
  1114. const tableData1 = tableData.slice(0,remainTableRow);
  1115. const tableData2 = tableData.slice(remainTableRow);
  1116. itemTableList.push(tableData1,tableData2);
  1117. itemHeadder.push(groupDynamicHeader[i],groupDynamicHeader[i])
  1118. // this.modulePageData.push(lastPageNum,lastPageNum);
  1119. //页码
  1120. itemTablePagesNum.push(lastPageNum,lastPageNum)
  1121. //高度
  1122. const tableHeight1 = tableData1.length > 0 ? (tableHeadHeight * headNum) + tableTitle + tableGap + tableData1.length * 40 : 0;
  1123. const tableHeight2 = tableData2.length > 0 ? (tableHeadHeight * headNum) + tableTitle + tableGap + tableData2.length * 40 : 0;
  1124. moduleHeightData.push(tableHeight1,tableHeight2)
  1125. }
  1126. }else{
  1127. const pageTableHeight = this.printPageHeight - (tableHeadHeight * headNum) - tableTitle - 41;// 一页能放下的table的高度 41 是距离底部的边距
  1128. const tableRowNum = Math.floor(pageTableHeight / 40);//一页可放多少行
  1129. // 按步长遍历,每次截取 表格行数 元素
  1130. for (let j = 0; j < tableData.length; j += tableRowNum) {
  1131. const group = tableData.slice(j, j + tableRowNum);
  1132. const key = j/tableRowNum;
  1133. //表格数据
  1134. itemTableList.push(group);
  1135. itemHeadder.push(groupDynamicHeader[i])
  1136. // this.modulePageData.push(lastPageNum + key + 1);
  1137. //页码
  1138. itemTablePagesNum.push(lastPageNum + key + 1)
  1139. //高度
  1140. const tableHeight = group.length > 0 ? (tableHeadHeight * headNum) + tableTitle + tableGap + group.length * 40 : 0;
  1141. moduleHeightData.push(tableHeight)
  1142. }
  1143. }
  1144. this.modulePageData.push(...itemTablePagesNum);
  1145. this.moduleHeightData.push(...moduleHeightData);
  1146. // console.log(this.modulePageData,111333)
  1147. tableList.push(itemTableList)
  1148. headerList.push(itemHeadder)
  1149. tablePagesNum.push(itemTablePagesNum);//当前模块表格的分页页码
  1150. }
  1151. return {headerList,tablePagesNum,tableList}
  1152. },
  1153. /*
  1154. *单个图分页
  1155. *chartHeight 图表高度
  1156. */
  1157. SingleChartPage(chartHeight){
  1158. let chartPagesNum = '';//各分析图 高度
  1159. const prevModuleLastPageNum = this.modulePageData.length > 0 ? this.modulePageData[this.modulePageData.length - 1] : 1;//上一模块 最后一页页码
  1160. //上一模块最后一页高度 和 当前模块 echart高度
  1161. let prevModuleLastPageHeight = [],moduleChartHeight = [];
  1162. this.modulePageData.forEach((item,i)=>{
  1163. if(item == prevModuleLastPageNum){
  1164. prevModuleLastPageHeight.push(this.moduleHeightData[i])
  1165. moduleChartHeight.push(this.moduleHeightData[i]);//最后一页高度
  1166. }
  1167. })
  1168. // 将当前模块 echart高度
  1169. this.moduleHeightData.push(chartHeight)
  1170. moduleChartHeight.push(chartHeight)
  1171. //进行分页 满足一页的高度放在一起
  1172. const printPageGroup = this.groupByThreshold([...moduleChartHeight], this.printPageHeight);
  1173. //每个模块对应的页码
  1174. for (let i = 0; i < printPageGroup.length; i++) {
  1175. const arr = printPageGroup[i]
  1176. for (let j = 0; j < arr.length; j++) {
  1177. if(i == 0){//第一页
  1178. if(j > prevModuleLastPageHeight.length - 1){
  1179. this.modulePageData.push(prevModuleLastPageNum)
  1180. chartPagesNum = prevModuleLastPageNum
  1181. }
  1182. }else{
  1183. this.modulePageData.push(prevModuleLastPageNum + i);
  1184. chartPagesNum = prevModuleLastPageNum + i
  1185. }
  1186. }
  1187. }
  1188. return chartPagesNum
  1189. },
  1190. GetDifficultyClass(val) {
  1191. if (val == 1) {
  1192. return 'difficulty easy'
  1193. } else if (val == 2) {
  1194. return 'difficulty relatively_easy'
  1195. } else if (val == 3) {
  1196. return 'difficulty general'
  1197. } else if (val == 4) {
  1198. return 'difficulty more_difficult'
  1199. } else if (val == 5) {
  1200. return 'difficulty difficult'
  1201. } else {
  1202. return ''
  1203. }
  1204. },
  1205. GetDifficultyName(val) {
  1206. if (val == 1) {
  1207. return '容易'
  1208. } else if (val == 2) {
  1209. return '较易'
  1210. } else if (val == 3) {
  1211. return '一般'
  1212. } else if (val == 4) {
  1213. return '较难'
  1214. } else if (val == 5) {
  1215. return '困难'
  1216. } else {
  1217. return '-'
  1218. }
  1219. },
  1220. //点击顶部下载PDF按钮导出
  1221. DownloadPdf(){
  1222. if(this.$refs.bookFlipBox){
  1223. this.$refs.bookFlipBox.DownloadPdfNew();
  1224. }
  1225. },
  1226. //向父级页面传值关闭下载Pdf按钮loading
  1227. PdfLoadEnd(){
  1228. this.$emit('closePdfLoading')
  1229. },
  1230. }
  1231. };
  1232. </script>
  1233. <style scoped lang="scss">
  1234. .area_module_describe{
  1235. margin-top: 20px;
  1236. }
  1237. .card-container {
  1238. display: flex;
  1239. flex-wrap: wrap;
  1240. /* 允许换行 */
  1241. /* 设置元素之间间隔 */
  1242. gap: 10px;
  1243. .card {
  1244. // flex: 0 1 calc((100% - 240px) / 5);
  1245. flex-grow: 1; /* 使每个div平分可用空间 */
  1246. flex-basis: 0; /* 初始基础大小为0 */
  1247. width: 20%;
  1248. // max-width: 320px;
  1249. // width: 238px;
  1250. /* 每个卡片占据 18% 宽度,确保能在一行显示五个,考虑间隔 */
  1251. // flex: 0 0 16.5%; /* 每个卡片占据 18% 宽度,确保能在一行显示五个,考虑间隔 */
  1252. // border: 2px dashed #ccc;
  1253. border-radius: 10px;
  1254. padding: 12px 6px;
  1255. box-sizing: border-box;
  1256. text-align: center;
  1257. color: #fff;
  1258. /* 文字颜色可以根据背景调整 */
  1259. background-size: cover;
  1260. background-position: center;
  1261. height: 70px;
  1262. /* 可调整高度 */
  1263. // margin-bottom: 20px; /* 卡片底部间距 */
  1264. position: relative;
  1265. }
  1266. .background-image {
  1267. position: absolute;
  1268. top: 0;
  1269. right: 0;
  1270. /* 背景图片宽度 */
  1271. width: 100%;
  1272. height: 70px;
  1273. background-size: contain;
  1274. background-repeat: no-repeat;
  1275. background-position: center right;
  1276. z-index: 1;
  1277. /* 确保背景图片在文本之下 */
  1278. border-radius: 10px;
  1279. }
  1280. .statistic,.value {
  1281. position: relative;
  1282. z-index: 2;
  1283. /* 确保文本在背景图片之上 */
  1284. }
  1285. .statistic {
  1286. font-size: 13px;
  1287. font-weight: 400;
  1288. line-height: 22px;
  1289. text-align: left;
  1290. z-index: 2;
  1291. }
  1292. .value {
  1293. font-size: 16px;
  1294. font-weight: 600;
  1295. line-height: 20px;
  1296. text-align: left;
  1297. margin-top: 5px;
  1298. z-index: 2;
  1299. }
  1300. }
  1301. .area_module{
  1302. .area_module_content{
  1303. display: flex;
  1304. width: 100%;
  1305. justify-content: space-between;
  1306. .area_module_chart{
  1307. width: 35% !important;
  1308. }
  1309. .area_module_table{
  1310. width: 65% !important;
  1311. }
  1312. }
  1313. .area_module_chart{
  1314. &.justify_content{
  1315. display: flex;
  1316. gap: 0px 48px;
  1317. flex-wrap: wrap;
  1318. .item_progress{
  1319. width: 170px;
  1320. height: 180px;
  1321. display: inline-flex;
  1322. align-items: center;
  1323. position: relative;
  1324. :deep(.el-progress--circle) {
  1325. .el-progress__text{
  1326. font-size: 14px !important;
  1327. color: #5470C6 !important;
  1328. background: rgba(84,112,198,0.1);
  1329. width: 120px;
  1330. height: 120px;
  1331. border-radius: 50%;
  1332. position: absolute;
  1333. left: 50%;
  1334. top: 50%;
  1335. transform: translate(-50%, -50%);
  1336. display: flex;
  1337. align-items: center;
  1338. justify-content: center;
  1339. padding-top: 30px;
  1340. box-sizing: border-box;
  1341. }
  1342. }
  1343. .item_progress_name{
  1344. position: absolute;
  1345. left: 50%;
  1346. top: 37%;
  1347. transform: translate(-50%,0);
  1348. font-weight: 500;
  1349. font-size: 16px !important;
  1350. color: #5470C6 !important;
  1351. }
  1352. }
  1353. }
  1354. }
  1355. .area_module_table{
  1356. &.error{
  1357. :deep() .el-table{
  1358. .el-table__header-wrapper{
  1359. .el-table__header{
  1360. .is-group{
  1361. tr{
  1362. th.el-table__cell:nth-last-child(3){
  1363. border-right: 1px solid #EBEEF5;
  1364. }
  1365. &:nth-child(2){
  1366. display:none;
  1367. }
  1368. }
  1369. }
  1370. }
  1371. }
  1372. .el-table__cell{
  1373. &.white_space_normal{
  1374. .cell{
  1375. white-space: normal;
  1376. padding:10px 0 10px 10px !important;
  1377. }
  1378. }
  1379. }
  1380. // &.el-table--striped {
  1381. // .el-table__body {
  1382. // tr{
  1383. // &.el-table__row--striped{
  1384. // &.row_color_FFFFFF {
  1385. // td.el-table__cell{
  1386. // background: #FFFFFF;
  1387. // }
  1388. // }
  1389. // }
  1390. // }
  1391. // }
  1392. // }
  1393. // &.el-table--striped .el-table__body tr.el-table__row.row_color_FAFAFA td.el-table__cell{
  1394. // background: #FAFAFA;
  1395. // }
  1396. // &.el-table--striped .el-table__body tr.el-table__row--striped.row_color_FAFAFA td.el-table__cell{
  1397. // background: #FAFAFA;
  1398. // }
  1399. // &.el-table--enable-row-hover .el-table__body tr.row_color_FFFFFF:hover > td {
  1400. // background-color: transparent !important;
  1401. // }
  1402. }
  1403. }
  1404. }
  1405. .difficulty {
  1406. width: 6px;
  1407. height: 6px;
  1408. display: inline-flex;
  1409. border-radius: 50%;
  1410. margin-right: 4px;
  1411. &.easy {
  1412. background: #3ba272;
  1413. }
  1414. &.relatively_easy {
  1415. background: #fac858;
  1416. }
  1417. &.general {
  1418. background: #5470c6;
  1419. }
  1420. &.more_difficult {
  1421. background: #ea7acb;
  1422. }
  1423. &.difficult {
  1424. background: #ee6666;
  1425. }
  1426. }
  1427. }
  1428. </style>