Bläddra i källkod

未扫描 列表更新

dengshaobo 3 veckor sedan
förälder
incheckning
0a79d6aa1e

+ 8 - 0
src/api/exam.ts

@@ -235,6 +235,14 @@ export const getBatchDetailImage= (data:any):Promise<ApiResponse> => {
   })
 }
 
+//扫描学生 获取未扫描 缺考 已上传的学生列表数据
+export const getExamStudentList= (data:any):Promise<ApiResponse> => { 
+  return request({
+    url: '/api/v1/ai_exam_scan/find_stu_by_condition',
+    method: 'get',
+    params: data 
+  })
+}
 
 
 

+ 22 - 1
src/store/exam.ts

@@ -33,6 +33,22 @@ export const useExamStore = defineStore('exam', () => {
             localStorage.removeItem('current_exam_info')
         }
     }
+    const unScanned=ref(0);//未扫描
+    const examMissNum=ref(0);//缺考人数
+    const abnormalNum=ref(0);//异常人数
+    const scannedNum=ref(0);//已上传人数
+
+    const setExamInfoCount = (info: any) => {
+
+        unScanned.value = info.unScanned;
+        examMissNum.value = info.examMissNum;
+        abnormalNum.value = info.abnormalNum;
+        scannedNum.value = info.scannedNum;
+        localStorage.setItem('current_exam_info_count', JSON.stringify(info));//当前考试异常数据信息
+    }
+
+
+
 
     // 清空考试信息
     const clearExamInfo = () => {
@@ -46,6 +62,11 @@ export const useExamStore = defineStore('exam', () => {
     examName,
     examType,
     setExamInfo,
-    clearExamInfo
+    clearExamInfo,
+    setExamInfoCount,
+    unScanned,
+    examMissNum,
+    abnormalNum,
+    scannedNum
   }
 })

+ 246 - 40
src/styles/common.scss

@@ -135,6 +135,80 @@ body {
   /* 不设置 font-family,浏览器使用默认字体 */
 }
 
+//左右切换按钮样式
+.right_user_tab {
+  width: calc(100% - 40px);
+  margin: auto;
+  display: flex;
+  margin-top: 20px;
+
+  .tab_system_user {
+    width: 50%;
+    height: 34px;
+    line-height: 34px;
+    text-align: center;
+    border-radius: 4px 0px 0px 4px;
+    cursor: pointer;
+    border: 1px solid #bbbbbb;
+    font-weight: 400;
+    font-size: 16px;
+    color: #bbbbbb;
+    cursor: pointer;
+  }
+
+  .tab_temporay_user {
+    width: 50%;
+    height: 34px;
+    border-radius: 0px 4px 4px 0px;
+    line-height: 34px;
+    text-align: center;
+
+    border: 1px solid #bbbbbb;
+    font-weight: 400;
+    font-size: 16px;
+    color: #bbbbbb;
+    cursor: pointer;
+  }
+
+  .select_cur {
+    background: #2e64fa;
+    font-weight: 400;
+    font-size: 16px;
+    color: #ffffff;
+    cursor: pointer;
+    border: 1px solid #2e64fa;
+  }
+}
+
+//下划线版本
+.right_tab_underline {
+  width: 100%;
+  height: 44px;
+  display: flex;
+  justify-content: space-between;
+
+  .tab_item {
+    width: 50%;
+    height: 44px;
+    text-align: center;
+    line-height: 44px;
+    font-weight: 400;
+    font-size: 14px;
+    color: #666666;
+    border-bottom: 2px solid #fff;
+    cursor: pointer;
+  }
+
+  .tab_item_cur {
+    width: 50%;
+    height: 44px;
+    font-weight: 500;
+    font-size: 14px;
+    color: #2E64FA;
+    border-bottom: 2px solid #2E64FA;
+  }
+}
+
 
 .page_tree {
   width: 100%;
@@ -148,7 +222,9 @@ body {
     color: #2e64fa !important;
     border-radius: 4px;
     padding: 5px 4px;
-    .el-icon-caret-right {
+    height: 36px;
+    // 选中时的样式
+    .el-tree-node__expand-icon {
       color: #2e64fa !important;
     }
   }
@@ -165,6 +241,7 @@ body {
   }
   .el-tree-node .el-tree-node__content {
     padding: 5px 4px;
+    height: 36px;
   }
 }
 //通用间隔
@@ -395,6 +472,10 @@ body {
   justify-content: flex-end;
   align-items: center;
 
+  .el-pagination .el-select
+  {
+    width: 120px;
+  }
   .el-pagination {
     padding: 0 !important;
     display: flex;
@@ -2897,6 +2978,7 @@ body {
 }
 
 // 使用element-ui按钮后的 公共按钮样式  导入 导出  其他等等可追加
+
 .el_button {
   .el-button .is-disabled {
     background-color: #f5f7fa;
@@ -2906,11 +2988,28 @@ body {
     background-color: red !important;
   }
 
+  .ratio_input
+  {
+   
+      height: 34px !important;
+      line-height: 34px !important;
+    
+  }
+
+
   .el-button {
-    min-width: 72px;
+    min-width: 78px;
     width: auto;
     height: 36px;
-    padding: 0 !important;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    padding: 10 !important;
+    font-weight: 400;
+
+    .icon_shuaxin {
+      margin-right: 5px;
+    }
   }
 
   //导出
@@ -2920,7 +3019,7 @@ body {
     font-weight: 400;
     font-size: 14px;
     color: #666666;
-    text-indent: 20px;
+    text-indent: 10px;
 
     background-image: url("../assets/icon/exam_exports.png");
     background-repeat: no-repeat;
@@ -2943,7 +3042,7 @@ body {
     font-size: 14px;
     color: #666666;
     margin-left: 10px;
-    text-indent: 20px;
+    text-indent: 10px;
     background-image: url("../assets/icon/exam_imports.png");
     background-repeat: no-repeat;
     background-size: 16px 16px;
@@ -2979,12 +3078,11 @@ body {
     font-weight: 400;
     font-size: 14px;
     color: #666666;
-    text-indent: 20px;
+    line-height: 34px;
+    padding: 0 !important;
+
+
 
-    background-image: url("../assets/icon/refresh_default.png");
-    background-repeat: no-repeat;
-    background-size: 16px 16px;
-    background-position: 10px 50%;
     cursor: pointer;
   }
 
@@ -3009,7 +3107,7 @@ body {
 
   // 删除
   .delete_btn {
-    width: 96px;
+    width: 76px;
     height: 36px !important;
     font-weight: 400;
     font-size: 14px;
@@ -3017,7 +3115,19 @@ body {
     text-align: center;
     border: 1px solid #f56c6c;
     cursor: pointer;
-    margin-left: 20px;
+
+  }
+
+  .delete_btn_disable {
+    width: 76px;
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #c0c4cc;
+    cursor: not-allowed;
+    background-image: none;
+    background-color: #ffffff;
+    border-color: #ebeef5;
   }
 
   // 编辑
@@ -3035,7 +3145,7 @@ body {
 
   //标记为正常
   .marke_normal_btn {
-    width: 96px;
+    width: 90px;
     height: 36px !important;
     font-weight: 400;
     font-size: 14px;
@@ -3043,12 +3153,36 @@ body {
     text-align: center;
     border: 1px solid #2e64fa;
     cursor: pointer;
-    margin-left: 20px;
   }
 
   //标记为正常 禁用
   .marke_normal_btn_disable {
-    width: 110px;
+    width: 90px;
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #c0c4cc;
+    cursor: not-allowed;
+    background-image: none;
+    background-color: #ffffff;
+    border-color: #ebeef5;
+  }
+
+  //标记为异常
+  .marke_anomaly_btn {
+    width: 90px;
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #F56C6C;
+    text-align: center;
+    border: 1px solid #F56C6C;
+    cursor: pointer;
+  }
+
+  //标记为正常 禁用
+  .marke_anomaly_btn_disable {
+    width: 90px;
     height: 36px !important;
     font-weight: 400;
     font-size: 14px;
@@ -3057,12 +3191,35 @@ body {
     background-image: none;
     background-color: #ffffff;
     border-color: #ebeef5;
-    margin-left: 20px;
   }
 
   // 标记为缺考
   .marke_miss_exam_btn {
-    width: 110px;
+    width: 90px;
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #2e64fa;
+    text-align: center;
+    border: 1px solid #2e64fa;
+    cursor: pointer;
+  }
+
+  .marke_miss_exam_btn_gray {
+    width: 90px;
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #C0C4CC;
+    box-sizing: border-box;
+    text-align: center;
+    border: 1px solid #EBEEF5;
+    cursor: pointer;
+  }
+
+  //重新切割
+  .re_cut_btn_100 {
+    width: 100%;
     height: 36px !important;
     font-weight: 400;
     font-size: 14px;
@@ -3070,7 +3227,6 @@ body {
     text-align: center;
     border: 1px solid #2e64fa;
     cursor: pointer;
-    margin-left: 20px;
   }
 
   //重新切割
@@ -3109,6 +3265,27 @@ body {
     cursor: pointer;
   }
 
+  .delete_paper_btn:hover {
+    background-color: #f56c6c30;
+  }
+
+
+  .delete_paper_btn_100 {
+    width: calc(100% - 40px);
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #f56c6c;
+    text-align: center;
+    border: 1px solid #f56c6c;
+    cursor: pointer;
+    margin: auto;
+  }
+
+  .delete_paper_btn_100:hover {
+    background-color: #f56c6c30;
+  }
+
   // 回收站
   .recycle_bin_btn {
     width: calc(100% - 40px);
@@ -3160,49 +3337,79 @@ body {
 
   //重新导入名单
   .other_btn {
-    width: 120px !important;
+    // width: 120px !important;
+    width: auto;
     height: 36px !important;
     border-radius: 4px 4px 4px 4px;
     border: 1px solid #dcdfe6;
     font-weight: 400;
     font-size: 14px;
     color: #666666;
+    padding: 0 10px !important;
   }
 
 
   //通用蓝色无背景编辑按钮
-  .editor_item
-  {
-    width: 96px;
+  .editor_item {
+    width: auto;
     height: 36px !important;
+    line-height: 36px;
     font-weight: 400;
     font-size: 14px;
     color: #2E64FA;
     text-align: center;
     border: 1px solid #2E64FA;
     cursor: pointer;
+    box-sizing: border-box;
+    padding: 0px 10px;
+    border-radius: 4px;
   }
-  .editor_item:hover
-  {
-    background: rgba(46,100,250,0.1);
+
+  .editor_item:hover {
+    background: rgba(46, 100, 250, 0.1);
     color: #2E64FA;
     border: 1px solid #2E64FA;
   }
+
+  //通用灰色无背景按钮
+  .normal_item {
+    width: auto;
+    height: 36px !important;
+    font-weight: 400;
+    font-size: 14px;
+    color: #666;
+    text-align: center;
+    border: 1px solid #DCDFE6;
+    cursor: pointer;
+    box-sizing: border-box;
+    padding: 0px 10px;
+  }
+
+  .normal_item:hover {
+    background: #DCDFE620;
+    color: #333;
+    border: 1px solid #DCDFE6;
+  }
+
   // 通用红色无背景删除
-  .delete_item 
-  {
-    width: 96px;
+  .delete_item {
+    width: auto;
+    // max-width: 78px;
     height: 36px !important;
+    line-height: 36px;
     font-weight: 400;
     font-size: 14px;
     color: #f56c6c;
     text-align: center;
     border: 1px solid #f56c6c;
     cursor: pointer;
+    box-sizing: border-box;
+    padding: 0px 10px;
+    border-radius: 4px;
   }
-  .delete_item:hover 
-  {
-    background: rgba(245,108,108,0.1);
+
+  .delete_item:hover {
+    background: rgba(245, 108, 108, 0.1);
     color: #f56c6c;
     border: 1px solid #f56c6c;
   }
@@ -3211,7 +3418,6 @@ body {
 
 
 
-
 .pic_item_list {
   width: 100%;
 
@@ -3650,9 +3856,9 @@ body {
             border-radius: 10px;
 
             .left_tree {
-            width: calc(100% - 40px);
-            height: calc(100% - 96px);
-            margin: auto;
+              width: calc(100% - 40px);
+              height: calc(100% - 96px);
+              margin: auto;
 
             .kc_list {
                 height: auto;
@@ -3780,11 +3986,11 @@ body {
             }
 
             .rights_right {
-            width: 360px;
-            height: 100%;
-            background-color: #ffffff;
-            border-radius: 10px;
-            position: relative;
+              width: 360px;
+              height: 100%;
+              background-color: #ffffff;
+              border-radius: 10px;
+              position: relative;
             }
 
             .right_title {

+ 10 - 0
src/styles/element.scss

@@ -168,4 +168,14 @@ button:focus, button:focus-visible {
 .el-dialog.is-fullscreen
 {
   padding: 0 !important;
+}
+
+//加载loading文案样式覆盖
+.el-loading-spinner .el-loading-text
+{
+  color: #2E64FA;
+}
+.el-loading-spinner
+{
+  top:40% !important;
 }

+ 201 - 20
src/views/exam/abnormal/tableList.vue

@@ -13,16 +13,16 @@
         </div>
         <div class="right_user_tab" v-else>
             <!-- 按考场 1  按班级 2 -->
-            <div class="tab_system_user" :class="activeName == 1?'select_cur':''" @click="OnExam(1)" >
+            <div class="tab_system_user" :class="activeName == 1?'select_cur':''" @click="ChangeRoomType(1)" >
                 按考场
             </div>
-            <div class="tab_temporay_user" :class="activeName == 2?'select_cur':''" @click="OnClass(2)">
+            <div class="tab_temporay_user" :class="activeName == 2?'select_cur':''" @click="ChangeRoomType(2)">
                 按班级
             </div>
         </div>
         <div class="page_jg_20"></div>
         <div class="left_tree page_tree" v-if="markType==0 || showUploadReview==0">
-            <el-tree  :highlight-current="true" :data="treeData" default-expand-all :props="defaultProps" :default-expanded-keys="defaultExKey" node-key="id" ref="classTree" @node-click="TreeHandleNodeClick"></el-tree>
+            <el-tree  :highlight-current="true" class="filter-tree" :data="treeData" default-expand-all :props="defaultProps" :default-expanded-keys="defaultExKey" node-key="id" ref="classTree" @node-click="TreeHandleNodeClick"></el-tree>
 
         </div>
         <div v-else class="left_question">
@@ -62,13 +62,13 @@
                 <el-table-column align="center" type="index" width="50" label="序号" :index="HandleIndexMethod"></el-table-column>
                 <el-table-column align="center" prop="studentBatch" label="扫描批次" v-if="scanState == 3"></el-table-column>  
                 <el-table-column align="center" prop="studentCode" label="学号"></el-table-column>
-                <el-table-column align="center" prop="exCode" label="考号"></el-table-column>
+                <el-table-column align="center" prop="examCode" label="考号"></el-table-column>
                 <el-table-column align="center" prop="studentName" label="姓名"></el-table-column>
                 <el-table-column align="center" prop="adminClassName" label="行政班"></el-table-column>
                 <el-table-column align="center" prop="teachingClassName" label="教学班"></el-table-column>
                 <el-table-column align="center" prop="registrationTypeName" label="学生类型"></el-table-column>
                 <el-table-column align="center"  label="考场">
-                    <template slot-scope="scope">
+                    <template #default="scope">
                         <!-- 提的bug  沒没有考场显示行政班 -->
                         <span v-if="scope.row.examRoomName">{{scope.row.examRoomName}}</span>
                         <span v-else>{{scope.row.adminClassName}}</span>
@@ -76,7 +76,7 @@
                     </template>
                 </el-table-column>
                 <el-table-column align="center"  label="填涂标记" v-if="scanState==2">
-                    <template slot-scope="scope">
+                    <template #default="scope">
                         
                         <div class="miss_img" v-if="scope.row.paperUrl">
                         <img :src="scope.row.paperUrl"  alt="">
@@ -85,7 +85,7 @@
                     </template>
                 </el-table-column>
                 <el-table-column align="center" prop="scannedStatus" label="状态" key="scannedStatus">
-                    <template v-slot="scope">
+                    <template #default="scope">
                         <div class="table_row_scan_state" v-if="scanState == 0">
                             <div class="state_no_scan"></div>未扫描
                         </div>
@@ -100,7 +100,7 @@
                 
                 
                 <el-table-column align="center" label="操作" width="160" >
-                    <template v-slot="scope">
+                    <template #default="scope">
                             <!-- 未扫描 -->
                         <div class="table_row_option" v-if="scanState == 0">
                             <span class="option_button_editor" @click="OpenMissExam(scope)">标记为缺考</span>
@@ -124,7 +124,7 @@
                     @current-change="ChangePage"
                     background
                     
-                    :page-sizes="[20,50,100]"
+                    :page-sizes="[10,50,100]"
                     layout="sizes,prev, pager, next"
                     @size-change="HandleSizeChange"
                     :current-page="pageInfo.pageNum"
@@ -220,7 +220,7 @@
                     </div>
                     <div class="item_image">
                         <!-- <img :src="item.url" alt=""> -->
-                        <MarkScore :drawData="reviewQuestionScoreList" :fullScore="reviewQuestionScore" :score="item.score" :paperImgUrl="item.url" @GetClickItem="(score) => GetClickItem(score,item, index)"></MarkScore>
+                        <!-- <MarkScore :drawData="reviewQuestionScoreList" :fullScore="reviewQuestionScore" :score="item.score" :paperImgUrl="item.url" @GetClickItem="(score) => GetClickItem(score,item, index)"></MarkScore> -->
                     </div>
                 </div>
             </div>
@@ -320,11 +320,14 @@
 </template>
 <script lang="ts" setup>
 import { useExamStore } from '@/store/exam'
+import { useUserStore } from '@/store/user'
 import { useRouter } from 'vue-router'
-import { onMounted ,ref} from 'vue';
+import { onMounted ,ref,nextTick,onUnmounted,computed, watch} from 'vue';
+import { getExamStudentList } from '@/api/exam';
 
 // 实例化 Store
 const examStore = useExamStore()
+const userStore = useUserStore()
 const router = useRouter()
 
 // 定义 Props
@@ -348,23 +351,83 @@ const props = defineProps({
   }, // 答案
 })
 
+//监听props变化
+watch(() => props.scanState, (newState) => {
+
+    console.log("扫描状态变更为",newState);
+    pageInfo.value.pageNum=1;
+    GetExamStudentList();//获取考生列表
+});
+
+// 考试科目 ID
+const examSubjectId = computed(() => {
+  return examStore.currentExam?.id
+})//计算属性
+
+//考试科目code
+const examSubjectCode=computed(() => {
+    return examStore.currentExam?.examSubjectCode
+})
+//当前登录人姓名
+const currentUserName=computed(() => {
+    return userStore.userName;
+})
+
 const showUploadReview = ref(0)//0 考生详情  1 复查识别
 const showReviewType=ref(0);//复查题目类型 0-客观题 1-主观题
 
 const activeName = ref(1);//1 按考场 2 按班级
 const markType=ref(0)//0 网阅卡 1 手阅卡
 const reviewQuestionIndex=ref('');//当前选择的题目索引
-const treeData=ref([]);//树形结构数据
+
+// 修改后:显式声明类型为 any[],或者定义具体的 Interface
+interface TreeNode {
+  id: string | number;
+  label: string;
+  children?: TreeNode[];
+  studentList?: any[];
+  [key: string]: any; // 允许其他属性
+}
+
+const treeData = ref<TreeNode[]>([]); // 树形结构数据
+const defaultExKey=ref(['all']);//
+const selectNodeId=ref('all');//选择的节点id
+const defaultProps={
+    children: 'children',
+    label: 'label'
+};
 
 const keyWord=ref('');//搜索关键词
 const reviewKeyWord=ref('');//复查搜索关键词
 
 const multiSelection=ref([]);//多选数据
 const isLoading=ref(false);//表格加载状态
-const studentTableData=ref([]);//学生表格数据
-const pageInfo=ref({ pageNum: 1, pageSize: 20, total: 0 });//分页信息
+// 学生表格数据(前端分页处理)
+const studentTableData = computed(() => {
+
+  if(keyWord.value=='')
+  {
+    const start = (pageInfo.value.pageNum - 1) * pageInfo.value.pageSize;
+    const end = start + pageInfo.value.pageSize;
+    return studentList.value.slice(start, end);
+  }
+  else
+  {
+    return studentList.value.filter(student=>{
+        return (
+            student.studentName.toLowerCase().includes(keyWord.value.toLowerCase()) 
+            ||
+            student.exCode.toLowerCase().includes(keyWord.value.toLowerCase())
+        );
+    })
+  }
+  
+});
+
+const pageInfo=ref({ pageNum: 1, pageSize: 10, total: 0 });//分页信息
 const studentPaperList=ref([]);//学生试卷列表
-const studentList=ref([]);//学生列表数据
+const allStudentList=ref([]);//所有学生列表数据存储
+const studentList=ref<any[]>([]);//学生列表数据
 
 const reviewObjectClassCode=ref('');//班级代码
 const reviewObjectClassList=ref([]);//班级列表
@@ -378,18 +441,46 @@ const scoreOptions=ref([]);//分数选项
 const reviewLoading=ref(false);//复查加载状态
 
 const reviewStudentList=ref([]);//复查学生列表
+const tableHeight=ref(200);//学生表格高度
 const subjectReviewTableHeight=ref(200);//主观题复查表格高度
 const tableKey=ref(0);//表格key
 
+
+const SelectCheckAll=()=>{
+
+}
+const HandleSelectionChange=(selection:any)=>{
+    
+}
+
+const TreeHandleNodeClick=(node:any)=>{
+
+}
+
+
+
+const ChangeUploadShow=(show:number)=>{
+    showUploadReview.value=show
+}
+
+const ChangeRoomType=(type:number)=>{
+    activeName.value=type
+    GetExamStudentList();
+}
+
+const ChangeReviewType=(type:number)=>{
+    showReviewType.value=type
+}
+
 //切换分页
 const ChangePage=(pageNum:number)=>{
-    
+    pageInfo.value.pageNum=pageNum;
 }
 
 
 //设置每页显示数量
 const HandleSizeChange=(size:number)=>{
-
+    pageInfo.value.pageSize=size;
 }
 //序号自定义方法
 const HandleIndexMethod=(index:number)=>{
@@ -400,6 +491,86 @@ const HandleIndexMethod=(index:number)=>{
     }
 }
 
+//获取学生列表
+const GetExamStudentList=async()=>{
+    isLoading.value=true
+    const params={
+        examSubjectId:examSubjectId.value,
+        type:activeName.value,
+        scannedStatus:props.scanState,
+        review:0,
+        schoolId:0,
+    };
+    let res=await getExamStudentList(params)
+    console.log("打印获取的扫描学生结果",res)
+    isLoading.value=false
+    if(res.code==200)
+    {
+       let childrenData:any[]=[];
+       let allDatalist:any[]=[];   //全部学生列表
+       let examInfoCount={
+            unScanned:res.data.unScanned,
+            examMissNum:res.data.examMissNum,
+            scannedNum:res.data.scannedNum,
+            abnormalNum:res.data.abnormalNum,
+            examTotal:res.data.totalNum,
+        };
+        examStore.setExamInfoCount(examInfoCount);//设置扫描数据信息
+       if(res.data.examRoomTypeTblVOS?.length>0)
+        {
+            res.data.examRoomTypeTblVOS.forEach((item:any)=> {
+                let obj={
+                    id:'index_'+item.examRoomCode, //考场id    
+                    label:item.examRoomName+'('+item.totalStudentNum+'人)', //考场名称
+                    studentList:item.scannedStudentTblVOS || [],//学生列表
+
+                };
+                allDatalist.push(...item.scannedStudentTblVOS);
+                childrenData.push(obj);
+            });
+            reviewObjectClassList.value=res.data.examRoomTypeTblVOS || [];
+        }
+        let oneTreeData={
+            id:'all',
+            label:'全部'+'('+allDatalist.length+'人)',
+            children:childrenData,
+            studentList:allDatalist,
+        };
+        treeData.value=[oneTreeData];
+        if(selectNodeId.value=='all')
+        {
+            studentList.value=allDatalist;
+            pageInfo.value.total=allDatalist.length;
+        }
+        else
+        {
+
+        }
+        console.log("打印获取的树形结构数据",treeData.value)
+
+    }
+}
+
+
+
+//计算高度的函数
+const CalculateTableHeight = () => {
+  // nextTick 确保 DOM 更新后再获取尺寸
+  nextTick(() => {
+    // window.innerHeight 是浏览器可视区域高度
+
+    // 简单算法:视窗高度 - 固定占用高度
+    let computedHeight = window.innerHeight - 270;
+    
+    // 限制最小高度,防止太矮
+    if(computedHeight < 200) 
+    {
+      computedHeight = 200;
+    }
+
+    tableHeight.value = computedHeight;
+  });
+}; 
 
 
 onMounted(() => {
@@ -408,11 +579,21 @@ onMounted(() => {
         console.warn('当前没有选中的考试信息')
         // 可选:如果没有数据,可以重定向回列表页或提示用户
     }
-    
-  
+    CalculateTableHeight()//计算表格高度
+    GetExamStudentList();
+    // 监听窗口大小变化
+    window.addEventListener('resize', CalculateTableHeight);
 })
+// 卸载时移除监听,防止内存泄漏
+onUnmounted(() => {
+  window.removeEventListener('resize', CalculateTableHeight);
+});
+
 </script>
  
 <style lang="scss" scoped>
-
+.content_main
+{
+    height: 100% !important;
+}
 </style>

+ 23 - 148
src/views/exam/abnormalDetail.vue

@@ -8,16 +8,16 @@
                 <div class="scan_button_list">
                     <!-- 状态  0  未扫描  1 已上传 2  缺考  3 异常 -->
                     <div class="button_item item_no_scan"  :class="scanState==0?'item_no_scan_active':''" @click="ScanStateChange(0)">
-                        未扫描({{scanDataInfo.unScanned}}人)
+                        未扫描({{unScanned}}人)
                     </div>
                     <div class="button_item item_miss_exam"  :class="scanState==2?'item_miss_exam_active':''" @click="ScanStateChange(2)">
-                        缺考({{ scanDataInfo.examMissNum }}人)
+                        缺考({{ examMissNum }}人)
                     </div>
                     <div class="button_item item_abnormal"  :class="scanState==3?'item_abnormal_active':''" @click="ScanStateChange(3)">
-                        异常({{ scanDataInfo.abnormalNum }}份)
+                        异常({{ abnormalNum }}份)
                     </div>
                     <div class="button_item item_sucess_upload"  :class="scanState==1?'item_sucess_upload_active':''" @click="ScanStateChange(1)">
-                        已上传({{ scanDataInfo.scannedNum }}人)
+                        已上传({{ scannedNum }}人)
                     </div>
                 </div>
             </div>
@@ -25,7 +25,7 @@
                 <!-- 异常 -->
                 <!-- <Abnormal v-if="scanState == 3"></Abnormal> -->
                 <!-- 状态  0  未扫描  1 已上传 2  缺考  3 异常 -->
-                <TableList ></TableList>
+                <TableList :scanState="scanState"></TableList>
             </div>
         </div>
 
@@ -73,10 +73,22 @@ const examSubjectId = computed(() => {
 const examSubjectCode=computed(() => {
     return examStore.currentExam?.examSubjectCode
 })
-//当前登录人姓名
-const currentUserName=computed(() => {
-    return userStore.userName;
+//未扫描
+const unScanned=computed(() => {
+    return examStore.unScanned;
 })
+const examMissNum=computed(() => {
+    return examStore.examMissNum;
+})
+const abnormalNum=computed(() => {
+    return examStore.abnormalNum;
+})
+const scannedNum=computed(() => {
+    return examStore.scannedNum;
+})
+
+
+
 
 const selectSchoolId=ref(0);//学校ID
 
@@ -96,20 +108,7 @@ const baseUrl=import.meta.env.VITE_API_BASE_URL;
 const uploadUrl=`https://dev3.k12100.net/teaching/api/v1/ai_exam_scan/upload_multi_img`;//图片上传地址
 
 
-//  定义数据类型接口
-interface BatchItem {
-  id?: string | number;
-  batchNo: string;
-  batchTypeName?: string;
-  scanUserName?: string;
-  scannedPaperNum?: number;
-  scannedTime?: number | string;
-  uploadNum?: number;
-  uploadStatus?: number; // 确保包含此属性
-  failedNumber?: number;
-  [key: string]: any; // 允许其他动态属性
-}
-const tableData=ref<BatchItem[]>([]); //批次列表
+
 const tableHeight=ref(500);
 const scanIdentifyList=[                
     {
@@ -135,113 +134,13 @@ const scanDataInfo=ref({
 
 });//扫描返回的数据信息
 
-//扫描进度  
-const scanProcess=computed(() => {
 
-    return Math.floor((scanDataInfo.value.scannedNum+scanDataInfo.value.examMissNum)/scanDataInfo.value.examTotal)*100;
-});
-
-//缺考进度
-const scanQuekao=computed(() => {
-    return Math.floor((scanDataInfo.value.examMissNum)/scanDataInfo.value.examTotal)*100;
-});
-//异常进度
-const scanYichang=computed(() => {
-    
-    return Math.floor((scanDataInfo.value.abnormalNum)/scanDataInfo.value.examTotal)*100;
-});
-//刷新
-const Refresh = () => {
-    tableData.value=[];
-    GetScanBatchList();
-}
 
 const ScanStateChange=(state:number)=>{
     scanState.value=state;
 }
-//重新识别弹窗
-const OpenReIdentify=() => {
 
-}
 
-//开始扫描
-const OpenScan = () => {
-
-    if(isScanning.value)
-    {
-        //正在扫描
-        ElMessage.warning('正在扫描中,请勿重复点击哦!');
-        return;
-    }
-
-    //判断客户端是否已经连接
-    if(scanClientStates.value)
-    {
-        //一打开客户端 
-        console.log('客户端已打开,开始扫描');
-        // isScanning.value=true;//扫描状态
-        const params={
-            examSubjectId:examSubjectId.value,
-            schoolId:selectSchoolId.value,
-        };
-        getCurrentBatchNo(params).then((res:any)=>{
-            console.log("当前获取批次结果",res);
-            if(res.code==200)
-            {
-                currentBatchNo.value=res.data.batchNo;
-                currentBatchNoId.value=res.data.id;
-                let newData={
-                    batchNo:currentBatchNo.value,
-                    id:currentBatchNoId.value,//批次号
-                    batchTypeName:'扫描',
-                    scanUserName:currentUserName.value,
-                    scannedPaperNum:0,//扫描张数
-                    scannedTime:Date.now(),//扫描时间
-                    uploadNum:0,//上传张数
-                    uploadStatus:0,//扫描状态
-                };
-                tableData.value.push(newData);
-                //开始扫描
-                let jsonParam={
-                    examSubjectId:examSubjectId.value,
-                    batchNumber:currentBatchNo.value,
-                    // sensitive: 35,//灵敏度参数 固定35
-                    filter:0,//是否过滤参数 1-是 0-否
-                    // heightRatio:this.heightRatio,//占打分框高度比例
-                    schoolId:selectSchoolId.value//学校id  联校单校都需要学校id
-                };
-                let json = {
-                    "action":"startScan",//交互指令参数
-                    "batchNumber":GetBatchStr(res.data.id,currentBatchNo.value),//批次号  这里传给客户端的批次号需要进行处理 截取批次id后5位拼接batchNumber
-                    "subjectCode":examSubjectCode.value,//科目编号
-                    "paperSchema":1,//this.paperSchema,// 单双面//页面类型  1 单面  2  双面
-                    "token":localStorage.getItem('token'),//token信息
-                    "uploadUrl":uploadUrl, // 图片上传地址
-                    "dpi":150,//dpi参数 设置图片清晰度质量的
-                    "isColor":1,//是否彩色图片 手阅卡扫描彩色图片 0  黑白  1 彩色
-                    "useDriveUI":1,//startScan和scanTemplate增加useDriveUI参数,=1时会弹框,其他值或不写则不弹
-                    "jsonParam":JSON.stringify(jsonParam),// 后端使用的参数 json字符串 后端接口固定三个参数  1:jsonParam  2:seqNumber(这个批次的图片序号:从1开始)   3:file 图片文件
-                };//正式版参数 
-                console.log("打印发送的数据",JSON.stringify(json));
-                setTimeout(() => {
-                    scanCommon.send(JSON.stringify(json))
-                },100)
-                
-            }
-            else
-            {
-                ElMessage.error(res.msg);
-            }
-            
-        });
-
-    }
-    else
-    {
-        //提示客户端未打开
-        ElMessage.warning('请先打开客户端');
-    }
-}
 
 //关闭弹窗
 const CloseDialog = () => {
@@ -249,13 +148,7 @@ const CloseDialog = () => {
 }
 
 
-//获取批次字符串
-const GetBatchStr=(batchId:any,batChNo:any)=>{
-    const batchNoValue = batchId.substring(batchId.length - 5);
-    const batchNo=String(batChNo).padStart(3, '0');
-    const batchNumber=batchNoValue+batchNo;//传给客户端的图片批次号 id后五位数加上00批次号
-    return batchNumber;
-}
+
 
 //根据处理后的批次号转换成处理前的批次号
 const GetBatchNumber=(batchNumber:any)=>{
@@ -385,24 +278,6 @@ const HasImportStudent = async () => {
     }
 }
 
-//获取扫描批次列表
-const GetScanBatchList=async()=>{
-    const params = {
-      examSubjectId: examSubjectId.value,
-      schoolId: 0,//单校 0 
-    };
-    const res = await getBatchList(params);
-    if(res.code==200)
-    {
-        tableData.value=res.data.scannedWebSocketVO.data;
-        selectSchoolId.value=res.data.schoolId;//获取学校id
-        scanDataInfo.value.abnormalNum=res.data.scannedWebSocketVO.abnormalNum;//异常数量
-        scanDataInfo.value.examMissNum=res.data.scannedWebSocketVO.examMissNum;//缺考数量
-        scanDataInfo.value.scannedNum=res.data.scannedWebSocketVO.scannedNum;//已上传数量
-        scanDataInfo.value.unScanned=res.data.scannedWebSocketVO.unScanned;//未扫描数量
-        scanDataInfo.value.examTotal=res.data.scannedWebSocketVO.examTotal;//总人数
-    }
-}
 
 
 
@@ -669,7 +544,7 @@ onMounted(() => {
         // 可选:如果没有数据,可以重定向回列表页或提示用户
     }
     HasImportStudent();//查询是否导入了学生名单
-    GetScanBatchList();//获取扫描批次列表
+
     CalculateTableHeight();//初始化计算表格高度
   
     // 监听窗口大小变化

+ 22 - 6
src/views/exam/components/scanButton.vue

@@ -151,13 +151,29 @@ export default {
         },
 
         // 格式化进度显示:如果小数部分为0则不显示,否则显示一位小数
-        FormatProcess(process) {
-            if (process % 1 === 0) {
-                // 如果是整数,直接返回整数部分
-                return Math.floor(process);
+        FormatProcess(process) 
+        {
+            // 1. 检查是否为有效数字
+            if (process === null || process === undefined || isNaN(process) || !isFinite(process)) {
+                return 0;
+            }
+
+            // 2. 确保是数字类型(防止字符串等意外类型)
+            const num = Number(process);
+
+            // 3. 再次校验转换后的结果
+            if (isNaN(num)) {
+                return 0;
+            }
+
+            // 4. 格式化逻辑
+            if (num % 1 === 0) {
+                // 如果是整数,直接返回整数
+                return num;
             } else {
-                // 如果有小数部分,保留一位小数
-                return process.toFixed(2);
+                // 如果有小数部分,保留两位小数(根据原代码逻辑是 toFixed(2))
+                // 注意:toFixed 返回的是字符串,如果需要数字可以加 +parseFloat(),但通常用于展示字符串即可
+                return parseFloat(num.toFixed(2)); 
             }
         },
         animations () {

+ 19 - 6
src/views/exam/scanList.vue

@@ -496,13 +496,26 @@ const GetScanBatchList=async()=>{
     const res = await getBatchList(params);
     if(res.code==200)
     {
-        tableData.value=res.data.scannedWebSocketVO.data;
+        
         selectSchoolId.value=res.data.schoolId;//获取学校id
-        scanDataInfo.value.abnormalNum=res.data.scannedWebSocketVO.abnormalNum;//异常数量
-        scanDataInfo.value.examMissNum=res.data.scannedWebSocketVO.examMissNum;//缺考数量
-        scanDataInfo.value.scannedNum=res.data.scannedWebSocketVO.scannedNum;//已上传数量
-        scanDataInfo.value.unScanned=res.data.scannedWebSocketVO.unScanned;//未扫描数量
-        scanDataInfo.value.examTotal=res.data.scannedWebSocketVO.examTotal;//总人数
+        if(res.data.scannedWebSocketVO)
+        {
+            tableData.value=res.data.scannedWebSocketVO?.data || [];
+            scanDataInfo.value.abnormalNum=res.data.scannedWebSocketVO.abnormalNum;//异常数量
+            scanDataInfo.value.examMissNum=res.data.scannedWebSocketVO.examMissNum;//缺考数量
+            scanDataInfo.value.scannedNum=res.data.scannedWebSocketVO.scannedNum;//已上传数量
+            scanDataInfo.value.unScanned=res.data.scannedWebSocketVO.unScanned;//未扫描数量
+            scanDataInfo.value.examTotal=res.data.scannedWebSocketVO.examTotal;//总人数
+            let examInfoCount={
+                unScanned:res.data.scannedWebSocketVO.unScanned,
+                examMissNum:res.data.scannedWebSocketVO.examMissNum,
+                scannedNum:res.data.scannedWebSocketVO.scannedNum,
+                abnormalNum:res.data.scannedWebSocketVO.abnormalNum,
+                examTotal:res.data.scannedWebSocketVO.examTotal,
+            };
+            examStore.setExamInfoCount(examInfoCount);//设置扫描数据信息
+        }
+        
     }
 }