| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782 |
- <template>
- <ReportModule
- :showTitle="true"
- :titleList="[state.groupTitle]"
- :showDescribe="true"
- tableOrChart="chart"
- :showPrintBtn="false"
- :showExportBtn="false"
- >
- <template #title_right>
- <EchartType
- :chartTypeList="state.problemAnalysisData.chartTypeList"
- :current="state.problemAnalysisData.chartType"
- @ChangeEchartType="
- (val: string) => ChangeEchartType(val, 'problemAnalysisData')
- "
- />
- </template>
- <template #module_table_chart>
- <template v-if="state.problemAnalysisData.data.length > 0">
- <BarLineCharts
- v-if="state.problemAnalysisData.chartType == 'line_bar_chart'"
- :legendList="state.problemAnalysisData.legendList"
- :showBarLegendIndex="state.problemAnalysisData.showBarLegendIndex"
- title="得分率"
- :data="state.problemAnalysisData.data"
- @HandleChartClick="
- (index: any, name: string) => HandleChartClick(index, name)
- "
- @ChangeChartOrder="
- (sortType: string, legendData: any, barIndex: any) =>
- ChangeChartOrder(sortType, legendData, barIndex, 1)
- "
- >
- </BarLineCharts>
- <BarsCharts
- v-if="state.problemAnalysisData.chartType == 'vertical_bar'"
- :key="state.chartKey"
- :data="state.problemAnalysisData.data"
- :legendList="state.problemAnalysisData.legendList"
- :showSortSelectbox="true"
- unit="%"
- title="得分率"
- :isClick="true"
- @HandleChartClick="
- (index: any, name: string) => HandleChartClick(index, name)
- "
- @ChangeChartOrder="
- (sortType: string, legendData: any, barIndex: any) =>
- ChangeChartOrder(sortType, legendData, barIndex, 1)
- "
- >
- </BarsCharts>
- <RadarCharts
- v-if="state.problemAnalysisData.chartType == 'radar_chart'"
- :key="state.chartKey"
- :data="state.problemAnalysisData.data"
- :legendList="state.problemAnalysisData.legendList"
- :showCheckBox="true"
- :openShowAllLegend="true"
- :isClick="true"
- @HandleChartClick="
- (index: any, name: string) => HandleChartClick(index, name)
- "
- >
- </RadarCharts>
- </template>
- <div
- v-else
- class="no_content_data"
- v-loading="state.dataLoading"
- :element-loading-text="state.loadingText"
- :element-loading-spinner="loadingSvgIcon"
- element-loading-background="#ffffff"
- >
- <span>暂无数据</span>
- </div>
- </template>
- <template #module_describe>
- 展示每道试题的得分率图。得分率指实际得分/考核分的比值,换算成的百分数。可以用于分析每道试题的难易程度和质量,试题得分率高意味着试题难度低或者学生整体水平高;得分率低意味着试题难度较高或者考生整体水平较低。点击每道试题的柱或雷达图的题号可在下方查看该题每个班的得分率情况。
- </template>
- </ReportModule>
- <ReportModule
- :showTitle="true"
- :titleList="[state.groupTitle, state.groupName]"
- :showDescribe="true"
- tableOrChart="chart"
- :showPrintBtn="false"
- :showExportBtn="false"
- >
- <template #title_right>
- <EchartType
- :chartTypeList="state.majorQuestionData.chartTypeList"
- :current="state.majorQuestionData.chartType"
- @ChangeEchartType="
- (val: string) => ChangeEchartType(val, 'majorQuestionData')
- "
- />
- </template>
- <template #module_table_chart>
- <template v-if="state.majorQuestionData.data.length > 0">
- <BarLineCharts
- ref="majorQuestionCharts"
- v-if="state.majorQuestionData.chartType == 'line_bar_chart'"
- :legendList="state.majorQuestionData.legendList"
- :showBarLegendIndex="state.majorQuestionData.showBarLegendIndex"
- title="得分率"
- :data="state.majorQuestionData.data"
- @HandleChartClick="
- (index: any, name: string) => HandleQuestionChartClick(index, name)
- "
- @ChangeChartOrder="
- (sortType: string, legendData: any, barIndex: any) =>
- ChangeChartOrder(sortType, legendData, barIndex, 2)
- "
- >
- </BarLineCharts>
- <BarsCharts
- ref="majorQuestionCharts"
- :key="state.chartKey"
- v-if="state.majorQuestionData.chartType == 'vertical_bar'"
- :data="state.majorQuestionData.data"
- :showSortSelectbox="true"
- :legendList="state.majorQuestionData.legendList"
- unit="%"
- title="得分率"
- :isClick="true"
- @HandleChartClick="
- (index: any, name: string) => HandleQuestionChartClick(index, name)
- "
- @ChangeChartOrder="
- (sortType: string, legendData: any, barIndex: any) =>
- ChangeChartOrder(sortType, legendData, barIndex, 2)
- "
- ></BarsCharts>
- <RadarCharts
- v-if="state.majorQuestionData.chartType == 'radar_chart'"
- :key="state.chartKey"
- :data="state.majorQuestionData.data"
- :legendList="state.majorQuestionData.legendList"
- :showCheckBox="true"
- :openShowAllLegend="true"
- :isClick="true"
- @HandleChartClick="
- (index: any, name: string) => HandleQuestionChartClick(index, name)
- "
- >
- </RadarCharts>
- </template>
- <div
- v-else
- class="no_content_data"
- v-loading="state.dataLoading"
- :element-loading-text="state.loadingText"
- :element-loading-spinner="loadingSvgIcon"
- element-loading-background="#ffffff"
- >
- <span>暂无数据</span>
- </div>
- </template>
- <template #module_describe>
- 展示每道试题的得分率图。得分率指实际得分/考核分的比值,换算成的百分数。可以用于分析每道试题的难易程度和质量,试题得分率高意味着试题难度低或者学生整体水平高;得分率低意味着试题难度较高或者考生整体水平较低。点击每道试题的柱或雷达图的题号可在下方查看该题每个班的得分率情况。
- </template>
- </ReportModule>
- <ReportModule
- :showTitle="true"
- :titleList="[state.groupTitle, state.questionTitle]"
- :showDescribe="true"
- tableOrChart="chart"
- :showPrintBtn="false"
- :showExportBtn="false"
- >
- <template #title_right>
- <EchartType
- :chartTypeList="state.questionScoreStatsData.chartTypeList"
- :current="state.questionScoreStatsData.chartType"
- @ChangeEchartType="
- (val: string) => ChangeEchartType(val, 'questionScoreStatsData')
- "
- />
- </template>
- <template #module_table_chart>
- <template v-if="state.questionScoreStatsData.datax.length > 0">
- <BarScoringRateVertical
- v-if="state.questionScoreStatsData.chartType == 'vertical_bar'"
- :datax="state.questionScoreStatsData.datax"
- :datay="state.questionScoreStatsData.dataStackY"
- :tooltipData="state.questionScoreStatsData.tooltipData"
- :isShowMarkLine="true"
- :average="state.questionScoreStatsData.rate"
- :markLineData="state.questionScoreStatsData.markLineData"
- :color="['#3BA272', '#EE6666']"
- typeName="得分率"
- :isClick="true"
- @HandleChartClick="
- (index: number) => HandleQuestionScoreChartClick(index)
- "
- ></BarScoringRateVertical>
- <DifferenceChart
- v-if="state.questionScoreStatsData.chartType == 'difference_chart'"
- :datax="state.questionScoreStatsData.datax"
- :datay="state.questionScoreStatsData.datay"
- unit="%"
- type="1"
- title="得分率"
- :rate="state.questionScoreStatsData.rate"
- @HandleChartClick="
- (index: number) => HandleQuestionScoreChartClick(index)
- "
- >
- </DifferenceChart>
- </template>
- <div
- v-else
- class="no_content_data"
- v-loading="state.dataLoading"
- :element-loading-text="state.loadingText"
- :element-loading-spinner="loadingSvgIcon"
- element-loading-background="#ffffff"
- >
- <span>暂无数据</span>
- </div>
- </template>
- <template #module_describe>
- 说明:通过上面图形,可查看该题每个班的得分率情况,由图中可以看出,得分率最高为<span
- style="color: #3ba272"
- >{{ state.questionScoreStatsData.maxClass }}</span
- >,最低为<span style="color: #ee6666">{{
- state.questionScoreStatsData.minClass
- }}</span
- >。点击每个班级的柱可在下方查看该班各个选项/得分的人数分布。
- </template>
- </ReportModule>
- <ReportModule
- :showTitle="true"
- :titleList="[state.groupTitle, state.questionTitle, state.classTitle]"
- :showDescribe="true"
- tableOrChart="qita"
- :showPrintBtn="false"
- :showExportBtn="false"
- >
- <template #module_qita>
- <div class="content_left answer">
- <BarChart
- v-if="state.questionAnswerData.datax.length"
- :datax="state.questionAnswerData.datax"
- :datay="state.questionAnswerData.datay"
- typeName="人数"
- :showNuitY="false"
- unit="人"
- :unitX="
- state.questionAnswerData.questionType == '单选题' ||
- state.questionAnswerData.questionType == '多选题' ||
- state.questionAnswerData.questionType == '判断题'
- ? ''
- : '分'
- "
- :showMarkPoint="false"
- :isShowMarkLine="false"
- :color="state.questionAnswerData.color"
- :answerValue="state.questionAnswerData.answerValue"
- :answerScore="state.questionAnswerData.answerScore"
- :fullMark="state.questionAnswerData.fullMark"
- :isClick="true"
- @HandleChartClick="
- (index: number, name: string) =>
- HandleQuestionAnswerChartClick(index, name)
- "
- style="height: 300px"
- ></BarChart>
- <div
- v-else
- class="module_chart no_content_data"
- v-loading="state.dataLoading"
- :element-loading-text="state.loadingText"
- :element-loading-spinner="loadingSvgIcon"
- element-loading-background="#ffffff"
- >
- <span>暂无数据</span>
- </div>
- </div>
- <div class="content_right answer table_42">
- <el-table
- border
- :data="state.questionAnswerData.tableData"
- stripe
- align="left"
- :header-row-style="HeaderRowStyle"
- >
- <el-table-column :label="state.classTitle" align="center">
- <el-table-column
- prop="title"
- align="center"
- label="名称"
- ></el-table-column>
- <el-table-column
- prop="value"
- align="center"
- label="数值"
- ></el-table-column>
- </el-table-column>
- </el-table>
- </div>
- </template>
- <template #module_describe>
- 说明:通过柱图,可查看该题下该班所有学生的选项或试题得分情况。点击每个柱可查看该选项或分数的学生明细和答题卡答题情况。
- </template>
- </ReportModule>
- <ReportModule
- :showTitle="true"
- :titleList="[
- state.groupTitle,
- state.questionTitle,
- state.classTitle,
- state.optionTitle,
- ]"
- :showDescribe="true"
- tableOrChart="qita"
- :showPrintBtn="false"
- :showExportBtn="false"
- >
- <template #title_right>
- <el-button
- class="default_button"
- v-if="
- state.questionAnswerData.questionType != '单选题' &&
- state.questionAnswerData.questionType != '多选题' &&
- state.questionAnswerData.questionType != '判断题'
- "
- @click="VisibleQuestionCard"
- >
- <img src="@/assets/icon/card_view.webp" />批量查看
- </el-button>
- </template>
- <template #module_qita>
- <div class="content_left paper_card">
- <StudentQuestionImg :paperInfo="state.paperInfos"></StudentQuestionImg>
- </div>
- <div class="content_right paper_card table_42">
- <el-table
- border
- :data="state.majorAnswerData.tableData"
- stripe
- highlight-current-row
- align="left"
- height="401px"
- row-key="studentRegistrationCode"
- :row-style="{ cursor: 'pointer' }"
- :row-class-name="TableRowClassName"
- @row-click="HandleRowClick"
- >
- <el-table-column
- prop="studentUserName"
- align="center"
- label="学生"
- show-overflow-tooltip
- ></el-table-column>
- <el-table-column
- label="班级"
- prop="className"
- align="center"
- min-width="70"
- show-overflow-tooltip
- ></el-table-column>
- <el-table-column
- prop="questionScore"
- align="center"
- label="得分"
- width="70"
- show-overflow-tooltip
- ></el-table-column>
- <el-table-column
- prop="paperScore"
- align="center"
- label="成绩"
- width="70"
- show-overflow-tooltip
- ></el-table-column>
- <el-table-column align="center" label="操作">
- <template #default="scope">
- <el-button text @click.stop="handleClick(scope.row as any)"
- >查看答题卡</el-button
- >
- </template>
- </el-table-column>
- </el-table>
- </div>
- </template>
- <template #module_describe>
- 说明:点击左侧表格列可切换学生查看具体学生答题图片,点击学生姓名可在下方查看学生均衡分析,点击学生成绩可查看学生答题卡原卷。
- </template>
- </ReportModule>
- <ReportModule
- ref="reportModuleRef"
- :showTitle="true"
- :titleList="[state.groupTitle]"
- :showDescribe="true"
- tableOrChart="table"
- :showPrintBtn="false"
- :showExportBtn="true"
- :currentPage="state.majorTableData.currentPage"
- :pageSize="state.majorTableData.pageSize"
- :total="state.majorTableData.total"
- @ChangePageSize="ChangePageSize"
- @ChangeCurrentPage="ChangeCurrentPage"
- @ExportExcel="ExportExcel"
- >
- <template #title_right>
- <SetTableHeader
- :data="{
- static: state.majorTableData.headerData,
- dynamisc: state.majorTableData.changeHeaderData,
- child: state.majorTableData.childHeaderData,
- }"
- :isShowDynamisc="false"
- :notEditable="['questionName']"
- @SetEnterHeaderData="SetEnterHeaderData"
- ></SetTableHeader>
- </template>
- <template #module_table_chart>
- <el-table
- :data="state.majorTableData.tableData"
- ref="majorTable"
- border
- stripe
- align="left"
- :key="state.majorTableData.tableKey"
- >
- <template v-for="item in state.majorTableData.headerData">
- <el-table-column
- v-if="item.display"
- :key="item.prop"
- align="center"
- :prop="item.prop"
- :min-width="item.label.length > 4 ? 110 : 90"
- :label="item.label"
- fixed="left"
- show-overflow-tooltip
- >
- <template #default="scope">
- {{ scope.row[item.prop] || "-"
- }}{{
- item.prop == "estimatedScoreRate" && scope.row[item.prop]
- ? "%"
- : ""
- }}
- </template>
- </el-table-column>
- </template>
- <template v-for="parent in state.majorTableData.changeHeaderData">
- <el-table-column
- v-if="parent.display"
- align="center"
- :prop="parent.prop"
- :label="parent.label"
- :key="parent.prop"
- >
- <template v-for="item in state.majorTableData.childHeaderData">
- <el-table-column
- v-if="item.display"
- :prop="`${parent.prop}_${item.prop}`"
- :key="`${parent.prop}_${item.prop}`"
- align="center"
- :label="item.label"
- :min-width="item.label.length > 4 ? 100 : 80"
- show-overflow-tooltip
- >
- <template #default="scope">
- <span v-if="item.prop.indexOf('Rate') > -1">{{
- scope.row[`${parent.prop}_${item.prop}`]
- ? `${scope.row[`${parent.prop}_${item.prop}`]}%`
- : "-"
- }}</span>
- <span
- v-else
- @click="OpenStudentDialog(item, parent, scope.row)"
- :class="{
- table_row_blue:
- (item.prop.indexOf('Count') > -1 ||
- item.prop.indexOf('Number') > -1) &&
- scope.row?.[`${parent.prop}_${item.prop}`] > 0,
- }"
- >{{
- scope.row?.[`${parent.prop}_${item.prop}`] ?? "-"
- }}</span
- >
- </template>
- </el-table-column>
- </template>
- </el-table-column>
- </template>
- </el-table>
- </template>
- </ReportModule>
- <!-- 批量查看小题答题卡 -->
- <QuestionCard
- :subjectId="analysisStore.filterObject.subjectId"
- :questionId="state.cardQuestionId"
- :platformNumbers="state.cardRegistrationCodeList"
- :groupTitle="state.groupTitle"
- :groupName="state.groupName"
- :questionTitle="state.questionTitle"
- :classTitle="state.classTitle"
- :optionTitle="state.optionTitle"
- :showDialog="state.showQuestionCardDialog"
- @CloseDialog="CloseQuestionCardDialog"
- ></QuestionCard>
- <!-- 学生答题卡组件 -->
- <StudentPaper
- :modelValue="state.showStudentPaperDialog"
- :paperInfo="state.paperInfo"
- :pageTitle="state.paperTitle"
- @updateModelValue="UpdateModelValue"
- ></StudentPaper>
- <StudentList
- :showDialog.sync="state.dialogData.showDialog"
- :title="state.dialogData.title"
- :tableTitle="state.dialogData.tableTitle"
- :apiName="state.dialogData.apiName"
- :studentParam="{
- fiveRateName: state.dialogData.fiveRateName,
- selectSubjectName: state.dialogData.selectSubjectName,
- selectSchoolLevel: state.dialogData.selectSchoolLevel,
- selectSchoolName: state.dialogData.selectSchoolName,
- selectClassLevel: state.dialogData.selectClassLevel,
- selectClassName: state.dialogData.selectClassName,
- questionId: state.dialogData.questionId,
- isPaper: state.dialogData.isPaper,
- quesScoreType: state.dialogData.quesScoreType,
- knowledgeId: state.dialogData.knowledgeId,
- questionGroupName: state.dialogData.questionGroupName,
- groupTitle: state.dialogData.groupTitle,
- }"
- @CloseDialog="CloseDialog"
- >
- </StudentList>
- </template>
- <script lang="ts" setup>
- import ReportModule from "@/components/ReportModule.vue";
- import EchartType from "@/components/EchartType.vue";
- import QuestionCard from "@/components/QuestionCard.vue";
- import StudentPaper from "@/components/StudentPaper.vue";
- import { useAnalysisStore } from "@/store/analysis";
- import {
- questionGroupAnalysis,
- queryAnswerListByAnswerAndScore,
- publicExport,
- } from "@/api/analysis";
- import BarLineCharts from "@/components/echarts/barLineCharts.vue";
- import RadarCharts from "@/components/echarts/radarCharts.vue";
- import BarsCharts from "@/components/echarts/barsCharts.vue";
- import BarScoringRateVertical from "@/components/echarts/barScoringRate_vertical.vue";
- import DifferenceChart from "@/components/echarts/differenceChart.vue";
- import BarChart from "@/components/echarts/barChart_answer.vue";
- import StudentQuestionImg from "@/components/StudentQuestionImg.vue";
- import SetTableHeader from "@/components/SetTableHeader.vue";
- import StudentList from "@/components/StudentList.vue";
- import { downloadExcel, GetExcelFileName } from "@/utils/exportExcel";
- import { loadingSvgIcon } from "@/utils/common";
- import { onMounted, reactive, watch, ref, computed, nextTick } from "vue";
- import { cloneDeep } from "lodash-es";
- // ================= TS 类型定义 =================
- interface ChartTypeItem {
- label: string;
- value: string;
- }
- interface HeaderItem {
- prop: string;
- label: string;
- display?: boolean;
- type?: number;
- }
- interface AnswerItem {
- name: string;
- studentNum: number;
- score: number;
- registrationCodeList?: string[];
- }
- interface QuestionStats {
- scoreRate: number;
- lossRate: number;
- averageScore: number;
- maxScore: number;
- minScore: number;
- answerList: AnswerItem[];
- headDataBOList?: Array<{ name: string; rate: number; studentNumber: number }>;
- [key: string]: any;
- }
- interface ClassItem {
- groupName: string;
- groupId: string | number;
- questionStats: QuestionStats;
- [key: string]: any;
- }
- interface QuestionItem {
- questionName: string;
- questionId: string | number;
- showCode?: number;
- answerValue: string;
- questionType: string;
- fullMark: string | number;
- classList: ClassItem[];
- knowledgeId?: string | number;
- groupName?: string;
- }
- interface GroupItem {
- groupName: string;
- groupCode: number;
- groupId: string | number;
- questionList: QuestionItem[];
- classList: ClassItem[];
- questionId?: string | number;
- knowledgeId?: string | number;
- [key: string]: any;
- }
- interface MarkLineDataItem {
- legendName: string;
- value: number;
- isShow: boolean;
- }
- interface ApiResponse {
- code: number;
- data?: {
- groupList: GroupItem[];
- headerList: HeaderItem[];
- changeHeaderList: HeaderItem[];
- childHeaderList: HeaderItem[];
- };
- }
- interface ExportParams {
- fileName: string;
- examName: string;
- sheetName: string;
- staticHeaderData: HeaderItem[];
- childHeaderData: HeaderItem[];
- dynamicsHeaderData: HeaderItem[];
- dataList: any[][];
- }
- interface State {
- groupTitle: string;
- groupName: string;
- questionTitle: string;
- classTitle: string;
- optionTitle: string;
- questionTypesData: {
- chartKey: number;
- refresh: boolean;
- data: any[];
- tableData: any[];
- };
- problemAnalysisData: {
- chartType: string;
- chartTypeList: ChartTypeItem[];
- legendList: string[];
- defaultLegendList: string[];
- showBarLegendIndex: number;
- questionList: QuestionItem[];
- questionTableList: any[];
- groupList: GroupItem[];
- groupTableList: GroupItem[];
- headerList: HeaderItem[];
- changeHeaderList: HeaderItem[];
- childHeaderList: HeaderItem[];
- questionListIndex: number;
- data: any[];
- };
- majorQuestionData: {
- chartType: string;
- chartTypeList: ChartTypeItem[];
- legendList: string[];
- defaultLegendList: string[];
- showBarLegendIndex: number;
- questionListIndex: number;
- data: any[];
- };
- questionScoreStatsData: {
- checked: boolean;
- isIndeterminate: boolean;
- markLineData: MarkLineDataItem[];
- chartTypeList: ChartTypeItem[];
- chartType: string;
- datax: string[];
- datay: number[];
- dataStackY: any[];
- tooltipData: any[];
- rate: number;
- maxClass: string;
- minClass: string;
- };
- questionAnswerData: {
- datax: string[];
- datay: number[];
- color: string;
- answerValue: string;
- answerScore: number[];
- questionType: string;
- fullMark: string | number;
- tableData: any[];
- classListIndex: number;
- };
- majorAnswerData: { paperUrl: string; tableData: any[]; rowIndex: number };
- majorStudentData: {
- tableData: any[];
- legendList: any[];
- radarChartData: any[];
- excellentCourseList: string;
- inferiorCourseList: string;
- };
- majorTableData: {
- tableKey: number;
- tableData: any[];
- allTableData: any[];
- headerData: HeaderItem[];
- changeHeaderData: HeaderItem[];
- childHeaderData: HeaderItem[];
- pageSize: number;
- total: number;
- currentPage: number;
- };
- chartKey: number;
- dataLoading: boolean;
- loadingText: string;
- paperInfo: {
- examPaperId: string | number;
- platformNumber: string;
- questionId: string | number;
- };
- paperTitle: string;
- showStudentPaperDialog: boolean;
- paperInfos: {
- examPaperId: string | number;
- platformNumber: string;
- questionId: string | number;
- };
- dialogData: {
- apiName: string;
- showDialog: boolean;
- title: string;
- tableTitle: string;
- fiveRateName: string;
- selectSubjectName: string;
- selectSchoolLevel: string | number;
- selectSchoolName: string;
- selectClassLevel: string | number;
- selectClassName: string;
- questionId: string | number;
- isPaper: string | number;
- quesScoreType: string | number;
- knowledgeId: string | number;
- questionGroupName: string;
- groupTitle: string;
- };
- showQuestionCardDialog: boolean;
- cardQuestionId: string | number;
- cardRegistrationCodeList: string[];
- }
- // =============================================
- const analysisStore = useAnalysisStore();
- const reportModuleRef = ref<InstanceType<typeof ReportModule> | null>(null);
- const getExamName = computed(
- () => analysisStore.analysisExamInfo?.examName || "",
- );
- const state = reactive<State>({
- groupTitle: "分组分析",
- groupName: "",
- questionTitle: "",
- classTitle: "",
- optionTitle: "",
- questionTypesData: { chartKey: 0, refresh: false, data: [], tableData: [] },
- problemAnalysisData: {
- chartType: "line_bar_chart",
- chartTypeList: [
- { label: "组合图", value: "line_bar_chart" },
- { label: "柱状图", value: "vertical_bar" },
- { label: "雷达图", value: "radar_chart" },
- ],
- legendList: [],
- defaultLegendList: [],
- showBarLegendIndex: 1,
- questionList: [],
- questionTableList: [],
- groupList: [],
- groupTableList: [],
- headerList: [],
- changeHeaderList: [],
- childHeaderList: [],
- questionListIndex: 0,
- data: [],
- },
- majorQuestionData: {
- chartType: "line_bar_chart",
- chartTypeList: [
- { label: "组合图", value: "line_bar_chart" },
- { label: "柱状图", value: "vertical_bar" },
- { label: "雷达图", value: "radar_chart" },
- ],
- legendList: [],
- defaultLegendList: [],
- showBarLegendIndex: 1,
- questionListIndex: 0,
- data: [],
- },
- questionScoreStatsData: {
- checked: false,
- isIndeterminate: true,
- markLineData: [],
- chartTypeList: [
- { label: "柱状图", value: "vertical_bar" },
- { label: "率差图", value: "difference_chart" },
- ],
- chartType: "vertical_bar",
- datax: [],
- datay: [],
- dataStackY: [],
- tooltipData: [],
- rate: 60,
- maxClass: "",
- minClass: "",
- },
- questionAnswerData: {
- datax: [],
- datay: [],
- color: "#5470C6",
- answerValue: "",
- answerScore: [],
- questionType: "",
- fullMark: "",
- tableData: [],
- classListIndex: 0,
- },
- majorAnswerData: { paperUrl: "", tableData: [], rowIndex: 0 },
- majorStudentData: {
- tableData: [],
- legendList: [],
- radarChartData: [],
- excellentCourseList: "",
- inferiorCourseList: "",
- },
- majorTableData: {
- tableKey: 0,
- tableData: [],
- allTableData: [],
- headerData: [],
- changeHeaderData: [],
- childHeaderData: [],
- pageSize: 10,
- total: 0,
- currentPage: 1,
- },
- chartKey: 0,
- dataLoading: false,
- loadingText: "加载中,请稍后...",
- paperInfo: { examPaperId: "", platformNumber: "", questionId: "" },
- paperTitle: "",
- showStudentPaperDialog: false,
- paperInfos: { examPaperId: "", platformNumber: "", questionId: "" },
- dialogData: {
- apiName: "questionGroupStudentInfo",
- showDialog: false,
- title: "",
- tableTitle: "",
- fiveRateName: "",
- selectSubjectName: "",
- selectSchoolLevel: "",
- selectSchoolName: "",
- selectClassLevel: "",
- selectClassName: "",
- questionId: "",
- isPaper: "",
- quesScoreType: "",
- knowledgeId: "",
- questionGroupName: "",
- groupTitle: "",
- },
- showQuestionCardDialog: false,
- cardQuestionId: "",
- cardRegistrationCodeList: [],
- });
- const majorQuestionCharts = ref<any>(null);
- const majorTable = ref<InstanceType<
- (typeof import("element-plus"))["ElTable"]
- > | null>(null);
- // 排序
- const ChangeChartOrder = (
- sortType: string,
- legendData: string[],
- barIndex: number | string,
- number: number,
- ) => {
- if (number == 1) {
- const fullVolume = state.problemAnalysisData.groupList.filter(
- (item) => item.groupCode == 999,
- );
- const groupList = state.problemAnalysisData.groupList.filter(
- (item) => item.groupCode != 999,
- );
- if (sortType == "2") {
- groupList.sort(
- (a, b) =>
- (a?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0) -
- (b?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0),
- );
- } else if (sortType == "3") {
- groupList.sort(
- (a, b) =>
- (b?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0) -
- (a?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0),
- );
- } else {
- groupList.sort((a, b) => (a?.groupCode || 0) - (b.groupCode || 0));
- }
- state.problemAnalysisData.groupList = [...groupList, ...fullVolume];
- state.problemAnalysisData.data = [];
- state.problemAnalysisData.groupList.forEach((group) => {
- const scoreRateArr =
- group.classList?.map((item) => item?.questionStats?.scoreRate ?? 0) ||
- [];
- state.problemAnalysisData.data.push([group.groupName, ...scoreRateArr]);
- });
- let chartTitle = ["group"];
- state.problemAnalysisData.changeHeaderList.forEach((item) => {
- chartTitle.push(item.label);
- });
- state.problemAnalysisData.data.unshift(chartTitle);
- state.problemAnalysisData.data.pop();
- state.problemAnalysisData.legendList = legendData;
- if (state.problemAnalysisData.groupList.length > 0) {
- GetClassQuestionData(0, state.problemAnalysisData.groupList[0].groupName);
- }
- } else {
- const fullVolume = state.problemAnalysisData.questionList.filter(
- (item) => item.showCode == 999,
- );
- const questionList = state.problemAnalysisData.questionList.filter(
- (item) => item.showCode != 999,
- );
- if (sortType == "2") {
- questionList.sort(
- (a, b) =>
- (a?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0) -
- (b?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0),
- );
- } else if (sortType == "3") {
- questionList.sort(
- (a, b) =>
- (b?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0) -
- (a?.classList?.[Number(barIndex)]?.questionStats?.scoreRate || 0),
- );
- } else {
- questionList.sort((a, b) => (a?.showCode || 0) - (b.showCode || 0));
- }
- state.problemAnalysisData.questionList = [...questionList, ...fullVolume];
- state.majorQuestionData.data = [];
- state.problemAnalysisData.questionList.forEach((question) => {
- const scoreRateArr =
- question.classList?.map(
- (item) => item?.questionStats?.scoreRate || 0,
- ) || [];
- state.majorQuestionData.data.push([
- question.questionName,
- ...scoreRateArr,
- ]);
- });
- let chartTitle: string[] = [];
- state.problemAnalysisData.changeHeaderList.forEach((item) => {
- chartTitle.push(item.label);
- });
- chartTitle.unshift("group");
- state.majorQuestionData.legendList = legendData;
- state.majorQuestionData.data.unshift(chartTitle);
- GetQuestionStatsData(0);
- }
- };
- // 试题图表切换公共方法
- type ChartDataProp =
- | "problemAnalysisData"
- | "majorQuestionData"
- | "questionScoreStatsData";
- const ChangeEchartType = (value: string, prop: ChartDataProp) => {
- if (prop == "problemAnalysisData") {
- ChangeChartOrder("1", state.problemAnalysisData.defaultLegendList, "", 1);
- } else if (prop == "majorQuestionData") {
- ChangeChartOrder("1", state.majorQuestionData.defaultLegendList, "", 2);
- }
- state[prop].chartType = value;
- };
- // 题目分组分析
- const GetQuestionGroupAnalysisData = () => {
- state.problemAnalysisData.data = [];
- state.dataLoading = true;
- questionGroupAnalysis({
- ...analysisStore.filterObject,
- analysisType: 4,
- })
- .then((res: ApiResponse) => {
- state.problemAnalysisData.data = [];
- if (res.code == 200 && res.data && res.data.groupList.length) {
- const { data } = res;
- const groupList = data.groupList || [];
- const changeHeaderList = data.changeHeaderList || [];
- state.problemAnalysisData.groupList = groupList;
- state.problemAnalysisData.groupTableList = cloneDeep(groupList);
- state.problemAnalysisData.headerList = data.headerList || [];
- state.problemAnalysisData.changeHeaderList = changeHeaderList;
- state.problemAnalysisData.childHeaderList = data.childHeaderList || [];
- state.chartKey++;
- state.problemAnalysisData.data = groupList.map((item) => [
- item.groupName,
- ]);
- groupList.forEach((group, key) => {
- const scoreRateArr =
- group.classList?.map(
- (item) => item?.questionStats?.scoreRate ?? 0,
- ) || [];
- state.problemAnalysisData.data[key].push(...scoreRateArr);
- });
- let chartTitle: string[] = [];
- let titleType: (string | number)[] = [];
- let classSelectLegend: string[] = [];
- changeHeaderList.forEach((item) => {
- chartTitle.push(item.label);
- titleType.push(item.type ? item.type : "");
- if (item.prop != "0" && item.prop.indexOf("school_group") == -1) {
- classSelectLegend.push(item.label);
- }
- });
- chartTitle.unshift("group");
- if (analysisStore.filterObject.classLevel != 2) {
- let startIndex = 1,
- endIndex = 3;
- if (analysisStore.filterObject.schoolLevel == 2) {
- startIndex =
- titleType.lastIndexOf(1) > -1 ? titleType.lastIndexOf(1) + 1 : 1;
- endIndex = titleType.indexOf(2) > -1 ? titleType.indexOf(2) + 2 : 3;
- } else {
- const barFirtIndex =
- titleType.lastIndexOf(1) > -1 ? titleType.lastIndexOf(1) + 1 : 1;
- startIndex = barFirtIndex;
- endIndex = barFirtIndex + 2;
- }
- state.problemAnalysisData.legendList =
- chartTitle.length > 1 ? chartTitle.slice(startIndex, endIndex) : [];
- state.problemAnalysisData.showBarLegendIndex = endIndex - 2;
- } else {
- state.problemAnalysisData.legendList = classSelectLegend;
- state.problemAnalysisData.showBarLegendIndex =
- changeHeaderList.length - 1;
- }
- state.problemAnalysisData.defaultLegendList = cloneDeep(
- state.problemAnalysisData.legendList,
- );
- state.problemAnalysisData.data.unshift(chartTitle);
- state.problemAnalysisData.data.pop();
- if (groupList.length > 0) {
- GetClassQuestionData(0, groupList[0].groupName);
- }
- GetMajorTableData();
- } else {
- // 重置所有数据
- state.questionTypesData.data = [];
- state.questionTypesData.tableData = [];
- state.problemAnalysisData.showBarLegendIndex = 1;
- state.problemAnalysisData.groupList = [];
- state.problemAnalysisData.questionList = [];
- state.problemAnalysisData.headerList = [];
- state.problemAnalysisData.changeHeaderList = [];
- state.problemAnalysisData.childHeaderList = [];
- state.majorQuestionData.data = [];
- state.majorQuestionData.legendList = [];
- state.questionScoreStatsData.datax = [];
- state.questionScoreStatsData.datay = [];
- state.questionScoreStatsData.dataStackY = [];
- state.questionScoreStatsData.tooltipData = [];
- state.questionScoreStatsData.rate = 0;
- state.questionScoreStatsData.maxClass = "";
- state.questionScoreStatsData.minClass = "";
- state.questionAnswerData.datax = [];
- state.questionAnswerData.datay = [];
- state.questionAnswerData.answerValue = "";
- state.questionAnswerData.answerScore = [];
- state.questionAnswerData.questionType = "";
- state.questionAnswerData.fullMark = "";
- state.questionAnswerData.tableData = [];
- state.questionAnswerData.classListIndex = 0;
- state.majorAnswerData.tableData = [];
- state.majorAnswerData.paperUrl = "";
- state.majorAnswerData.rowIndex = 0;
- state.majorStudentData.tableData = [];
- state.majorStudentData.legendList = [];
- state.majorStudentData.radarChartData = [];
- state.majorStudentData.excellentCourseList = "";
- state.majorStudentData.inferiorCourseList = "";
- state.majorTableData.tableData = [];
- state.majorTableData.headerData = [];
- state.majorTableData.changeHeaderData = [];
- state.majorTableData.childHeaderData = [];
- state.majorTableData.pageSize = 10;
- state.majorTableData.total = 0;
- state.majorTableData.currentPage = 1;
- }
- })
- .finally(() => {
- state.dataLoading = false;
- });
- };
- // 点击柱状图折线图
- const HandleChartClick = (index: number | string, name: string) => {
- majorQuestionCharts.value?.ChangeSelectValue?.();
- GetClassQuestionData(Number(index), name);
- };
- // 大题分析 /阅读表达 点击柱状图
- const HandleQuestionChartClick = (index: number | string, name: string) => {
- GetQuestionStatsData(Number(index));
- };
- // 获取小题分析 /第N题
- const GetQuestionStatsData = (index: number) => {
- const questionData = cloneDeep(state.problemAnalysisData.questionList[index]);
- state.problemAnalysisData.questionListIndex = index;
- state.questionTitle = questionData?.questionName || "";
- if (questionData && questionData.classList) {
- state.questionScoreStatsData.datax = [];
- state.questionScoreStatsData.datay = [];
- state.questionScoreStatsData.dataStackY = [];
- state.questionScoreStatsData.tooltipData = [];
- let dataStackY: number[] = [];
- const isHasEstimatedScore = state.problemAnalysisData.headerList.find(
- (item) => item.prop == "estimatedScore",
- );
- if (questionData.classList.length > 1) {
- const key = state.problemAnalysisData.showBarLegendIndex;
- state.questionScoreStatsData.markLineData = [];
- const classList = questionData.classList || [];
- if (
- analysisStore.filterObject.classLevel == 0 ||
- analysisStore.filterObject.classLevel == 1
- ) {
- state.questionScoreStatsData.rate = Number(
- classList?.[key - 1]?.questionStats?.scoreRate || 0,
- );
- } else {
- state.questionScoreStatsData.rate = Number(
- classList?.[key]?.questionStats?.scoreRate || 0,
- );
- }
- classList.forEach((item: ClassItem, idx: number) => {
- const keyIndex =
- analysisStore.filterObject.classLevel == 0 ||
- analysisStore.filterObject.classLevel == 1
- ? key - (isHasEstimatedScore ? 2 : 1)
- : key;
- if (idx <= keyIndex) {
- const rate = Number(item?.questionStats?.scoreRate || 0);
- state.questionScoreStatsData.markLineData.push({
- legendName: item.groupName,
- value: rate,
- isShow: idx == keyIndex,
- });
- }
- });
- questionData.classList = questionData.classList.slice(
- isHasEstimatedScore ? key - 1 : key,
- );
- } else {
- state.questionScoreStatsData.rate = 60;
- }
- questionData.classList.forEach((item) => {
- state.questionScoreStatsData.datax.push(item.groupName);
- state.questionScoreStatsData.datay.push(
- item.questionStats?.scoreRate || 0,
- );
- dataStackY.push(item.questionStats?.lossRate || 0);
- state.questionScoreStatsData.tooltipData.push({
- list: [
- { name: "失分率", value: `${item.questionStats?.lossRate || 0}%` },
- ],
- });
- });
- const datay = state.questionScoreStatsData.datay;
- const max = datay.length > 0 ? Math.max(...datay) : 0;
- const min = datay.length > 0 ? Math.min(...datay) : 0;
- const maxValue = max.toFixed(2);
- const minValue = min.toFixed(2);
- let maxClass: string[] = [];
- let minClass: string[] = [];
- state.questionScoreStatsData.datay.forEach((item, idx) => {
- if (Number(item).toFixed(2) == maxValue)
- maxClass.push(state.questionScoreStatsData.datax[idx]);
- if (Number(item).toFixed(2) == minValue)
- minClass.push(state.questionScoreStatsData.datax[idx]);
- });
- state.questionScoreStatsData.minClass = minClass.join("、");
- state.questionScoreStatsData.maxClass = maxClass.join("、");
- state.questionScoreStatsData.dataStackY = [
- state.questionScoreStatsData.datay,
- dataStackY,
- ];
- }
- GetQuestionAnswerData(state.problemAnalysisData.showBarLegendIndex);
- };
- // 大题分析 /阅读表达
- const GetClassQuestionData = (index: number, name: string) => {
- state.majorQuestionData.data = [];
- state.groupName = name;
- const groupItem = state.problemAnalysisData.groupList[index];
- if (!groupItem) return;
- const questionList = groupItem.questionList || [];
- state.problemAnalysisData.questionList = questionList;
- state.majorQuestionData.data = questionList.map((item) => [
- item.questionName,
- ]);
- questionList.forEach((question, key) => {
- const scoreRateArr =
- question.classList?.map((item) => item?.questionStats?.scoreRate || 0) ||
- [];
- state.majorQuestionData.data[key].push(...scoreRateArr);
- });
- let chartTitle: string[] = [];
- let titleType: (string | number)[] = [];
- let classSelectLegend: string[] = [];
- state.problemAnalysisData.changeHeaderList.forEach((item) => {
- chartTitle.push(item.label);
- titleType.push(item.type ? item.type : "");
- if (item.prop != "0" && item.prop.indexOf("school_group") == -1) {
- classSelectLegend.push(item.label);
- }
- });
- chartTitle.unshift("group");
- if (analysisStore.filterObject.classLevel != 2) {
- let startIndex = 1,
- endIndex = 3;
- if (analysisStore.filterObject.schoolLevel == 2) {
- startIndex =
- titleType.lastIndexOf(1) > -1 ? titleType.lastIndexOf(1) + 1 : 1;
- endIndex = titleType.indexOf(2) > -1 ? titleType.indexOf(2) + 2 : 3;
- } else {
- const barFirtIndex =
- titleType.lastIndexOf(1) > -1 ? titleType.lastIndexOf(1) + 1 : 1;
- startIndex = barFirtIndex;
- endIndex = barFirtIndex + 2;
- }
- state.majorQuestionData.legendList =
- chartTitle.length > 1 ? chartTitle.slice(startIndex, endIndex) : [];
- state.majorQuestionData.showBarLegendIndex = endIndex - 2;
- } else {
- state.majorQuestionData.legendList = classSelectLegend;
- }
- state.majorQuestionData.defaultLegendList = cloneDeep(
- state.majorQuestionData.legendList,
- );
- state.majorQuestionData.data.unshift(chartTitle);
- GetQuestionStatsData(0);
- };
- // 切换 获取小题分析 /第N题 获取第N班答题列表
- const HandleQuestionScoreChartClick = (index: number) => {
- GetQuestionAnswerData(index + state.problemAnalysisData.showBarLegendIndex);
- };
- // 获取小题分析 /第N题 / 第N班 选项
- const GetQuestionAnswerData = (index: number) => {
- const isHasEstimatedScore = state.problemAnalysisData.headerList.find(
- (item) => item.prop == "estimatedScore",
- );
- const newINdex = isHasEstimatedScore ? index - 1 : index;
- const question =
- state.problemAnalysisData.questionList[
- state.problemAnalysisData.questionListIndex
- ];
- if (!question) return;
- const classList = question.classList?.[newINdex];
- state.questionAnswerData.answerValue = question.answerValue;
- state.questionAnswerData.questionType = question.questionType;
- state.questionAnswerData.fullMark = question.fullMark;
- state.questionAnswerData.classListIndex = newINdex;
- if (classList && classList.questionStats) {
- const answerList = classList.questionStats.answerList || [];
- state.classTitle = classList.groupName;
- state.questionAnswerData.datax = [];
- state.questionAnswerData.datay = [];
- let sum = 0;
- answerList.forEach((item) => {
- sum += item.studentNum;
- state.questionAnswerData.datax.push(item.name);
- state.questionAnswerData.datay.push(item.studentNum);
- state.questionAnswerData.answerScore.push(item.score);
- });
- state.questionAnswerData.tableData = [
- { title: "得分率", value: `${classList.questionStats.scoreRate}%` },
- { title: "平均分", value: `${classList.questionStats.averageScore}` },
- { title: "最高分", value: `${classList.questionStats.maxScore}` },
- { title: "最低分", value: `${classList.questionStats.minScore}` },
- { title: "人数", value: `${sum}人` },
- ];
- if (analysisStore.filterObject.schoolLevel == 2) {
- GetAnswerListByAnswerAndScore(
- 0,
- answerList.length > 0 ? answerList[0].name : "",
- );
- }
- }
- };
- // 点击柱状图小题分析 /第N题 / 第N班 选项 获取答题情况
- const HandleQuestionAnswerChartClick = (index: number, name: string) => {
- if (analysisStore.filterObject.schoolLevel == 2) {
- GetAnswerListByAnswerAndScore(index, name);
- }
- };
- // 通过答案或者分数查询某题作答情况
- const GetAnswerListByAnswerAndScore = (index: number, name: string) => {
- state.optionTitle = name;
- const question =
- state.problemAnalysisData.questionList[
- state.problemAnalysisData.questionListIndex
- ];
- if (!question) return;
- const classItem =
- question.classList?.[state.questionAnswerData.classListIndex];
- if (!classItem) return;
- const classItemKeys = Object.keys(classItem);
- const reportParam: any = { ...analysisStore.filterObject };
- Object.keys(analysisStore.filterObject).forEach((item) => {
- if (classItemKeys.indexOf(item) > -1) {
- reportParam[item] = classItem[item];
- }
- });
- const answer = classItem.questionStats?.answerList?.[index];
- const params = {
- ...reportParam,
- questionId: question.questionId,
- registrationCodeList: answer?.registrationCodeList || [],
- };
- state.cardQuestionId = params.questionId;
- state.cardRegistrationCodeList = params.registrationCodeList;
- queryAnswerListByAnswerAndScore(params).then((res: any) => {
- if (res.code == 200) {
- state.majorAnswerData.tableData = res.data || [];
- HandleRowClick(
- state.majorAnswerData.tableData.length > 0
- ? state.majorAnswerData.tableData[0]
- : {},
- );
- } else {
- state.majorAnswerData.tableData = [];
- }
- });
- };
- // 点击某行学生某题作答情况
- const HandleRowClick = (row: any) => {
- if (row?.studentRegistrationCode) {
- const question =
- state.problemAnalysisData.questionList[
- state.problemAnalysisData.questionListIndex
- ];
- if (question) {
- state.paperInfos = {
- examPaperId: analysisStore.filterObject.subjectId,
- platformNumber: row.studentRegistrationCode,
- questionId: question.questionId,
- };
- }
- state.majorAnswerData.rowIndex = state.majorAnswerData.tableData.findIndex(
- (item) => item.studentRegistrationCode == row?.studentRegistrationCode,
- );
- } else {
- state.paperInfos = { examPaperId: "", platformNumber: "", questionId: "" };
- }
- };
- // 获取项目分析表
- const GetMajorTableData = () => {
- state.majorTableData.tableKey += 1;
- state.majorTableData.headerData = state.problemAnalysisData.headerList;
- state.majorTableData.changeHeaderData =
- state.problemAnalysisData.changeHeaderList;
- state.majorTableData.childHeaderData =
- state.problemAnalysisData.childHeaderList;
- const headerPropData = state.problemAnalysisData.headerList.map(
- (item) => item.prop,
- );
- const childHeaderPropData = state.problemAnalysisData.childHeaderList.map(
- (item) => item.prop,
- );
- let allTableData: any[] = [];
- const allList = state.problemAnalysisData.groupTableList || [];
- allList.forEach((item) => {
- let itemObj: any = {
- questionId: item?.questionId || "",
- knowledgeId: item?.knowledgeId || "",
- };
- const classList = item.classList || [];
- headerPropData.forEach((title) => {
- itemObj[title] = Array.isArray(item[title])
- ? item[title].join("、")
- : item[title];
- });
- classList.forEach((el) => {
- if (
- el.questionStats?.headDataBOList &&
- el.questionStats.headDataBOList.length > 0
- ) {
- el.questionStats.headDataBOList.forEach((bo) => {
- el.questionStats[`${bo.name}Rate`] = bo.rate;
- el.questionStats[`${bo.name}StudentNumber`] = bo.studentNumber;
- });
- } else {
- el.questionStats = el.questionStats || {};
- }
- childHeaderPropData.forEach((field) => {
- itemObj[`${el.groupId}_${field}`] = el.questionStats[field];
- });
- });
- allTableData.push(itemObj);
- });
- state.majorTableData.total = allTableData.length;
- state.majorTableData.allTableData = allTableData;
- GetPageMajorTableData();
- ResetTableScroll();
- };
- const GetPageMajorTableData = () => {
- const start =
- (state.majorTableData.currentPage - 1) * state.majorTableData.pageSize;
- const end = start + state.majorTableData.pageSize;
- state.majorTableData.tableData = state.majorTableData.allTableData.slice(
- start,
- end,
- );
- };
- // 重置表格滚动条位置
- const ResetTableScroll = () => {
- nextTick(() => {
- if (majorTable.value) {
- const tableBody = majorTable.value.$el?.querySelector(
- ".el-table__body-wrapper",
- );
- if (tableBody) {
- tableBody.scrollTop = 0;
- tableBody.scrollLeft = 0;
- }
- }
- });
- };
- // 设置表头字段显示隐藏
- const SetEnterHeaderData = (data: any) => {
- if (data.static && data.static.length > 0)
- state.problemAnalysisData.headerList = [...data.static];
- if (data.dynamisc && data.dynamisc.length > 0)
- state.problemAnalysisData.changeHeaderList = [...data.dynamisc];
- if (data.child && data.child.length > 0)
- state.problemAnalysisData.childHeaderList = [...data.child];
- GetMajorTableData();
- };
- // 人员弹框
- const OpenStudentDialog = (
- childHeader: HeaderItem,
- parent: HeaderItem,
- row: any,
- ) => {
- if (
- (childHeader.prop.indexOf("Count") > -1 ||
- childHeader.prop.indexOf("Number") > -1) &&
- row?.[`${parent.prop}_${childHeader.prop}`] > 0
- ) {
- state.dialogData.showDialog = true;
- state.dialogData.title = childHeader.label;
- state.dialogData.tableTitle = parent.label;
- state.dialogData.fiveRateName = "";
- const fiveRateProps = [
- "topStudentNumber",
- "excellentStudentNumber",
- "goodStudentNumber",
- "passStudentNumber",
- "lowStudentNumber",
- ];
- if (fiveRateProps.includes(childHeader.prop)) {
- state.dialogData.fiveRateName = childHeader.label.replace(/人数/g, "");
- }
- state.dialogData.selectSubjectName = analysisStore.filterObject.subjectName;
- if (parent.prop == "0") {
- state.dialogData.selectSchoolLevel = 0;
- state.dialogData.selectSchoolName = parent.label;
- state.dialogData.selectClassLevel = 0;
- state.dialogData.selectClassName = "年级";
- } else if (parent.prop.indexOf("school_group") > -1) {
- state.dialogData.selectSchoolLevel = 1;
- state.dialogData.selectSchoolName = parent.label;
- state.dialogData.selectClassLevel = 0;
- state.dialogData.selectClassName = "年级";
- } else if (
- parent.prop.indexOf("school") > -1 &&
- parent.prop.indexOf("school_group") == -1
- ) {
- state.dialogData.selectSchoolLevel = 2;
- state.dialogData.selectSchoolName = parent.label;
- state.dialogData.selectClassLevel = 0;
- state.dialogData.selectClassName = "年级";
- } else if (parent.prop.indexOf("class_group") > -1) {
- state.dialogData.selectSchoolLevel = 2;
- state.dialogData.selectSchoolName = analysisStore.filterObject.schoolName;
- state.dialogData.selectClassLevel = 1;
- state.dialogData.selectClassName = parent.label;
- } else {
- state.dialogData.selectSchoolLevel = 2;
- state.dialogData.selectSchoolName = analysisStore.filterObject.schoolName;
- state.dialogData.selectClassLevel = 2;
- state.dialogData.selectClassName = parent.label;
- }
- state.dialogData.questionId = row.questionId;
- state.dialogData.isPaper = row.questionName == "全卷" ? 1 : 0;
- if (childHeader.prop == "fullMarkCount") state.dialogData.quesScoreType = 0;
- else if (childHeader.prop == "zeroMarkCount")
- state.dialogData.quesScoreType = 1;
- else state.dialogData.quesScoreType = 3;
- state.dialogData.knowledgeId = row.knowledgeId;
- state.dialogData.questionGroupName = row?.groupName || "";
- state.dialogData.groupTitle = state.groupTitle.replace(/分析/g, "");
- }
- };
- // 关闭人员弹框
- const CloseDialog = (val: boolean) => {
- state.dialogData.showDialog = val;
- };
- // 分页获取分析表
- const ChangeCurrentPage = (val: number) => {
- state.majorTableData.currentPage = val;
- GetMajorTableData();
- };
- const ChangePageSize = (val: number) => {
- state.majorTableData.pageSize = val;
- state.majorTableData.currentPage = 1;
- GetMajorTableData();
- };
- // 导出Excel
- const ExportExcel = () => {
- reportModuleRef.value?.SetExportLoading?.(true);
- const examName = getExamName.value;
- let params: ExportParams = {
- fileName: `${GetExcelFileName(examName, analysisStore.filterObject, state.groupTitle)}`,
- examName: examName,
- sheetName: state.groupTitle,
- staticHeaderData: [],
- childHeaderData: [],
- dynamicsHeaderData: [],
- dataList: [],
- };
- params.staticHeaderData = state.problemAnalysisData.headerList.filter(
- (item) => item.display,
- );
- params.childHeaderData = state.problemAnalysisData.childHeaderList.filter(
- (item) => item.display,
- );
- params.dynamicsHeaderData = state.problemAnalysisData.changeHeaderList.filter(
- (item) => item.display,
- );
- let dataList: any[][] = [];
- state.majorTableData.allTableData.forEach((item) => {
- const rowData: any[] = [];
- params.staticHeaderData.forEach((header) => {
- rowData.push(item?.[header.prop] || "-");
- });
- params.dynamicsHeaderData.forEach((parent) => {
- params.childHeaderData.forEach((child) => {
- const itemValue = item[`${parent.prop}_${child.prop}`];
- if (child.prop.indexOf("Rate") > -1) {
- rowData.push(itemValue ? `${itemValue}%` : "-");
- } else {
- rowData.push(itemValue ?? "-");
- }
- });
- });
- dataList.push(rowData);
- });
- params.dataList = dataList;
- downloadExcel(publicExport, params).finally(() => {
- reportModuleRef.value?.SetExportLoading?.(false);
- });
- };
- // 设置表头样式
- const HeaderRowStyle = ({ rowIndex }: { row: any; rowIndex: number }) => {
- if (rowIndex === 1) return { display: "none" };
- return {};
- };
- const TableRowClassName = ({ rowIndex }: { row: any; rowIndex: number }) => {
- if (rowIndex === state.majorAnswerData.rowIndex) return "current-row";
- return "";
- };
- // 查看答题卡
- const handleClick = (row: any) => {
- state.paperInfo = {
- examPaperId: analysisStore.filterObject.subjectId,
- platformNumber: row.studentRegistrationCode,
- questionId: "",
- };
- state.paperTitle = `${getExamName.value}-${analysisStore.filterObject.subjectName}-${row.className}-${row.studentUserName}`;
- state.showStudentPaperDialog = true;
- };
- // 更新弹窗状态
- const UpdateModelValue = (val: boolean) => {
- state.showStudentPaperDialog = val;
- };
- // 批量查看小题答题卡
- const VisibleQuestionCard = () => {
- state.showQuestionCardDialog = true;
- };
- // 关闭弹框
- const CloseQuestionCardDialog = () => {
- state.showQuestionCardDialog = false;
- };
- const pageInit = () => {
- const chartTypeLists = [
- { label: "组合图", value: "line_bar_chart" },
- { label: "柱状图", value: "vertical_bar" },
- { label: "雷达图", value: "radar_chart" },
- ];
- const chartTypeList = [
- { label: "柱状图", value: "vertical_bar" },
- { label: "雷达图", value: "radar_chart" },
- ];
- const isNotSingleClass = analysisStore.filterObject.classLevel != 2;
- state.problemAnalysisData.chartTypeList = isNotSingleClass
- ? chartTypeLists
- : chartTypeList;
- state.problemAnalysisData.chartType = isNotSingleClass
- ? "line_bar_chart"
- : "vertical_bar";
- state.majorQuestionData.chartTypeList = isNotSingleClass
- ? chartTypeLists
- : chartTypeList;
- state.majorQuestionData.chartType = isNotSingleClass
- ? "line_bar_chart"
- : "vertical_bar";
- state.questionScoreStatsData.chartType = "vertical_bar";
- state.majorTableData.currentPage = 1;
- state.majorAnswerData.rowIndex = 0;
- GetQuestionGroupAnalysisData();
- };
- // 监听筛选条件
- watch(
- () => analysisStore.filterObject,
- () => {
- pageInit();
- },
- { deep: true },
- );
- onMounted(() => {
- pageInit();
- });
- </script>
- <style lang="scss" scoped>
- .content_left {
- &.answer {
- width: calc(100% - 220px);
- }
- &.paper_card {
- width: calc(100% - 480px);
- height: 400px;
- background-color: #f5f5f5;
- border-radius: 10px;
- }
- }
- .content_right {
- height: 100%;
- display: flex;
- align-items: center;
- margin: auto 0 auto auto;
- padding-bottom: 0;
- &.answer {
- width: 200px;
- }
- &.paper_card {
- width: 460px;
- }
- :deep(.el-table) {
- border-left: 0px;
- border-right: 0px;
- .el-table__cell {
- height: 44px;
- }
- }
- }
- </style>
|