Sfoglia il codice sorgente

成绩查询页面

liurongli 2 settimane fa
parent
commit
da5f1af0d3

BIN
src/assets/icon/down_expanded.webp


BIN
src/assets/icon/export_icon.webp


BIN
src/assets/icon/print_icon.webp


BIN
src/assets/icon/up_expanded.webp


+ 274 - 0
src/components/ReportModule.vue

@@ -0,0 +1,274 @@
+<template>
+    <div class="report_module">
+        <div class="module_title">
+            <div class="title_left">
+                <template v-if="showTitle && titleList.length">
+                    <template v-for="(item, index) in titleList">
+                        <span :class="{ span_item: index != titleList.length - 1 }">{{ item }}</span><span
+                            v-if="index != titleList.length - 1" class="split_line">/</span>
+                    </template>
+                </template>
+                <slot name="title_left" />
+            </div>
+            <div class="title_right">
+                <slot name="title_right" />
+                <template v-if="showPrintBtn">
+                    <el-button class="default_button" :loading="state.printLoading">
+                        <img v-if="!state.printLoading" src="@/assets/icon/print_icon.webp" alt="打印PDF" />打印PDF
+                    </el-button>
+                </template>
+                <template v-if="showExportBtn">
+                    <el-button class="default_button" :loading="state.exportLoading">
+                        <img v-if="!state.exportLoading" src="@/assets/icon/export_icon.webp" alt="导出Excel" />导出Excel
+                    </el-button>
+                </template>
+            </div>
+        </div>
+        <div :class="[`module_${tableOrChart}`, { table_42: tableOrChart == 'table' }]">
+            <!-- 表格或图表显示 -->
+            <slot name="module_table_chart" />
+            <!-- 表格分页 -->
+            <div class="page_pagination" v-if="tableOrChart == 'table' && showTablePage">
+                <el-pagination background :page-size="20" :pager-count="11" layout="prev, pager, next" :total="1000" />
+            </div>
+        </div>
+        <!-- 描述 -->
+        <div v-if="showDescribe" class="module_describe">
+            <div ref="textContainer" class="text_container" :class="{ 'expanded': state.isExpanded }">
+                <slot name="module_describe"></slot>
+            </div>
+            <button v-if="state.showExpandButton" @click="ToggleExpand" class="toggle_button"
+                :class="state.isExpanded ? 'show_expanded' : 'hide_expanded'">
+                {{ state.isExpanded ? '收起' : '展开' }}
+            </button>
+        </div>
+    </div>
+</template>
+<script lang="ts" setup>
+import { onMounted, reactive, nextTick, ref } from "vue";
+const props = defineProps({
+    titleList: {
+        type: Array,
+        default: []
+    },//标题
+    showTitle: {
+        type: Boolean,
+        default: true
+    },//是否显示标题
+    showPrintBtn: {
+        type: Boolean,
+        default: true
+    },//是否显示打印按钮
+    showExportBtn: {
+        type: Boolean,
+        default: true
+    },//是否显示导出按钮
+    tableOrChart: {
+        type: String,
+        default: 'table'
+    },
+    showTablePage: {
+        type: Boolean,
+        default: true
+    },//表格是否显示分页
+    showDescribe: {
+        type: Boolean,
+        default: true
+    },//是否显示描述
+})
+const state = reactive({
+    printLoading: false,
+    exportLoading: false,
+    isExpanded: false,//是否展开或者收缩
+    showExpandButton: true,
+});
+const textContainer = ref(null);
+
+onMounted(() => {
+    nextTick(() => {
+        checkLines();
+    })
+});
+// 检查行数并设置是否显示按钮
+const checkLines = () => {
+    const container = textContainer.value;
+    if (container) {
+        const range = document.createRange();// 创建一个 Range 对象
+        range.selectNodeContents(container);// 选择要测量的文本内容
+        const rect = range.getBoundingClientRect();// 获取文本内容的边界矩形
+        const lineHeight = parseInt(window.getComputedStyle(container).lineHeight, 10);// 获取行高
+        const lines = Math.ceil(rect.height / lineHeight);// 计算行数
+        console.log("打印行数lines", lines);
+        state.showExpandButton = lines > 3;
+    }
+}
+const ToggleExpand = () => {
+    state.isExpanded = !state.isExpanded;
+}
+</script>
+
+<style lang="scss" scoped>
+.report_module {
+    width: 100%;
+    background-color: #fff;
+    margin-top: 10px;
+    border-radius: 10px;
+
+    .module_title {
+        width: 100%;
+        padding: 0 20px;
+        box-sizing: border-box;
+        margin: auto;
+        font-weight: 600;
+        font-size: 16px;
+        color: #333333;
+        text-align: left;
+        line-height: 50px;
+        padding-top: 10px;
+        padding-bottom: 10px;
+        display: flex;
+        justify-content: space-between;
+
+        .title_left {
+            display: inline-flex;
+            align-items: center;
+            flex-wrap: wrap;
+
+            .span_item {
+                font-weight: 400;
+                font-size: 16px;
+                color: #999999;
+            }
+
+            .split_line {
+                font-weight: 400;
+                font-size: 16px;
+                color: #999999;
+                margin: 0 6px;
+            }
+        }
+
+        .title_right {
+            display: flex;
+            justify-content: flex-end;
+            align-items: center;
+            gap: 10px;
+
+            .default_button {
+                margin-left: 0px;
+                height: 36px;
+                line-height: 36px;
+                padding: 0 10px;
+                font-weight: 400;
+                font-size: 14px;
+                color: #666666;
+                display: flex;
+                align-items: center;
+
+                &:active,
+                &:focus {
+                    outline: none; // 去掉点击后的轮廓
+                    box-shadow: none; // 去掉点击后的阴影
+                    background-color: inherit; // 保持背景颜色不变
+                    color: #666666; // 保持文字颜色不变
+                    border: 1px solid #DCDFE6;
+                }
+
+                &:hover {
+                    background-color: #f9f9f9;
+                    border: 1px solid #DCDFE6;
+                    color: #666;
+                }
+
+                span {
+                    display: flex;
+                    align-items: center;
+                }
+
+                img {
+                    width: 16px;
+                    height: 16px;
+                    margin-right: 4px;
+                }
+
+                .el-icon-loading {
+                    color: #666;
+                }
+            }
+        }
+    }
+
+    .module_table {
+        width: 100%;
+        padding: 0 20px 14px;
+        box-sizing: border-box;
+        border-collapse: collapse;
+    }
+
+    .module_chart {
+        width: 100%;
+        padding: 0 20px;
+        box-sizing: border-box;
+        min-height: 360px;
+    }
+
+    .module_describe {
+        width: 100%;
+        padding: 14px 20px;
+        box-sizing: border-box;
+        font-weight: 400;
+        font-size: 14px;
+        color: #999999;
+        line-height: 24px;
+        text-align: left;
+
+        .text_container {
+            position: relative;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            display: -webkit-box;
+            -webkit-line-clamp: 3;
+            -webkit-box-orient: vertical;
+            transition: max-height 0.3s ease-out;
+            max-height: 72px;
+
+            p {
+                line-height: 22px;
+            }
+        }
+
+        .text_container.expanded {
+            -webkit-line-clamp: unset;
+            max-height: none;
+        }
+
+        .toggle_button {
+            margin-top: 8px;
+            cursor: pointer;
+            background: none;
+            border: none;
+            color: #2E64FA;
+            font-size: 14px;
+            line-height: 1;
+            width: 100%;
+            height: 24px;
+            text-align: right;
+            padding: 0 20px 0 0;
+        }
+
+        .show_expanded {
+            background-image: url('@/assets/icon/up_expanded.webp');
+            background-size: 16px 16px;
+            background-position: 100% 50%;
+            background-repeat: no-repeat;
+        }
+
+        .hide_expanded {
+            background-image: url('@/assets/icon/down_expanded.webp');
+            background-size: 16px 16px;
+            background-position: 100% 50%;
+            background-repeat: no-repeat;
+        }
+    }
+}
+</style>

+ 7 - 7
src/router/index.ts

@@ -83,37 +83,37 @@ const routes: Array<RouteRecordRaw> = [
           {
             path: 'optionDetail',
             name: 'optionDetail',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/optionDetail.vue')
           },//选项明细
           {
             path: 'levelDistribution',
             name: 'levelDistribution',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/levelDistribution.vue')
           },//水平分布
           {
             path: 'classComparison',
             name: 'classComparison',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/classComparison.vue')
           },//班级对比
           {
             path: 'questionAnalysis',
             name: 'questionAnalysis',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/questionAnalysis.vue')
           },//小题分析
           {
             path: 'groupAnalysis',
             name: 'groupAnalysis',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/groupAnalysis.vue')
           },//分组分析
           {
             path: 'optionAnalysis',
             name: 'optionAnalysis',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/optionAnalysis.vue')
           },//选项分析
           {
             path: 'propositionAnalysis',
             name: 'propositionAnalysis',
-            component: () => import('@/views/analysis/score.vue')
+            component: () => import('@/views/analysis/propositionAnalysis.vue')
           },//命题分析
         ]
       },

+ 33 - 0
src/styles/common.scss

@@ -4843,4 +4843,37 @@ body {
     /* 选中行的文字颜色 */
 
   }
+}
+// 成绩查询
+.page_report_main{
+  display: flex;
+  flex-direction: column;
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+  .page_filter{
+    width: 100%;
+    padding: 10px;
+    box-sizing: border-box;
+    background-color: #FFFFFF;
+    border-radius: 10px;
+    .filters_group{
+      .group_item{
+        margin-bottom: 0;
+        gap: 10px;
+        &:nth-child(1){
+          margin-top: 0;
+        }
+        .group_title{
+          width: auto;
+          margin-right: 10px;
+        }
+        .list_item{
+          padding-left: 10px;
+          padding-right: 10px;
+          border-radius: 4px;
+        }
+      }
+    }
+  }
 }

+ 102 - 0
src/views/analysis/classComparison.vue

@@ -0,0 +1,102 @@
+<template>
+  <ReportModule :titleList="['1、平均分分析图']" tableOrChart="chart" :showPrintBtn="false" :showExportBtn="false">
+    <template #module_table_chart>
+
+    </template>
+    <template #module_describe>
+      说明:信度是反应考试一致性或可靠性的指标,信度高,表示考试成绩较为准确,误差较小; 信度低,表明误差大;信度低的考试无法正确评价考生的知识水平与智能素质。
+      效度是指测验的有效性或正确性,即测验能否准确测量出其所要测量的内容。效度高的测验能够确保测验内容与测验目的的一致性,反映测验的正确性和准确性。
+      分析试题的难度和区分度可以确保试题的质量和有效性,从而更好地评估学生的知识掌握程度和区分不同水平的学生。
+      难度指试题的难易程度,通常用P值表示。计算方式为P=X/M(P为难度,X为试题平均得分,M为试题满分)。P值在0到1之间,值越大表示试题越简单,试题通常分为容易题(P≥0.7)、中等题(0.4至0.7之间)和难题(P≤0.4)。
+      区分度是衡量试题对不同水平考生的区分能力,通常用D值表示。通过计算高分组和低分组在某一试题上的通过率之差,得到试题区分度。区分度高的试题能将不同水平的考生区分开来,水平高的学生得高分,水平低的学生得低分。D值的取值范围介于-1至1之间,D值越高,区分的效果越好。D≥0.4表明此题的区分度很好,属于优秀;0.3≤D<0.4表明此题的区分度较好,属于良好;0.2≤D<0.4表明此题的区分度一般;D<0.2表明此题的区分度较低。
+      图中展示了各科的命题分析明细,点击科目的柱可在下方查看该科所有小题的命题分析。
+    </template>
+  </ReportModule>
+  <ReportModule :titleList="['2、平均分分析表']" tableOrChart="table" :showPrintBtn="false" :showDescribe="false">
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { onMounted, reactive } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  activeIndex: -1, // 设置分数段索引  默认第一个
+  sortRangeScore: [5, 10], // 设置分数段
+  scoreInput: "",//输入框的值
+});
+
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.el-input__inner {
+  height: 36px;
+}
+
+.el-input__suffix {
+  line-height: 36px;
+}
+
+.right_item {
+  font-size: 14px;
+  color: #999;
+  font-weight: 400;
+  cursor: pointer;
+  height: 30px;
+  line-height: 32px;
+  margin-right: 5px;
+  border-bottom: 2px solid #ffffff;
+
+  &.item_active {
+    font-size: 14px;
+    color: #2E64FA;
+    font-weight: 500;
+    cursor: pointer;
+    border-bottom: 2px solid #2E64FA;
+  }
+}
+
+
+
+.right_set {
+  font-weight: 400;
+  font-size: 14px;
+  color: #333333;
+
+  .el-input {
+    text-align: center;
+    padding: 0 5px;
+    margin: 0 2px;
+  }
+
+}
+
+</style>

+ 36 - 21
src/views/analysis/errorAnalysis.vue

@@ -1,26 +1,41 @@
 <template>
-    <!-- 成绩查询 成绩单 -->
-  <div >
-    
-  </div>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :titleList="['错题分析表']" :showDescribe="false" tableOrChart="table" :showTablePage="false">
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
 </template>
 <script lang="ts" setup>
-import { useExamStore } from '@/store/exam'
-import { useRouter } from 'vue-router'
-import { onMounted ,ref} from 'vue';
-
-// 实例化 Store
-const examStore = useExamStore()
-const router = useRouter()
-
-
-onMounted(() => {
-  
-
-  
-})
+import ReportModule from '@/components/ReportModule.vue';
+import { onMounted, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+onMounted(() => { });
 </script>
- 
-<style lang="scss" scoped>
 
-</style>
+<style lang="scss" scoped></style>

+ 88 - 0
src/views/analysis/groupAnalysis.vue

@@ -0,0 +1,88 @@
+<template>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :showTitle="false" :showDescribe="false" tableOrChart="table">
+    <template #title_left>
+      <el-input v-model="state.keyWord" style="width: 200px" placeholder="请输入学号或姓名" class="input_with">
+        <template #append>
+          <el-button :icon="Search" />
+        </template>
+      </el-input>
+      <span class="count_item">应考:293人</span>
+      <span class="count_item">实考:280人</span>
+      <span class="count_item orange">缺考:13人</span>
+    </template>
+    <template #title_right>
+      <el-checkbox-group class="checkbox_group" v-model="state.checkList">
+        <el-checkbox label="显示分组" value="group" />
+        <el-checkbox label="显示小题" value="question" />
+      </el-checkbox-group>
+    </template>
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { Search } from '@element-plus/icons-vue'
+import { onMounted, reactive, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  keyWord: '',
+  checkList: ['group']
+});
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.input_with {
+  margin-right: 10px;
+}
+
+.count_item {
+  font-weight: 400;
+  font-size: 16px;
+  color: #333333;
+  line-height: 24px;
+  margin-left: 10px;
+
+  &.orange {
+    color: #FB9F34;
+  }
+}
+
+.checkbox_group {
+  :deep(.el-checkbox) {
+    margin-right: 10px;
+
+    &:nth-child(1) {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 92 - 16
src/views/analysis/index.vue

@@ -1,26 +1,102 @@
 <template>
-    <!-- 成绩查询 首页 -->
-  <div >
-    
+  <!-- 成绩查询 首页 -->
+  <div class="page_report_main" ref="mainContent">
+    <div class="page_filter">
+      <FiltersItem :data="filtersData" />
+    </div>
+    <router-view></router-view>
+    <div class="report_bottom">
+      <div class="bottom_no_more">
+        没有更多了,<span @click="GotoPageTop">回到顶部</span>
+      </div>
+    </div>
   </div>
 </template>
 <script lang="ts" setup>
-import { useExamStore } from '@/store/exam'
-import { useRouter } from 'vue-router'
-import { onMounted ,ref} from 'vue';
+import FiltersItem from '@/components/FiltersItem.vue';
+import { onMounted, ref } from "vue";
+// const mainContent = ref(null);
 
-// 实例化 Store
-const examStore = useExamStore()
-const router = useRouter()
+// 1. 定义过滤项中列表项的类型
+interface FilterListItem {
+  label: string
+  value: string
+}
+// 2. 定义单个过滤条件的类型
+interface FilterItem {
+  label: string
+  list: FilterListItem[]
+  value: string
+}
+const filtersData = ref<FilterItem[]>([
+  {
+    label: '班级类型',
+    list: [{
+      label: '行政班',
+      value: '1'
+    }, {
+      label: '教学班',
+      value: '2'
+    }],
+    value: '1',
+  },
+  {
+    label: '班级名称',
+    list: [{
+      label: '年级',
+      value: ''
+    }, {
+      label: '1班',
+      value: ''
+    }],
+    value: '',
+  }
+]);//过滤条件数据
 
-
-onMounted(() => {
-  
-
-  
-})
+onMounted(() => { });
+const GotoPageTop = () => {
+  // mainContent.value.scrollTop = 0;
+  // window.scrollTo({
+  //   top: 0,
+  //   behavior: 'smooth' // 平滑滚动
+  // });
+}
 </script>
- 
+
 <style lang="scss" scoped>
+.report_bottom {
+  width: 100%;
+  height: auto;
+
+  .bottom_no_more {
+    font-size: 14px;
+    color: #666;
+    text-align: center;
+    margin-top: 32px;
+    margin-bottom: 20px;
+
+    span {
+      font-size: 14px;
+      color: #2E64FA;
+      font-weight: 500;
+      cursor: pointer;
+    }
+  }
 
+  .bottom_button {
+    width: 80px;
+    height: 32px;
+    border: 1px solid #2E64FA;
+    border-radius: 4px;
+    color: #2E64FA;
+    font-size: 12px;
+    font-weight: 400;
+    line-height: 32px;
+    text-align: center;
+    margin: auto;
+    margin-top: 20px;
+    margin-bottom: 16px;
+    cursor: pointer;
+  }
+}
 </style>

+ 120 - 0
src/views/analysis/levelDistribution.vue

@@ -0,0 +1,120 @@
+<template>
+  <ReportModule :titleList="['1、分数段图']" tableOrChart="chart" :showPrintBtn="false" :showExportBtn="false">
+    <template #title_right>
+      <div :class="['right_item', { item_active: state.activeIndex == index }]"
+        v-for="(item, index) in state.sortRangeScore" :key="index">
+        {{ item }}分段
+      </div>
+      <div class="right_set">
+        <span>设置分数段</span>
+        <el-input v-model.number="state.scoreInput" maxlength="3" style="width: 54px;" />
+        <span>分/段</span>
+      </div>
+      <div class="right_radio">
+        <el-select style="width:100px;">
+          <el-option :value="2" label="按年级"></el-option>
+          <el-option :value="3" label="按班级"></el-option>
+        </el-select>
+      </div>
+    </template>
+    <template #module_table_chart>
+
+    </template>
+    <template #module_describe>
+      说明:信度是反应考试一致性或可靠性的指标,信度高,表示考试成绩较为准确,误差较小; 信度低,表明误差大;信度低的考试无法正确评价考生的知识水平与智能素质。
+      效度是指测验的有效性或正确性,即测验能否准确测量出其所要测量的内容。效度高的测验能够确保测验内容与测验目的的一致性,反映测验的正确性和准确性。
+      分析试题的难度和区分度可以确保试题的质量和有效性,从而更好地评估学生的知识掌握程度和区分不同水平的学生。
+      难度指试题的难易程度,通常用P值表示。计算方式为P=X/M(P为难度,X为试题平均得分,M为试题满分)。P值在0到1之间,值越大表示试题越简单,试题通常分为容易题(P≥0.7)、中等题(0.4至0.7之间)和难题(P≤0.4)。
+      区分度是衡量试题对不同水平考生的区分能力,通常用D值表示。通过计算高分组和低分组在某一试题上的通过率之差,得到试题区分度。区分度高的试题能将不同水平的考生区分开来,水平高的学生得高分,水平低的学生得低分。D值的取值范围介于-1至1之间,D值越高,区分的效果越好。D≥0.4表明此题的区分度很好,属于优秀;0.3≤D<0.4表明此题的区分度较好,属于良好;0.2≤D<0.4表明此题的区分度一般;D<0.2表明此题的区分度较低。
+      图中展示了各科的命题分析明细,点击科目的柱可在下方查看该科所有小题的命题分析。
+    </template>
+  </ReportModule>
+  <ReportModule :titleList="['2、分数段表']" tableOrChart="table" :showPrintBtn="false" :showDescribe="false">
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { onMounted, reactive } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  activeIndex: -1, // 设置分数段索引  默认第一个
+  sortRangeScore: [5, 10], // 设置分数段
+  scoreInput: "",//输入框的值
+});
+
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.el-input__inner {
+  height: 36px;
+}
+
+.el-input__suffix {
+  line-height: 36px;
+}
+
+.right_item {
+  font-size: 14px;
+  color: #999;
+  font-weight: 400;
+  cursor: pointer;
+  height: 30px;
+  line-height: 32px;
+  margin-right: 5px;
+  border-bottom: 2px solid #ffffff;
+
+  &.item_active {
+    font-size: 14px;
+    color: #2E64FA;
+    font-weight: 500;
+    cursor: pointer;
+    border-bottom: 2px solid #2E64FA;
+  }
+}
+
+
+
+.right_set {
+  font-weight: 400;
+  font-size: 14px;
+  color: #333333;
+
+  .el-input {
+    text-align: center;
+    padding: 0 5px;
+    margin: 0 2px;
+  }
+
+}
+
+.right_radio {}
+</style>

+ 88 - 0
src/views/analysis/optionAnalysis.vue

@@ -0,0 +1,88 @@
+<template>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :showTitle="false" :showDescribe="false" tableOrChart="table">
+    <template #title_left>
+      <el-input v-model="state.keyWord" style="width: 200px" placeholder="请输入学号或姓名" class="input_with">
+        <template #append>
+          <el-button :icon="Search" />
+        </template>
+      </el-input>
+      <span class="count_item">应考:293人</span>
+      <span class="count_item">实考:280人</span>
+      <span class="count_item orange">缺考:13人</span>
+    </template>
+    <template #title_right>
+      <el-checkbox-group class="checkbox_group" v-model="state.checkList">
+        <el-checkbox label="显示分组" value="group" />
+        <el-checkbox label="显示小题" value="question" />
+      </el-checkbox-group>
+    </template>
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { Search } from '@element-plus/icons-vue'
+import { onMounted, reactive, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  keyWord: '',
+  checkList: ['group']
+});
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.input_with {
+  margin-right: 10px;
+}
+
+.count_item {
+  font-weight: 400;
+  font-size: 16px;
+  color: #333333;
+  line-height: 24px;
+  margin-left: 10px;
+
+  &.orange {
+    color: #FB9F34;
+  }
+}
+
+.checkbox_group {
+  :deep(.el-checkbox) {
+    margin-right: 10px;
+
+    &:nth-child(1) {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 88 - 0
src/views/analysis/optionDetail.vue

@@ -0,0 +1,88 @@
+<template>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :showTitle="false" :showDescribe="false" tableOrChart="table">
+    <template #title_left>
+      <el-input v-model="state.keyWord" style="width: 200px" placeholder="请输入学号或姓名" class="input_with">
+        <template #append>
+          <el-button :icon="Search" />
+        </template>
+      </el-input>
+      <span class="count_item">应考:293人</span>
+      <span class="count_item">实考:280人</span>
+      <span class="count_item orange">缺考:13人</span>
+    </template>
+    <template #title_right>
+      <el-checkbox-group class="checkbox_group" v-model="state.checkList">
+        <el-checkbox label="显示分组" value="group" />
+        <el-checkbox label="显示小题" value="question" />
+      </el-checkbox-group>
+    </template>
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { Search } from '@element-plus/icons-vue'
+import { onMounted, reactive, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  keyWord: '',
+  checkList: ['group']
+});
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.input_with {
+  margin-right: 10px;
+}
+
+.count_item {
+  font-weight: 400;
+  font-size: 16px;
+  color: #333333;
+  line-height: 24px;
+  margin-left: 10px;
+
+  &.orange {
+    color: #FB9F34;
+  }
+}
+
+.checkbox_group {
+  :deep(.el-checkbox) {
+    margin-right: 10px;
+
+    &:nth-child(1) {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 88 - 0
src/views/analysis/propositionAnalysis.vue

@@ -0,0 +1,88 @@
+<template>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :showTitle="false" :showDescribe="false" tableOrChart="table">
+    <template #title_left>
+      <el-input v-model="state.keyWord" style="width: 200px" placeholder="请输入学号或姓名" class="input_with">
+        <template #append>
+          <el-button :icon="Search" />
+        </template>
+      </el-input>
+      <span class="count_item">应考:293人</span>
+      <span class="count_item">实考:280人</span>
+      <span class="count_item orange">缺考:13人</span>
+    </template>
+    <template #title_right>
+      <el-checkbox-group class="checkbox_group" v-model="state.checkList">
+        <el-checkbox label="显示分组" value="group" />
+        <el-checkbox label="显示小题" value="question" />
+      </el-checkbox-group>
+    </template>
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { Search } from '@element-plus/icons-vue'
+import { onMounted, reactive, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  keyWord: '',
+  checkList: ['group']
+});
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.input_with {
+  margin-right: 10px;
+}
+
+.count_item {
+  font-weight: 400;
+  font-size: 16px;
+  color: #333333;
+  line-height: 24px;
+  margin-left: 10px;
+
+  &.orange {
+    color: #FB9F34;
+  }
+}
+
+.checkbox_group {
+  :deep(.el-checkbox) {
+    margin-right: 10px;
+
+    &:nth-child(1) {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 88 - 0
src/views/analysis/questionAnalysis.vue

@@ -0,0 +1,88 @@
+<template>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :showTitle="false" :showDescribe="false" tableOrChart="table">
+    <template #title_left>
+      <el-input v-model="state.keyWord" style="width: 200px" placeholder="请输入学号或姓名" class="input_with">
+        <template #append>
+          <el-button :icon="Search" />
+        </template>
+      </el-input>
+      <span class="count_item">应考:293人</span>
+      <span class="count_item">实考:280人</span>
+      <span class="count_item orange">缺考:13人</span>
+    </template>
+    <template #title_right>
+      <el-checkbox-group class="checkbox_group" v-model="state.checkList">
+        <el-checkbox label="显示分组" value="group" />
+        <el-checkbox label="显示小题" value="question" />
+      </el-checkbox-group>
+    </template>
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
+</template>
+<script lang="ts" setup>
+import ReportModule from '@/components/ReportModule.vue';
+import { Search } from '@element-plus/icons-vue'
+import { onMounted, reactive, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  keyWord: '',
+  checkList: ['group']
+});
+onMounted(() => { });
+</script>
+
+<style lang="scss" scoped>
+.input_with {
+  margin-right: 10px;
+}
+
+.count_item {
+  font-weight: 400;
+  font-size: 16px;
+  color: #333333;
+  line-height: 24px;
+  margin-left: 10px;
+
+  &.orange {
+    color: #FB9F34;
+  }
+}
+
+.checkbox_group {
+  :deep(.el-checkbox) {
+    margin-right: 10px;
+
+    &:nth-child(1) {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 80 - 18
src/views/analysis/score.vue

@@ -1,26 +1,88 @@
 <template>
-    <!-- 成绩查询 成绩单 -->
-  <div >
-    
-  </div>
+  <!-- 成绩查询 成绩单 -->
+  <ReportModule :showTitle="false" :showDescribe="false" tableOrChart="table">
+    <template #title_left>
+      <el-input v-model="state.keyWord" style="width: 200px" placeholder="请输入学号或姓名" class="input_with">
+        <template #append>
+          <el-button :icon="Search" />
+        </template>
+      </el-input>
+      <span class="count_item">应考:293人</span>
+      <span class="count_item">实考:280人</span>
+      <span class="count_item orange">缺考:13人</span>
+    </template>
+    <template #title_right>
+      <el-checkbox-group class="checkbox_group" v-model="state.checkList">
+        <el-checkbox label="显示分组" value="group" />
+        <el-checkbox label="显示小题" value="question" />
+      </el-checkbox-group>
+    </template>
+    <template #module_table_chart>
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="date" label="Date" width="180" />
+        <el-table-column prop="name" label="Name" width="180" />
+        <el-table-column prop="address" label="Address" />
+      </el-table>
+    </template>
+  </ReportModule>
 </template>
 <script lang="ts" setup>
-import { useExamStore } from '@/store/exam'
-import { useRouter } from 'vue-router'
-import { onMounted ,ref} from 'vue';
+import ReportModule from '@/components/ReportModule.vue';
+import { Search } from '@element-plus/icons-vue'
+import { onMounted, reactive, ref } from "vue";
+const tableData = [
+  {
+    date: '2016-05-03',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-02',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-04',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+  {
+    date: '2016-05-01',
+    name: 'Tom',
+    address: 'No. 189, Grove St, Los Angeles',
+  },
+]
+const state = reactive({
+  keyWord: '',
+  checkList: ['group']
+});
+onMounted(() => { });
+</script>
 
-// 实例化 Store
-const examStore = useExamStore()
-const router = useRouter()
+<style lang="scss" scoped>
+.input_with {
+  margin-right: 10px;
+}
 
+.count_item {
+  font-weight: 400;
+  font-size: 16px;
+  color: #333333;
+  line-height: 24px;
+  margin-left: 10px;
 
-onMounted(() => {
-  
+  &.orange {
+    color: #FB9F34;
+  }
+}
 
-  
-})
-</script>
- 
-<style lang="scss" scoped>
+.checkbox_group {
+  :deep(.el-checkbox) {
+    margin-right: 10px;
 
-</style>
+    &:nth-child(1) {
+      margin-right: 20px;
+    }
+  }
+}
+</style>

+ 9 - 9
src/views/exam/components/stepItem.vue

@@ -74,15 +74,15 @@ const menuList = computed(() => {
       { name: '扫描学生', number: '2', path: 'scanList', desc: '扫描学生,处理扫描异常学生等', status: 0 },
       { name: '成绩查询', number: '3', path: 'analysis', desc: '设置每个主观题下的划分区信息及位置', status: 0 ,
         menu:[
-          { name: '成绩单', path: 'score' },
-          { name: '错题分析', path: 'errorAnalysis' },
-          { name: '选项明细', path: 'optionDetail' },
-          { name: '水平分布', path: 'levelDistribution' },
-          { name: '班级对比', path: 'classComparison' },
-          { name: '小题分析', path: 'questionAnalysis' },
-          { name: '分组分析', path: 'groupAnalysis' },
-          { name: '选项分析', path: 'optionAnalysis' },
-          { name: '命题分析', path: 'propositionAnalysis' },
+          { name: '成绩单',number: '4', path: 'score' },
+          { name: '错题分析',number: '5', path: 'errorAnalysis' },
+          { name: '选项明细',number: '6', path: 'optionDetail' },
+          { name: '水平分布',number: '7', path: 'levelDistribution' },
+          { name: '班级对比',number: '8', path: 'classComparison' },
+          { name: '小题分析',number: '9', path: 'questionAnalysis' },
+          { name: '分组分析',number: '10', path: 'groupAnalysis' },
+          { name: '选项分析',number: '11', path: 'optionAnalysis' },
+          { name: '命题分析',number: '12', path: 'propositionAnalysis' },
         ]
       },
     ];