zhangjie 2 anni fa
parent
commit
e5feb09a1f

+ 60 - 62
src/features/report/ReportCover.vue

@@ -28,69 +28,11 @@
           <th>分析</th>
           <th>说明</th>
         </tr>
-        <tr>
-          <td>1</td>
-          <td>关联分析</td>
-          <td>
-            对比分析不同年度的整体分致数据变化,若无其它年度分析项目,此投告为空。
-          </td>
-        </tr>
-        <tr>
-          <td>2</td>
-          <td>科目试卷特征量数</td>
-          <td>针对本年度数据做整体总结。</td>
-        </tr>
-        <tr>
-          <td>3</td>
-          <td>科目成绩频率分布</td>
-          <td>分析各区间段内人数频率以表格及曲线图展示,整体获知出题情况。</td>
-        </tr>
-        <tr>
-          <td>4</td>
-          <td>科目分数线分组频率分布</td>
-          <td>
-            可自定义分数点,如无自定义则系统默认三个点:零、默认起始计算分、满分,便于划线录取。
-          </td>
-        </tr>
-        <tr>
-          <td>5</td>
-          <td>试题特征量数分析</td>
-          <td>
-            分析每道题的特征:谁度、平均值、方差、区分度等,反映出每道题的出题质量。
-          </td>
-        </tr>
-        <tr>
-          <td>6</td>
-          <td>试卷题目难度编排曲线</td>
-          <td></td>
-        </tr>
-        <tr>
-          <td>7</td>
-          <td>试题题目区分度编排</td>
-          <td>曲线展示整卷区分度的变化,反应各题对本次选材的贡献度。</td>
-        </tr>
-        <tr>
-          <td>8</td>
-          <td>试题难度分组分布</td>
-          <td>
-            根据阅卷的打分结构计算每一道大题下展每一道小题,在各总分分数区间段的难度系效并形成曲线圈,并可自定义总分分数区间段,并计算难度系数,当某些题目在高分段的难度表现的比低分段的表现更难时需要考恧出题是否过偏或。
-          </td>
-        </tr>
-        <tr>
-          <td>9</td>
-          <td>题型难度分组分布</td>
-          <td>
-            在难度系数上可将各题按题型、考查知识点、考查能力点
-            等多维度来分析全卷在各考查维度的难度占比 (需要定义
-            并导入各题的属性)。
-          </td>
-        </tr>
-        <tr>
-          <td>10</td>
-          <td>题型区分度分组分布</td>
+        <tr v-for="(item, index) in introData" :key="index">
+          <td>{{ index + 1 }}</td>
+          <td>{{ item.name }}</td>
           <td>
-            在区分度上可将各题按题型、考查知识点、考查能力点等多维度来分析全卷在各考查维度的区分度占比(需要定义
-            并导入各题的属性)。
+            {{ item.desc }}
           </td>
         </tr>
       </table>
@@ -152,8 +94,64 @@
 
 <script setup lang="ts">
 import { SASPaper } from "@/types";
+import { onMounted } from "vue";
 
 const props = defineProps<{
   paper: SASPaper;
+  hasCompareProject: boolean;
 }>();
+
+const introList = [
+  {
+    name: "关联分析",
+    desc: "对比分析不同年度的整体分数数据变化,若无其它年度分析项目,此报告为空。",
+  },
+  {
+    name: "科目试卷特征量数",
+    desc: "针对本年度数据做整体总结。",
+  },
+  {
+    name: "科目成绩频率分布",
+    desc: "分析各区间段内人数频率以表格及曲线图展示,整体获知出题情况。",
+  },
+  {
+    name: "科目分数线分组频率分布",
+    desc: "可自定义分数点,如无自定义则系统默认三个点:零、默认起始计算分、满分,便于划线录取。",
+  },
+  {
+    name: "试题特征量数分析",
+    desc: "分析每道题的特征:难度、平均值、方差、区分度等,反映出每道题的出题质量。",
+  },
+  {
+    name: "试卷题目难度编排曲线",
+    desc: "曲线展示整卷难度变化,评估出题及顺序是否合理。",
+  },
+  {
+    name: "试题题目区分度编排",
+    desc: "曲线展示整卷区分度的变化,反应各题对本次选材的贡献度。",
+  },
+  {
+    name: "试题难度分组分布",
+    desc: "根据阅卷的打分结构计算每一道大题下属每一道小题,在各总分分数区间段的难度系数并形成曲线图,并可自定义总分分数区间段,并计算难度系数,当某些题目在高分段的难度表现的比低分段的表现更难时需要考虑出题是否过偏或。",
+  },
+  {
+    name: "题型难度分组分布",
+    desc: "在难度系数上可将各题按题型、考查知识点、考查能力点等多维度来分析全卷在各考查维度的难度占比(需要定义并导入各题的属性)。",
+  },
+  {
+    name: "题型区分度分组分布",
+    desc: "在区分度上可将各题按题型、考查知识点、考查能力点等多维度来分析全卷在各考查维度的区分度占比(需要定义并导入各题的属性)。",
+  },
+];
+
+interface IntroItemType {
+  name: string;
+  desc: string;
+}
+let introData = $shallowRef<IntroItemType[]>([]);
+
+onMounted(() => {
+  introData = introList;
+  if (!props.hasCompareProject) introData = introList.slice(1);
+});
 </script>

+ 96 - 4
src/features/report/ReportDifficulty.vue

@@ -2,13 +2,17 @@
   <div class="report-page report-diff">
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、试卷题目难度编排</h2>
+        <h2>{{ props.partNo }}、试卷题目难度编排</h2>
         <p class="report-name"></p>
       </div>
 
-      <div class="report-part diff-part">
+      <div class="report-part diff-part chart-part">
         <h4 class="report-part-title">难度系数表</h4>
-        <!-- TODO: chart -->
+        <v-chart
+          :initOptions="{ renderer: 'svg' }"
+          :option="chartOption()"
+          :autoresize="true"
+        />
       </div>
 
       <div class="report-part part-intro">
@@ -22,4 +26,92 @@
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { SASQuestion } from "@/types";
+import { EChartsOption } from "echarts";
+
+const props = defineProps<{
+  questions: SASQuestion[];
+  partNo: string;
+}>();
+
+function chartOption() {
+  return {
+    grid: {
+      show: true,
+      left: 35,
+      bottom: 20,
+      right: 5,
+      top: 45,
+      borderColor: "#A3B4CC",
+    },
+    xAxis: {
+      type: "category",
+      data: props.questions.map((v) => v.mainNumber + "-" + v.subNumber),
+      axisLine: {
+        show: false,
+      },
+      axisTick: {
+        show: false,
+      },
+      axisLabel: {
+        fontSize: 13,
+        fontWeight: 400,
+        color: "#172C4D",
+      },
+    },
+    yAxis: {
+      type: "value",
+      min: 0,
+      max: 1,
+      splitNumber: 10,
+      axisLine: {
+        show: false,
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: "#E1E5EB",
+        },
+      },
+      axisLabel: {
+        fontSize: 12,
+        color: "#6B7D99",
+        formatter: function (val: number) {
+          if (val === 1) return "1.0";
+          return val;
+        },
+      },
+    },
+    series: [
+      {
+        data: props.questions.map((v) => v.difficulty),
+        type: "line",
+        symbolSize: 6,
+        lineStyle: {
+          color: "#0091FF",
+          width: 3,
+        },
+        areaStyle: {
+          color: "rgba(0, 145, 255, 0.1)",
+        },
+        markLine: {
+          silent: true,
+          symbol: "none",
+          lineStyle: {
+            color: "#333",
+          },
+          data: [
+            {
+              yAxis: 0.5,
+            },
+            {
+              yAxis: 0.6,
+            },
+          ],
+        },
+      },
+    ],
+  } as EChartsOption;
+}
+</script>

+ 99 - 4
src/features/report/ReportDiscrimination.vue

@@ -2,13 +2,17 @@
   <div class="report-page report-diff">
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、试题题目区分度编排</h2>
+        <h2>{{ props.partNo }}、试题题目区分度编排</h2>
         <p class="report-name"></p>
       </div>
 
-      <div class="report-part diff-part">
+      <div class="report-part diff-part chart-part">
         <h4 class="report-part-title">区分度表</h4>
-        <!-- TODO: chart -->
+        <v-chart
+          :initOptions="{ renderer: 'svg' }"
+          :option="chartOption()"
+          :autoresize="true"
+        />
       </div>
 
       <div class="report-part part-intro">
@@ -22,4 +26,95 @@
   </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import { SASQuestion } from "@/types";
+import { EChartsOption } from "echarts";
+
+const props = defineProps<{
+  questions: SASQuestion[];
+  partNo: string;
+}>();
+
+function chartOption() {
+  return {
+    grid: {
+      show: true,
+      left: 35,
+      bottom: 20,
+      right: 5,
+      top: 45,
+      borderColor: "#A3B4CC",
+    },
+    xAxis: {
+      type: "category",
+      data: props.questions.map((v) => v.mainNumber + "-" + v.subNumber),
+      axisLine: {
+        show: false,
+      },
+      axisTick: {
+        show: false,
+      },
+      axisLabel: {
+        fontSize: 13,
+        fontWeight: 400,
+        color: "#172C4D",
+      },
+    },
+    yAxis: {
+      type: "value",
+      min: 0,
+      max: 1,
+      splitNumber: 10,
+      axisLine: {
+        show: false,
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: "#E1E5EB",
+        },
+      },
+      axisLabel: {
+        fontSize: 12,
+        color: "#6B7D99",
+        formatter: function (val: number) {
+          if (val === 1) return "1.0";
+          return val;
+        },
+      },
+    },
+    series: [
+      {
+        data: props.questions.map((v) => v.discrimination),
+        type: "line",
+        symbolSize: 6,
+        lineStyle: {
+          color: "#0091FF",
+          width: 3,
+        },
+        areaStyle: {
+          color: "rgba(0, 145, 255, 0.1)",
+        },
+        markLine: {
+          silent: true,
+          symbol: "none",
+          lineStyle: {
+            color: "#333",
+          },
+          data: [
+            {
+              yAxis: 0.2,
+            },
+            {
+              yAxis: 0.3,
+            },
+            {
+              yAxis: 0.4,
+            },
+          ],
+        },
+      },
+    ],
+  } as EChartsOption;
+}
+</script>

+ 102 - 32
src/features/report/ReportMain.vue

@@ -1,24 +1,49 @@
 <template>
   <div :class="['report', { 'is-print': viewType === 'print' }]">
-    <ReportCover :paper="sasPaper" />
-    <ReportCompare :paper="sasPaper" />
-    <ReportSummary :paper="sasPaper" />
-    <ReportScore :course="sasCourse" :scoreGap="scoreGap" />
-    <ReportScoreGroup :course="sasCourse" :scoreGap="scoreGap" />
-    <ReportQuestion :questions="paperQuestions" />
-    <ReportDifficulty />
-    <ReportDiscrimination />
+    <ReportCover :paper="sasPaper" :hasCompareProject="hasCompareProject" />
+    <ReportCompare v-if="hasCompareProject" :paper="sasPaper" />
+    <ReportSummary
+      v-if="sasPaper"
+      :paper="sasPaper"
+      :partNo="partNos.summary"
+    />
+    <ReportScore
+      :course="sasCourse"
+      :scoreGap="scoreGap"
+      :partNo="partNos.score"
+    />
+    <ReportScoreGroup
+      :course="sasCourse"
+      :scoreGap="scoreGap"
+      :partNo="partNos.scoreGroup"
+    />
+    <ReportQuestion
+      v-if="paperQuestions.length"
+      :questions="paperQuestions"
+      :partNo="partNos.question"
+    />
+    <ReportDifficulty
+      v-if="paperQuestions.length"
+      :questions="paperQuestions"
+      :partNo="partNos.difficulty"
+    />
+    <ReportDiscrimination
+      v-if="paperQuestions.length"
+      :questions="paperQuestions"
+      :partNo="partNos.discrimination"
+    />
     <ReportQuestionGroup
+      v-if="sasPaper && paperQuestions.length"
       :questions="paperQuestions"
-      :startScore="sasPaper.startScore"
-      :totalScore="sasPaper.totalScore"
+      :paper="sasPaper"
+      :partNo="partNos.questionGroup"
     />
   </div>
 </template>
 
 <script setup lang="ts">
 import {
-  getPaperQuestionGroups,
+  getPaper,
   getPaperQuestions,
   getSasPaper,
 } from "@/api/paperAnalysisPage";
@@ -34,13 +59,7 @@ import ReportDifficulty from "./ReportDifficulty.vue";
 import ReportDiscrimination from "./ReportDiscrimination.vue";
 import { RANGE_POINT_TYPE } from "@/constants/constants";
 
-import {
-  // Paper,
-  SASPaper,
-  SASQuestion,
-  SasCourse,
-  RangeConfig,
-} from "@/types";
+import { SASPaper, SASQuestion, SasCourse, RangeConfig } from "@/types";
 import { useRoute } from "vue-router";
 import { computed, onMounted } from "vue";
 
@@ -56,21 +75,50 @@ const compareProjectId = +route.params.compareProjectId;
 const viewType = route.params.viewType;
 
 let paperQuestions = $ref<SASQuestion[]>([]);
+let partNos = $shallowRef({
+  summary: "二",
+  score: "三",
+  scoreGroup: "四",
+  question: "五",
+  difficulty: "六",
+  discrimination: "七",
+  questionGroup: "八",
+});
 
 const hasCompareProject = computed(() => !!compareProjectId);
-console.log(hasCompareProject);
 
 onMounted(async () => {
   await fetchData();
+
+  if (!hasCompareProject.value) {
+    partNos = {
+      summary: "一",
+      score: "二",
+      scoreGroup: "三",
+      question: "四",
+      difficulty: "五",
+      discrimination: "六",
+      questionGroup: "七",
+    };
+  }
 });
 
+function numberPrecision(num: number) {
+  return Math.round(num * 100) / 100;
+}
+
 async function fetchData() {
-  // await fetchPaper();
-  await fetchPaperQuestions();
+  await fetchPaper();
   await fetchSasPaper();
+  await fetchPaperQuestions();
   await fetchSasCourse();
 }
 
+async function fetchPaper() {
+  const res = await getPaper(paperId);
+  courseId = res.data.courseId;
+}
+
 async function fetchPaperQuestions() {
   const res = await getPaperQuestions(paperId);
   paperQuestions = res.data.map((q) => {
@@ -80,11 +128,11 @@ async function fetchPaperQuestions() {
     q.difficulityGroupLevel = JSON.parse(
       <string>(<unknown>q.difficulityGroupLevel) || "[]"
     );
-    q.avgScore = Math.round(q.avgScore * 100) / 100;
-    q.stdev = Math.round(q.stdev * 100) / 100;
-    q.coefficient = Math.round(q.coefficient * 100) / 100;
-    q.difficulty = Math.round(q.difficulty * 100) / 100;
-    q.discrimination = Math.round(q.discrimination * 100) / 100;
+    q.avgScore = numberPrecision(q.avgScore);
+    q.stdev = numberPrecision(q.stdev);
+    q.coefficient = numberPrecision(q.coefficient);
+    q.difficulty = numberPrecision(q.difficulty);
+    q.discrimination = numberPrecision(q.discrimination);
     return q;
   });
 }
@@ -98,6 +146,13 @@ async function fetchSasPaper() {
     <string>(<unknown>res.data.discriminationLevel) || "[]"
   );
   sasPaper = res.data;
+  scoreGap = getScoreGap(sasPaper.totalScore);
+
+  sasPaper.avgScore = numberPrecision(sasPaper.avgScore);
+  sasPaper.stdev = numberPrecision(sasPaper.stdev);
+  sasPaper.coefficient = numberPrecision(sasPaper.coefficient);
+  sasPaper.difficulty = numberPrecision(sasPaper.difficulty);
+  sasPaper.reliability1 = numberPrecision(sasPaper.reliability1);
 }
 
 async function fetchSasCourse() {
@@ -128,7 +183,6 @@ async function fetchSasCourse() {
       return acc;
     });
   sasCourse.scoreRangeTotal = acc;
-  let scoreGap = 10;
 
   sasCourse.segements = [];
   const validSeg = Math.round(sasCourse.totalScore / scoreGap);
@@ -139,13 +193,17 @@ async function fetchSasCourse() {
     row[1] = sasCourse.scoreRange
       .slice(row[0], nextScore * scoreGap)
       .reduce((p, c) => p + c, 0);
-    row[2] = row[1] / sasCourse.scoreRangeAcc[sasCourse.totalScore];
+    row[2] = numberPrecision(
+      (100 * row[1]) / sasCourse.scoreRangeAcc[sasCourse.totalScore]
+    );
     const endGap =
       nextScore * scoreGap - 1 >= sasCourse.totalScore
         ? sasCourse.totalScore
         : nextScore * scoreGap - 1;
     row[3] = sasCourse.scoreRangeAcc[endGap];
-    row[4] = row[3] / sasCourse.scoreRangeAcc[sasCourse.totalScore];
+    row[4] = numberPrecision(
+      (100 * row[3]) / sasCourse.scoreRangeAcc[sasCourse.totalScore]
+    );
     sasCourse.segements.push(row);
   }
   if (validSeg * scoreGap === sasCourse.totalScore) {
@@ -155,7 +213,7 @@ async function fetchSasCourse() {
       sasCourse.scoreRange[sasCourse.totalScore] /
         sasCourse.scoreRangeAcc[sasCourse.totalScore],
       sasCourse.scoreRangeAcc[sasCourse.totalScore],
-      1,
+      100,
     ]);
   }
 
@@ -175,7 +233,7 @@ async function fetchSasCourse() {
           nextRange.baseScore + nextRange.adjustScore
         )
         .reduce((p, c) => p + c, 0) || 0;
-    row[2] = row[1] / sasCourse.scoreRangeTotal;
+    row[2] = numberPrecision((100 * row[1]) / sasCourse.scoreRangeTotal);
     row[3] =
       sasCourse.scoreRangeAcc[
         nextRange.baseScore + nextRange.adjustScore - 1
@@ -186,7 +244,7 @@ async function fetchSasCourse() {
     ) {
       row[3] = sasCourse.scoreRangeAcc[sasCourse.scoreRangeAcc.length - 1];
     }
-    row[4] = row[3] / sasCourse.scoreRangeTotal;
+    row[4] = numberPrecision((100 * row[3]) / sasCourse.scoreRangeTotal);
 
     sasCourse.rangeSegements.push(row);
   }
@@ -200,4 +258,16 @@ async function fetchSasCourse() {
     }${rangeConfig.adjustScore > 0 ? "+" : ""}${rangeConfig.adjustScore})-`;
   }
 }
+
+function getScoreGap(totalScore: number) {
+  if (totalScore <= 150) {
+    return 10;
+  } else if (totalScore > 150 && totalScore <= 300) {
+    return 20;
+  } else if (totalScore > 300 && totalScore <= 450) {
+    return 30;
+  } else {
+    return 50;
+  }
+}
 </script>

+ 3 - 2
src/features/report/ReportQuestion.vue

@@ -6,7 +6,7 @@
   >
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、试卷题目特征分析</h2>
+        <h2>{{ props.partNo }}、试卷题目特征分析</h2>
         <p class="report-name"></p>
       </div>
 
@@ -68,7 +68,7 @@
 import { SASQuestion } from "@/types";
 import { onMounted } from "vue";
 
-const props = defineProps<{ questions: SASQuestion[] }>();
+const props = defineProps<{ questions: SASQuestion[]; partNo: string }>();
 
 let questionGroup = $shallowRef<SASQuestion[][]>([]);
 
@@ -76,6 +76,7 @@ onMounted(() => {
   const maxRowCount = 37;
   const groupCount = Math.ceil(props.questions.length / maxRowCount);
   questionGroup = [];
+
   for (let i = 0; i < groupCount; i++) {
     questionGroup.push(
       props.questions.slice(i * maxRowCount, (i + 1) * maxRowCount)

+ 7 - 7
src/features/report/ReportQuestionGroup.vue

@@ -2,7 +2,7 @@
   <div class="report-page report-question">
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、试题难度分组分布</h2>
+        <h2>{{ props.partNo }}、试题难度分组分布</h2>
         <p class="report-name"></p>
       </div>
 
@@ -12,7 +12,7 @@
             <col style="width: 30px" />
             <col style="width: 30px" />
             <col
-              v-for="(item, index) in props.totalScore / scoreGap"
+              v-for="(item, index) in props.paper.totalScore / scoreGap"
               :key="index"
             />
           </colgroup>
@@ -20,7 +20,7 @@
             <th>大题号</th>
             <th>小题号</th>
             <template
-              v-for="(item, index) in props.totalScore / scoreGap"
+              v-for="(item, index) in props.paper.totalScore / scoreGap"
               :key="index"
             >
               <th v-if="index >= limitScoreIndex">{{ index * scoreGap }}-</th>
@@ -46,16 +46,16 @@
 </template>
 
 <script setup lang="ts">
-import { SASQuestion } from "@/types";
+import { SASQuestion, SASPaper } from "@/types";
 import { computed } from "vue";
 
 const props = defineProps<{
   questions: SASQuestion[];
-  totalScore: number;
-  startScore: number;
+  paper: SASPaper;
+  partNo: string;
 }>();
 let limitScoreIndex = computed(() => {
-  return Math.floor(props.startScore / scoreGap);
+  return Math.floor(props.paper.startScore / scoreGap);
 });
 let scoreGap = $ref(10);
 </script>

+ 67 - 3
src/features/report/ReportScore.vue

@@ -2,7 +2,7 @@
   <div class="report-page report-score">
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、科目成绩频率分布</h2>
+        <h2>{{ props.partNo }}、科目成绩频率分布</h2>
         <p class="report-name"></p>
       </div>
 
@@ -40,9 +40,13 @@
         </table>
       </div>
 
-      <div class="report-part score-chart">
+      <div class="report-part score-chart chart-part">
         <h4 class="report-part-title">频率分布表({{ scoreGap }}分)</h4>
-        <!-- TODO: chart -->
+        <v-chart
+          :initOptions="{ renderer: 'svg' }"
+          :option="chartOption()"
+          :autoresize="true"
+        />
       </div>
 
       <div class="report-part part-intro">
@@ -58,9 +62,69 @@
 
 <script setup lang="ts">
 import { SasCourse } from "@/types";
+import { EChartsOption } from "echarts";
 
 const props = defineProps<{
   course: SasCourse;
   scoreGap: number;
+  partNo: string;
 }>();
+
+function chartOption() {
+  return {
+    grid: {
+      show: true,
+      left: 35,
+      bottom: 20,
+      right: 5,
+      top: 45,
+      borderColor: "#A3B4CC",
+    },
+    xAxis: {
+      type: "category",
+      data: props.course.segements.map((v) => v[0]),
+      axisLine: {
+        show: false,
+      },
+      axisTick: {
+        show: false,
+      },
+      axisLabel: {
+        fontSize: 13,
+        fontWeight: 400,
+        color: "#172C4D",
+      },
+    },
+    yAxis: {
+      type: "value",
+      axisLine: {
+        show: false,
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: "#E1E5EB",
+        },
+      },
+      axisLabel: {
+        fontSize: 12,
+        color: "#6B7D99",
+      },
+    },
+    series: [
+      {
+        data: props.course.segements.map((v) => v[1]),
+        type: "line",
+        symbolSize: 6,
+        lineStyle: {
+          color: "#0091FF",
+          width: 3,
+        },
+        areaStyle: {
+          color: "rgba(0, 145, 255, 0.1)",
+        },
+      },
+    ],
+  } as EChartsOption;
+}
 </script>

+ 67 - 3
src/features/report/ReportScoreGroup.vue

@@ -2,7 +2,7 @@
   <div class="report-page report-score">
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、科目分数线分组的频率分布</h2>
+        <h2>{{ props.partNo }}、科目分数线分组的频率分布</h2>
         <p class="report-name"></p>
       </div>
 
@@ -35,9 +35,13 @@
         </table>
       </div>
 
-      <div class="report-part freq-chart">
+      <div class="report-part freq-chart chart-part">
         <h4 class="report-part-title">频率分布表</h4>
-        <!-- TODO: chart -->
+        <v-chart
+          :initOptions="{ renderer: 'svg' }"
+          :option="chartOption()"
+          :autoresize="true"
+        />
       </div>
 
       <div class="report-part part-intro">
@@ -53,9 +57,69 @@
 
 <script setup lang="ts">
 import { SasCourse } from "@/types";
+import { EChartsOption } from "echarts";
 
 const props = defineProps<{
   course: SasCourse;
   scoreGap: number;
+  partNo: string;
 }>();
+
+function chartOption() {
+  return {
+    grid: {
+      show: true,
+      left: 35,
+      bottom: 20,
+      right: 5,
+      top: 45,
+      borderColor: "#A3B4CC",
+    },
+    xAxis: {
+      type: "category",
+      data: props.course.rangeSegements.map((v) => v[0]),
+      axisLine: {
+        show: false,
+      },
+      axisTick: {
+        show: false,
+      },
+      axisLabel: {
+        fontSize: 13,
+        fontWeight: 400,
+        color: "#172C4D",
+      },
+    },
+    yAxis: {
+      type: "value",
+      axisLine: {
+        show: false,
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: "#E1E5EB",
+        },
+      },
+      axisLabel: {
+        fontSize: 12,
+        color: "#6B7D99",
+      },
+    },
+    series: [
+      {
+        data: props.course.rangeSegements.map((v) => v[1]),
+        type: "line",
+        symbolSize: 6,
+        lineStyle: {
+          color: "#0091FF",
+          width: 3,
+        },
+        areaStyle: {
+          color: "rgba(0, 145, 255, 0.1)",
+        },
+      },
+    ],
+  } as EChartsOption;
+}
 </script>

+ 2 - 2
src/features/report/ReportSummary.vue

@@ -2,7 +2,7 @@
   <div class="report-page report-summary">
     <div class="report-body">
       <div class="report-body-head">
-        <h2>、科目试卷特征量数</h2>
+        <h2>{{ props.partNo }}、科目试卷特征量数</h2>
         <p class="report-name"></p>
       </div>
 
@@ -87,6 +87,7 @@ import { onMounted } from "vue";
 
 const props = defineProps<{
   paper: SASPaper;
+  partNo: string;
 }>();
 
 interface EvaluateItemType {
@@ -142,7 +143,6 @@ function getEvaluate(model: EvaluateItemType[], val: number): string {
     if (index) return item.range[0] <= val && item.range[1] > val;
     return item.range[0] <= val && item.range[1] >= val;
   });
-
   return m ? m.value : "";
 }
 </script>

+ 5 - 0
src/features/report/assets/report.css

@@ -128,6 +128,11 @@
 .part-intro span {
   font-weight: 600;
 }
+.chart-part .report-part-title {
+  position: absolute;
+  top: 27px;
+  z-index: 9;
+}
 
 /* report cover */
 .report-cover {

+ 4 - 2
src/main.ts

@@ -21,13 +21,14 @@ import numberToPercent from "@/directives/numberToPercent";
 import ECharts from "vue-echarts";
 import { use } from "echarts/core";
 
-import { CanvasRenderer } from "echarts/renderers";
+import { CanvasRenderer,SVGRenderer } from "echarts/renderers";
 import { LineChart, BarChart } from "echarts/charts";
 import {
   GridComponent,
   TitleComponent,
   TooltipComponent,
   LegendComponent,
+  MarkLineComponent,
 } from "echarts/components";
 import { Table } from "ant-design-vue";
 [Table].forEach((element) => {
@@ -35,13 +36,14 @@ import { Table } from "ant-design-vue";
 });
 
 use([
+  SVGRenderer,
   CanvasRenderer,
   LineChart,
   BarChart,
   GridComponent,
   TitleComponent,
   TooltipComponent,
-  LegendComponent,
+  LegendComponent,MarkLineComponent
 ]);
 
 import { createPinia } from "pinia";