| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123 |
- <template>
- <div class="page_list">
-
- <div class="search_content">
- <div class="content_left">
- <span class="scan_state_title">客户端状态:</span>
- <span class="scan_state_open" v-if="scanClientStates">
- <i class="iconfont icon_open"></i>已打开</span>
- <span class="scan_state_close" v-else>
- <i class="iconfont icon_close"></i>未打开</span>
- <span v-if="scanClientStates" class="scan_state_title" style="color: #999;">(当前客户端版本:{{scanClientVersion}})</span>
- <!-- <el-select v-model="params.batchNo" placeholder="选择批次" @change="GoSearch()" class="select_width" >
- <el-option label="全部批次" value=""></el-option>
- <el-option v-for="item in batchList"
- :key="item.value"
- :label="item.label" :value="item.value"></el-option>
- </el-select>
- <el-select v-model="params.batchNo" placeholder="选择状态" @change="GoSearch()" class="select_width" >
- <el-option label="全部状态" value=""></el-option>
- <el-option v-for="item in batchList"
- :key="item.value"
- :label="item.label" :value="item.value"></el-option>
- </el-select>
- <el-input placeholder="考试名称,编号" v-model="params.keyWord" @input="GoSearch" @change="GoSearch()" class="input_width" >
- <el-button @click="GoSearch()" slot="append" icon="el-icon-search"></el-button>
- </el-input> -->
- </div>
- <div class="content_right">
- <el-button @click="Refresh" >
- <i class="iconfont icon_shuaxin"></i>刷新
- </el-button>
-
-
- <!-- <el-button class="delete_item" type="text" @click="OpenDeleteAllDialog" v-if="tableData.length>0">删除所有</el-button> -->
- <el-button @click="OpenReIdentify" >重新识别</el-button>
- <el-button @click="OpenEditExamList()" type="primary" v-if="isImportStudent">编辑考场名单</el-button>
- <el-button @click="OpenImportStudent()" type="primary" v-else>导入考场名单</el-button>
- </div>
- </div>
- <div class="page_jg_20"></div>
- <div class="page_content" >
- <div class="content_table">
- <div class="page_table">
- <el-table :data="tableData" style="width: 100%" :height="tableHeight">
- <!-- <el-table-column prop="questionName" label="序号" width="100" align="center" >
- </el-table-column> -->
- <el-table-column prop="batchNo" label="批次" width="120" align="center">
- </el-table-column>
- <el-table-column prop="scannedPaperNum" label="扫描张数" align="center">
- </el-table-column>
- <el-table-column prop="uploadNum" label="待上传张数" align="center" >
- <template v-slot="scope">
- <div class="table_row_answer" v-if="GetNoUploadNumber(scope.row)>0" @click="OpenUpload(scope.row)">
- <span style="color:red;text-decoration:underline;"> {{GetNoUploadNumber(scope.row)}}</span>
- <!-- {{scope.row.failedNumber || 0}} -->
- </div>
- <div v-else>0</div>
- </template>
- </el-table-column>
- <el-table-column prop="uploadNum" label="已上传张数" align="center" >
- <template v-slot="scope">
-
- </template>
- </el-table-column>
- <el-table-column prop="scanUserName" label="扫描人" align="center" >
- <template v-slot="scope">
-
- </template>
- </el-table-column>
- <el-table-column prop="scanUserName" label="扫描时间" align="center">
- <template v-slot="scope">
- {{formatTimestamp(scope.row.scannedTime) }}
- </template>
- </el-table-column>
- <el-table-column prop="name" label="操作" width="250" align="center">
- <template v-slot="scope">
- <div class="ele_button table_row_button" v-if="scope.row.uploadStatus==0" style="color:#2E64FA;">
- <i class="el-icon-loading"></i>{{loadingText}}……
- </div>
- <div class="ele_button table_row_button" v-else>
- <span class="btn_editor" @click="GotoBatchDetail(scope.row.batchNo)">详情</span>
- <span class="btn_delete" v-if="scope.row.scanUserName==currentUserName " @click="OptionDelete(scope.row)">删除</span>
- <span class="editor_disable" v-else>删除</span>
- </div>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </div>
- <div class="content_right">
- <div class="right_header">
- <div class="scan_set"> 扫描设置</div>
- <div class="scan_set_scan_code">
-
- <el-select style="width: 100px;margin-right: 6px;" v-model="useDriveUI" placeholder="是否显示驱动弹窗" @change="ChangeDriveUI">
- <el-option v-for="item in scanTypeList" :key="item.value" :label="item.label" :value="item.value"></el-option>
- </el-select>
- <!-- 识别号: -->
- <el-select style="width: 100px;margin-right: 6px;" v-model="scanIdentifyCode" placeholder="选择识别号" @change="ChangeCode" >
- <el-option v-for="item in scanIdentifyList" :key="item.value" :label="item.label" :value="item.value"></el-option>
- </el-select>
- </div>
- </div>
- <div class="right_center">
- <div class="scan_buttons">
- <ScanButton :process="scanProcess" :quekao="scanQuekao" :yichang="scanYichang" @click="OpenScan()"></ScanButton>
- </div>
- <div class="scan_list">
- <div class="list_item no_scan" >
- <div class="list_item_info" @click="GotoDetail(0)">
- <div class="item_info_title">
- 未扫描
- </div>
- <div class="item_info_number">
- <span class="number_no_scan">{{scanDataInfo.unScanned}}人</span>
- <!-- <span class="number_no_icon"><img src="../../assets/icon/no_scan_icon.png"></span> -->
- </div>
- </div>
- </div>
- <div class="list_item no_exam" >
- <div class="list_item_info " @click="GotoDetail(2)">
- <div class="item_info_title">
- 缺考
- </div>
- <div class="item_info_number">
- <span class="number_no_exam">{{scanDataInfo.examMissNum}}人</span>
- <!-- <span class="number_no_icon"><img src="../../assets/icon/miss_exam.png"></span> -->
- </div>
- </div>
- </div>
- <div class="list_item annormal_icon" >
- <div class="list_item_info " @click="GotoDetail(3)">
- <div class="item_info_title">
- 异常
- </div>
- <div class="item_info_number">
- <span class="number_abnormal">{{scanDataInfo.abnormalNum}}份</span>
- <!-- <span class="number_no_icon"><img src="../../assets/icon/abnormal_icon.png"></span> -->
- </div>
- </div>
- </div>
- <div class="list_item sucess_upload" >
- <div class="list_item_info " @click="GotoDetail(1)">
- <div class="item_info_title">
- 已上传
- </div>
- <div class="item_info_number">
- <span class="number_uploaded">{{scanDataInfo.scannedNum}}人</span>
- <!-- <span class="number_no_icon"><img src="../../assets/icon/sucess_upload.png"></span> -->
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="right_button">
- <el-button type="primary" @click="FinishScanned()" :loading="finishLoading" style="width:calc(100% - 40px);">扫描完成</el-button>
- </div>
- </div>
- </div>
- <SelectStudent v-model="showSelectStudent" @success="StudentSuccess"></SelectStudent>
- <AbnormalDetail v-model="showAbnormalDialog" :scanState="scanState"></AbnormalDetail>
- </div>
- </template>
- <script lang="ts" setup>
- import { useExamStore } from '@/store/exam'
- import { useUserStore } from '@/store/user'
- import { useRouter } from 'vue-router'
- import { onMounted ,ref,computed,onUnmounted,nextTick } from 'vue';
- import ScanButton from './components/scanButton.vue'
- import SelectStudent from './components/selectStudent.vue'
- import { finishScanned,getExamScoreSummary,hasImportStudent,getBatchList,getCurrentBatchNo,deleteBatch,updateScanCount,setExamScanSetting,saveChooseCode} from '@/api/exam'
- import scanCommon from '@/utils/scanCommon';
- import { ElMessageBox, ElMessage } from 'element-plus'
- import { formatTimestamp } from '@/utils/common';
- import AbnormalDetail from './abnormalDetail.vue';
- import WebSocketManager from '@/utils/webSocket'//后端websocket链接js
- // 实例化 Store
- const examStore = useExamStore()
- const userStore = useUserStore()
- const router = useRouter()
- // 考试科目 ID
- const examSubjectId = computed(() => {
- return examStore.currentExam?.id
- })//计算属性
- const userInfo=computed(() => {
- return userStore.userInfo;
- })//用户信息
- const schoolType=computed(() => {
- return ''
- })
- //考试科目code
- const examSubjectCode=computed(() => {
- return examStore.currentExam?.examSubjectCode
- })
- //当前登录人姓名
- const currentUserName=computed(() => {
- return userStore.userName;
- })
- //查询是否导入了学生名单
- const HasImportStudent = async () => {
- const params = {
- examSubjectId: examSubjectId.value,
- schoolId: 0,//单校 0
- };
- const res = await hasImportStudent(params);
- console.log("打印是否导入了学生名单",res);
- if(res.code==200)
- {
- isImportStudent.value=res.data;
- }
- else{
- isImportStudent.value=false;
- }
- if(!isImportStudent.value)
- {
- console.log("未导入学生名单,跳转到选择学生名单界面");
- //跳转导入学生名单界面
- router.push({
- name: 'selectExamination',
-
- });
- }
- }
- // 组件创建时立即执行
- HasImportStudent();//查询是否导入了学生名单();
- const selectSchoolId=ref(0);//学校ID
- const showAbnormalDialog=ref(false);//异常弹窗
- const scanState = ref(0);//扫描状态//默认未扫描
- const params=ref({
- batchNo:'',
- keyWord:''
- })
- const scanClientStates=ref(false);//客户端状态
- const scanClientVersion=ref('');//客户端版本
- const isScanning=ref(false);//是否正在扫描 扫描状态
- const hasMakeTemplate=ref(false);//模版是否制作完成
- const currentBatchNo=ref('');//当前批次号
- const currentBatchNoId=ref('');//当前批次号id
- const loadingText=ref('');//加载文本
- const baseUrl=import.meta.env.VITE_API_BASE_URL;
- const uploadUrl=`https://dev3.k12100.net/teaching/api/v1/ai_exam_scan/upload_multi_img`;//图片上传地址
- const updateCountUrl=`https://dev3.k12100.net/teaching/api/v1/ai_exam_scan/record_batch_scan_number`;
- const webSocket=ref<InstanceType<typeof WebSocketManager> | null>(null);//websocket
- let websocketUrl=import.meta.env.VITE_WEB_SOCKET_URL;//websocket链接地址
- // 定义数据类型接口
- 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=[
- {
- label:'考号',
- value:'2',
- },
- {
- label:'学号',
- value:'1',
- }
- ];//识别号列表
- const scanTypeList=[
- {
- label:'不弹窗',
- value:0,
- },
- {
- label:'弹窗',
- value:1,
- }
- ];
- const scanIdentifyCode=ref('1');////识别号 1-学号 2-考号
- const useDriveUI=ref(0);//1是会弹框,其他值或不写则不弹
- const isImportStudent=ref(false);//是否导入了学生名单
- const showSelectStudent=ref(false);//是否显示选择学生名单弹窗
- const finishLoading=ref(false);//扫描完成加载中
- const scanDataInfo=ref({
- abnormalNum:0,//异常数量
- examMissNum:0,//缺考数量
- unScanned:0,//未扫描数量
- scannedNum:0,//已上传数量
- examTotal:0,//考试总人数
- });//扫描返回的数据信息
- //扫描进度
- 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 FinishScanned= async () =>{
- console.log("打印完成")
- ElMessageBox.confirm('确认完成吗?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning',
- customClass:'page_dialog'
- }).then(async () => {
-
- let param={
- id:examSubjectId.value
- };
- finishLoading.value=true;
- const res = await finishScanned(param)
- if(res.code == 200)
- {
- // ElMessage.success("完成成功!")
- let idList=res.data.split(",");
- let analysisParam = {
- examId:idList[0],
- examPaperIds:[idList[1]],//多科传0 单科传科目ID
- }
- //扫描完成 调用汇总接口
- const analysisRes = await getExamScoreSummary(analysisParam);
- if(analysisRes.code == 200)
- {
- ElMessage.success("完成成功!")
- finishLoading.value=false;
- }
- else
- {
- ElMessage.error(analysisRes.msg);
- finishLoading.value=false;
- }
- }
- else
- {
- ElMessage.error(res.msg);
- finishLoading.value=false;
- }
- })
- }
- // 根据环境配置请求地址
- const ConfigRequestUrlByEnv= () =>{
- console.log("打印环境", import.meta.env.MODE);
- if (import.meta.env.MODE === 'development')
- {
- //开发环境
- console.log("打印import.meta.env.VITE_API_BASE_URL", import.meta.env.VITE_API_BASE_URL);
- websocketUrl = 'wss://dev3.k12100.net/teaching/api/v1/teaching/websocket/'
- console.log("设置webSocket地址",websocketUrl);
- } else if (import.meta.env.MODE === 'production')
- {
- websocketUrl = import.meta.env.VITE_WEB_SOCKET_URL || '';
- console.log("打印websocket地址", websocketUrl);
- console.log("打印上传图片地址", uploadUrl);
- }
-
- }
- //切换弹窗模式
- const ChangeDriveUI=()=>{
- console.log("打印弹窗模式", useDriveUI.value);
- let params={
- alterWindow:useDriveUI.value
- };
- setExamScanSetting(params).then(res => {
- if(res.code == 200)
- {
- ElMessage.success("设置成功!")
- }
- else
- {
- ElMessage.error(res.msg);
-
- }
- })
- }
- //改变识别码
- const ChangeCode=()=>{
- let param={
- examSubjectId:examSubjectId.value,
- chooseCode:scanIdentifyCode.value//识别号 1-学号 2-平台号 3-学籍号 4-考号
- };
- saveChooseCode(param).then(res=>{
- console.log("打印识别码设置结果",res);
- if(res.code==200)
- {
- ElMessage.success("设置成功!")
- }
- else
- {
- ElMessage.error(res.msg);
- }
- })
- }
- //获取未上传图片的数量
- const GetNoUploadNumber=(item:BatchItem)=>
- {
- const scannedPaperNum = item.scannedPaperNum ?? 0;
- const uploadNum = item.uploadNum ?? 0;
- const result = scannedPaperNum - uploadNum;
-
- return result > 0 ? result : 0;
- }
- // 跟后端websocket连接 1.建立socket连接 用户ID_考试科目ID_学校ID_批次号
- const WebSocketLink = () => {
- if(webSocket.value && webSocket.value.getSocketStatus() === WebSocket.OPEN)
- {
- webSocket.value.closeWebSocket();
- }
- let userCourseId='';
- let schoolIdValue = userInfo.value.schoolId; // 这里逻辑是 单校都取登录用户的学校ID 如果是联校账号 给单校扫描 传单校的学校id
- // if(schoolType.value == 1) {
- // //联校 盟主学校
- // schoolIdValue = selectSchoolId.value;
- // } else {
- // schoolIdValue = userInfo.value.schoolId;
- // }
-
- console.log("打印用户信息", userInfo.value);
- userCourseId = `${userInfo.value.userId}_${examSubjectId.value}_${schoolIdValue}_${currentBatchNo.value}`; //用户 科目 批次号
- console.log("websocketUrl",websocketUrl);
- const url = `${websocketUrl}${userCourseId}`;
- console.log("打印websocket链接地址url", url);
- webSocket.value = new WebSocketManager(url, MessageBack);
- webSocket.value.start();
- }
- //websocket消息返回
- const MessageBack = (data:any) => {
- // console.log("打印websocket返回数据", data);
- const msg=JSON.parse(data);
- console.log("Websocket消息返回处理",msg);
- //code 0 建立成功 200 业务成功 400 业务失败 异常 需要提示信息
- if(msg.code==0)
- {
- //建立成功
- console.log("和后端的websocket建立成功");
- }
- else if(msg.code==200)
- {
- //业务成功
- // console.log("打印当前tableData的数据",this.tableData);
- //正常扫描
- let currentData=msg.data[0];
- let targetItem = tableData.value.find(item => item.batchNo == currentData.batchNo);
- console.log("识别成功+1",targetItem);
- if(msg.abnormalNum==-1)
- {
- scanDataInfo.value.unScanned = msg.unScanned;
- scanDataInfo.value.examMissNum = msg.examMissNum;
- scanDataInfo.value.abnormalNum = msg.abnormalNum;
- scanDataInfo.value.scannedNum = msg.scannedNum;
- if (targetItem) {
- if(currentData.uploadNum==-1)
- {
- targetItem.uploadNum++;
- }
- }
- }
- else
- {
- if (targetItem) {
- targetItem.uploadNum = msg.data[0].uploadNum;
- }
- scanDataInfo.value.unScanned = msg.unScanned;
- scanDataInfo.value.examMissNum = msg.examMissNum;
- scanDataInfo.value.abnormalNum = msg.abnormalNum;
- scanDataInfo.value.scannedNum = msg.scannedNum;
- let process = (Number(scanDataInfo.value.scannedNum) + Number(scanDataInfo.value.examMissNum)) / Number(scanDataInfo.value.examTotal) * 100
- if (isNaN(process)) {
- process = 0
- }
-
- }
- if(targetItem)
- {
- if(Number(targetItem.scannedPaperNum) === Number(targetItem.uploadNum))
- {
- targetItem.uploadStatus=1;
- // loadingText.value='';
- isScanning.value=false;
- // removeBeforeUnloadListener();// 移除页面离开阻止监听器
- }
- else
- {
- }
- }
-
-
-
- }
- else if(msg.code==400)
- {
- //业务失败
- GetScanBatchList();
- ElMessage.error(msg.message);
- }
- }
- //重新识别弹窗
- 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, // 图片上传地址
- "updateCountUrl":updateCountUrl,//更新扫描纸张数量接口 接口参数 批次id post 请求 id
- "batchId":currentBatchNoId.value,//批次号id
- "dpi":150,//dpi参数 设置图片清晰度质量的
- "isColor":1,//是否彩色图片 手阅卡扫描彩色图片 0 黑白 1 彩色
- "useDriveUI":0,//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)
- // 建立与后端的websocket连接
- WebSocketLink();
- }
- else
- {
- ElMessage.error(res.msg);
- }
-
- });
- }
- else
- {
- //提示客户端未打开
- ElMessage.warning('请先打开客户端');
- }
- }
- //获取批次字符串
- 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)=>{
- if (!batchNumber) {
- console.warn('批次号为空或未定义');
- return currentBatchNo.value;//返回当前的批次号
- }
-
- const batchStr = batchNumber.toString();
- if (batchStr.length < 3) {
- console.warn('批次号长度小于3位:', batchStr);
- return currentBatchNo.value;//返回当前的批次号
- }
-
- const lastThree = batchStr.slice(-3);
- const parsedNumber = parseInt(lastThree, 10);
-
- if (isNaN(parsedNumber)) {
- console.error('无法解析批次号:', lastThree);
- return currentBatchNo.value;//返回当前的批次号
- }
- console.log("打印最后的批次号",parsedNumber);
- return parsedNumber.toString();
- }
- //删除批次
- const OptionDelete=(row: any) => {
- console.log('删除批次', row);
-
- if(row.scanUserName==currentUserName.value)
- {
- ElMessageBox.confirm('确定要删除该批次吗?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- customClass:'page_dialog',
- type: 'warning'
- }).then(() => {
- // 删除操作
- console.log('删除', row);
- const params={
- examSubjectId:examSubjectId.value,
- batchNo:row.batchNo,
- schoolId:selectSchoolId.value,
- };
- deleteBatch(params).then((res:any)=>{
- if(res.code==200)
- {
- ElMessage.success("删除成功!")
- GetScanBatchList();
- }
- else
- {
- ElMessage.error(res.msg);
- }
- })
-
- }).catch(() => {
- // 取消操作
- console.log('取消删除');
- });
- }
- else
- {
- ElMessage.warning('只能删除自己上传的记录');
- }
- }
- //跳转到异常详情页
- const GotoDetail = (type: number) => {
- console.log('跳转到异常详情页', type);
- scanState.value=type;
- // 根据类型跳转到不同的详情页
- showAbnormalDialog.value=true;
-
- }
- //跳转到批次详情页
- const GotoBatchDetail=(batchNo:any)=>{
- router.push({
- path: '/exam/scanDetail',
- query: {
- examSubjectId: examSubjectId.value,
- batchNo: batchNo,
- },
- })
- }
- // 打开导入学生名单
- const OpenImportStudent = () => {
- showSelectStudent.value=true;
- }
- // 打开编辑考试名单
- const OpenEditExamList = () => {
- router.push({
- path: '/exam/examList',
- query: {
- examSubjectId: examSubjectId.value,
- },
- });
- }
- //学生名单导入成功
- const StudentSuccess = () => {
- HasImportStudent();
- }
- //获取扫描批次列表
- const GetScanBatchList=async()=>{
- const params = {
- examSubjectId: examSubjectId.value,
- schoolId: 0,//单校 0
- };
- const res = await getBatchList(params);
- if(res.code==200)
- {
-
- selectSchoolId.value=res.data.schoolId;//获取学校id
- 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);//设置扫描数据信息
- }
-
- }
- }
- //计算高度的函数
- const CalculateTableHeight = () => {
- // nextTick 确保 DOM 更新后再获取尺寸
- nextTick(() => {
- // window.innerHeight 是浏览器可视区域高度
- // 简单算法:视窗高度 - 固定占用高度
- let computedHeight = window.innerHeight - 136;
-
- // 限制最小高度,防止太矮
- if (computedHeight < 200) {
- computedHeight = 200;
- }
- tableHeight.value = computedHeight;
- });
- };
- //更新扫描张数
- const UpdateBatchScanNumber = (batchId: any, scanNumber: Number) => {
- const params={
- id:batchId,
- recordNumber: scanNumber,
- };
- updateScanCount(params).then((res:any)=>{
- if(res.code==200)
- {
- console.log("第"+batchId+"批次更新扫描张数"+scanNumber+"成功", res);
- }
- })
- };
- // 处理扫描结果
- const HandleScanResult = (res: any) => {
- console.log('收到扫描数据', res);
- // 业务逻辑...
- if (res.action == 'uploading')
- {
- let batchNumber: any = '';
- if (res.batchNumber)
- {
- batchNumber = GetBatchNumber(res.batchNumber || res.data?.batchNumber);
- }
- const targetItem = tableData.value.find((item: any) => item.batchNo == batchNumber);
-
- if (typeof loadingText !== 'undefined') loadingText.value = "启动扫描仪中";
- ElMessage.success("正在启动扫描仪,请稍后…");
- if (targetItem)
- {
- targetItem.uploadStatus = 0; //更新上传状态 0 开始上传
- }
- }
- // 开始扫描指令
- if (res.action == 'startScan')
- {
-
- let batchNumber = GetBatchNumber(res?.batchNumber || res.data?.batchNumber);
- let currentItem = tableData.value.find((item: any) => item.batchNo == batchNumber);
- console.log("打印currentItem", currentItem);
-
- //开始扫描指令
- if (res.code == 200)
- {
- ElMessage.success("扫描仪启动成功,开始扫描…");
- if(typeof loadingText !== 'undefined') loadingText.value = "正在扫描中";
- }
-
- if (res.code == 502)
- {
- console.log("开始扫描指令502错误 未检测到纸张或者卡纸", res);
- console.log("打印currentItem", currentItem);
- if (currentItem) {
- currentItem.uploadStatus = 1; //更新上传状态
- }
- if (typeof loadingText !== 'undefined') loadingText.value = ""; //清空上传提示
- isScanning.value = false; //重置扫描状态
- ElMessage.error(res.msg);
- }
-
- if (res.code == 510)
- {
- console.log("启动扫描失败,上传正在进行中", res);
- isScanning.value = true; //重置扫描状态
- ElMessage.warning(res.msg + '请勿重复点击');
- }
-
- if (res.code == 509) {
- console.log("扫描仪正在使用中", res);
- if (res.msg == '未找到指定的扫描仪') {
- isScanning.value = false; //重置扫描状态
- }
- ElMessage.warning(res.msg + ',请稍后再试!');
- if (currentItem) {
- currentItem.uploadStatus = 1; //更新上传状态
- }
- }
- }
- // 扫描完成指令
- if (res.action == 'uploadFinish') {
- console.log("上传完成uploadFinish 更新上传动画状态", res);
-
- // 修复:直接调用 GetBatchNumber
- let batchNumber = GetBatchNumber(res?.batchNumber || res.data?.batchNumber);
- let targetItem = tableData.value.find((item: any) => item.batchNo == batchNumber);
-
- if (typeof loadingText !== 'undefined') loadingText.value = '正在上传中';
-
- if (targetItem) {
- targetItem.scannedPaperNum = res.scanNumber; //更新扫描张数
- targetItem.failedNumber = res.failedNumber; //更新失败张数
-
- if (typeof UpdateBatchScanNumber === 'function') {
- UpdateBatchScanNumber(targetItem.id, Number(targetItem.scannedPaperNum));
- }
- }
- isScanning.value = false; //重置扫描状态
- }
- if (res.action == 'uploadNumber') {
- console.log("上传完成uploadNumber 更新上传张数", res);
- // 逻辑已注释,保持原样
- }
- if (res.action == 'scanNumber') {
- console.log("扫描张数scanNumber 更新扫描张数");
- // 修复:直接调用 GetBatchNumber
- let batchNumber = GetBatchNumber(res.batchNumber || res.data?.batchNumber);
- let targetItem = tableData.value.find((item: any) => item.batchNo == batchNumber);
- console.log("打印targetItem", targetItem);
-
- if (targetItem) {
- targetItem.scannedPaperNum = res.number; //更新上传张数
- targetItem.uploadStatus = 0; //更新上传状态 0 开始上传
- }
-
- // 修复:确保 UpdateBatchScanNumber 已定义
- if (targetItem && typeof UpdateBatchScanNumber === 'function') {
- UpdateBatchScanNumber(targetItem.id, Number(targetItem.scannedPaperNum));
- }
- }
- if (res.action == 'loadImage') {
- console.log("加载图片loadImage 获取图片数据", res);
-
- // 修复:reImageList 必须是 ref
- if (typeof reImageList !== 'undefined') {
- reImageList.value = res.data || [];
- reImageList.value.forEach((item: any) => {
- item.uploadStatus = -2;
- item.uploadProgress = 0;
- });
- }
-
- let batchNumber = GetBatchNumber(res.batchNumber);
- let targetItem = tableData.value.find((item: any) => item.batchNo == batchNumber);
-
- console.log("打印重新上传图片列表", reImageList.value);
- console.log("打印重新上传的批次Item", targetItem);
-
- if (targetItem) {
- targetItem.uploadStatus = 0;
- }
-
- if (typeof loadingText !== 'undefined') loadingText.value = '正在上传中';
- if (typeof uploadDialogTitle !== 'undefined') uploadDialogTitle.value = '未上传的图片';
- if (typeof showUploadDialog !== 'undefined') showUploadDialog.value = true;
- }
- if (res.action == 'finish') {
- console.log("图片重传finish指令", res);
-
- let batchNumber = GetBatchNumber(res.batchNumber);
- let targetItem = tableData.value.find((item: any) => item.batchNo == batchNumber);
- let fileIndex = res.fileIndex.split(",");
- console.log("打印fileIndex", fileIndex);
-
- fileIndex.forEach((index: string) => {
- // 修复:reImageList.value
- let reImageItem = reImageList.value.find((item: any) => item.fileIndex == index);
- if (reImageItem) {
- let progress = reImageItem.uploadProgress;
- const interval = setInterval(() => {
- progress += 5;
- if (progress >= 100) {
- progress = 100;
- clearInterval(interval);
- // 修复:Vue3 不需要 $set,直接赋值即可触发响应式
- reImageItem.uploadStatus = res.uploadState;
- }
- reImageItem.uploadProgress = progress;
- }, 100);
- }
- });
- // 修复:reImageCount 可能是 ref 或计算属性
- let currentReImageCount = typeof reImageCount !== 'undefined' ? reImageCount.value : reImageList.value.length;
-
- if (currentReImageCount === 0) {
- if (typeof showUploadDialog !== 'undefined') showUploadDialog.value = false;
- if (targetItem) {
- targetItem.uploadStatus = 1;
- isScanning.value = false;
- // 修复:确保 GetBatchList 已定义
- if (typeof GetBatchList === 'function') GetBatchList();
- }
- }
- }
- if (res.action == 'getFailedImage') {
- console.log("获取失败图片getFailedImage", res);
- let failedList = res.data || [];
-
- failedList.forEach((item: any) => {
- let batchNumber = GetBatchNumber(item.batchNumber);
- let currentItem = tableData.value.find((item1: any) => item1.batchNo == batchNumber);
-
- if (currentItem) {
- if (item.failedNumber == 0) {
- if (currentItem.scannedPaperNum != currentItem.uploadNum) {
- currentItem.scannedPaperNum = currentItem.uploadNum;
- if (typeof UpdateBatchScanNumber === 'function') {
- UpdateBatchScanNumber(currentItem.id, currentItem.uploadNum);
- }
- }
- } else {
- let number = currentItem.uploadNum + item.failedNumber;
- currentItem.scannedPaperNum = number;
- if (typeof UpdateBatchScanNumber === 'function') {
- UpdateBatchScanNumber(currentItem.id, number);
- }
- }
- }
- });
- }
- if (res.action == 'scanFinishBatch')
- {
- if (typeof loadingText !== 'undefined') loadingText.value = '本次扫描结束';
- console.log("本批次扫描完成scanFinishBatch 更新扫描张数", res);
- }
- };
- onMounted(() => {
- // 初始化连接
- scanCommon.init(HandleScanResult);
- // 监听连接状态
- scanCommon.watchConnection((isOnline,clientVersion) => {
-
- scanClientStates.value=isOnline;
- scanClientVersion.value=clientVersion; //客户端版本号
- // console.log("客户端版本",clientVersion);
- });
- if (!examStore.currentExam) {
- console.warn('当前没有选中的考试信息')
- // 可选:如果没有数据,可以重定向回列表页或提示用户
- }
-
- GetScanBatchList();//获取扫描批次列表
- CalculateTableHeight();//初始化计算表格高度
- console.log("打印当前的配置",import.meta.env.VUE_APP_BASE);
- //环境判断
- if (import.meta.env.VUE_APP_BASE === 'https://www.k12100.com')
- {
- }
- else
- {
- ConfigRequestUrlByEnv();///连接本地时候使用
- }
- // 监听窗口大小变化
- window.addEventListener('resize', CalculateTableHeight);
- });
- // 卸载时移除监听,防止内存泄漏
- onUnmounted(() => {
- window.removeEventListener('resize', CalculateTableHeight);
- // 组件销毁时务必停止,防止内存泄漏和后台重连
- scanCommon.stop();
- });
- </script>
-
- <style lang="scss" scoped>
- .page_list
- {
- width: 100%;
- height: 100%;
- padding: 20px;
- background-color: #fff;
- border-radius: 4px;
- box-sizing: border-box;
- }
- .scan_state_title
- {
- font-size: 14px;
- color:#333;
- font-weight: 400;
- }
- .scan_state_open
- { margin-left: 5px;
- font-size: 14px;
- font-weight: 400;
- color: #2BC644;
- i
- {
- margin-right: 5px;
- }
- }
- .scan_state_close
- {
- font-size: 14px;
- font-weight: 400;
- margin-left: 5px;
- color:#F56C6C;
- i
- {
- margin-right: 5px;
- }
-
- }
- </style>
|