<template>
  <div class="page_list">
    
    <div class="search_content">
        <div class="content_left">
                <span class="scan_state_title"><span>客户端状态</span>：</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">
            <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>
            <div @click="OpenImportDialog" class="editor_item" >导入扫描图片</div>
            <el-button @click="OpenEditExamList()" type="primary">编辑考场名单</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 scan_state_title" @click="OpenNumberSet()"> <span>考号设置</span></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>
    
    <div class="page_dialog">
          <el-dialog
            v-model="showNumberSetDialog"
            title="考号设置"
            width="480px"
            class="page_dialog"
            
        >
            <el-form ref="formRef"   label-width="130px">
                <el-form-item label="考号识别顺序：" prop="examSubjectName">
                    <el-select style="width: 60px;margin-right: 6px;" v-model="examCodeStart" placeholder="开始位置" >
                        <el-option v-for="item in 10" :key="item" :label="item" :value="item"></el-option>
                    </el-select>
                    -
                    <el-select style="width: 60px;margin-right: 6px;margin-left: 6px;" v-model="examCodeEnd" placeholder="结束位置">
                        <el-option v-for="item in 10" :key="item" :label="item" :value="item"></el-option>
                    </el-select>
                </el-form-item>
                
               
            </el-form>

            <template #footer>
            <span class="dialog-footer">
                <el-button @click="CloseNumberSet()">取消</el-button>
                <el-button type="primary" :loading="setLoading" @click="HandleSubmit">确定</el-button>
            </span>
            </template>
        </el-dialog>
        <ReIdentify v-model="isReIdentify" :reIdentifyTotal="reIdentifyTotal" justObjective="0" :schoolInfo="selectSchoolInfo"  @ReIdentifyComplete="Refresh"></ReIdentify>
        <UploadImage v-if="showUploadImage" v-model="showUploadImage"  :batchNumber="currentBatchNo" :isfilter="isfilter"  :schoolInfo="selectSchoolInfo"  @UploadProgress="UploadProgress" @UploadComplete="UploadComplete"  @CancelUpload="CancelUpload"></UploadImage>
        <AbnormalDetail v-model="showAbnormalDialog" :scanState="scanState" @success="BackScan"></AbnormalDetail>
    </div>
  </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 UploadImage from './components/UploadImage.vue'//导入扫描图片
import {setExamNumberPosition,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 ReIdentify from './components/ReIdentify.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 showNumberSetDialog=ref(false);//考号识别顺序设置
const examCodeStart=ref(1);//考号开始位置
const examCodeEnd=ref(10);//考号结束位置
const setLoading=ref(false);//考号设置加载中

const isReIdentify=ref(false);//是否重新识别
const reIdentifyTotal = ref(0);//需要识别的数
const selectSchoolInfo=ref({
    schoolId:'',
    schoolName:''
});//学校信息
const params=ref({
    batchNo:'',
    keyWord:''
})

const scanClientStates=ref(false);//客户端状态
const scanClientVersion=ref('');//客户端版本
const isScanning=ref(false);//是否正在扫描 扫描状态
const hasMakeTemplate=ref(false);//模版是否制作完成
const currentBatchNo=ref('');//当前批次号

const isfilter=ref(1);//是否过滤

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 showUploadImage=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 UploadProgress=(batchNumber:number,scanNumber:number)=>{

    console.log("图片上传扫描更新进度",batchNumber,scanNumber);
    const targetItem = tableData.value.find((item:any) => item.batchNo == batchNumber);
    
    if (targetItem) {

        
    }
}

//导入图片完成
const UploadComplete=(batchNumber:number,scanNumber:number,currentBatchNOID:string) => { 

     let count = scanNumber;

    // // 1：单面    2：双面
    // if (paperSchema.value == 2) {
    //     // 双面扫描数量除以2（向下取整，防止奇数报错）
    //     count = Math.floor(scanNumber / 2);
    // } else {
        // 单面不除以2
        count = scanNumber;
    // }

    currentBatchNo.value = batchNumber.toString();

    const newData = {
        batchNo: currentBatchNo.value,
        scanUserName: userInfo.value?.userName || '', // 增加空值保护
        scannedPaperNum: count, // 扫描张数
        scannedTime: Date.now(), // 扫描时间
        uploadNum: 0, // 上传张数
        uploadStatus: 0,
    };

    tableData.value.push(newData);
    
    loadingText.value = "正在上传中";

    // 建立与后端的websocket连接
    WebSocketLink(); 
    
    // 扫描完成更新扫描张数
    UpdateBatchScanNumber(currentBatchNOID, count);
}

//取消上传
const CancelUpload=(batchNumber:number)=>{
    const targetItem = tableData.value.find((item:any)=> item.batchNo == batchNumber);
                
    setTimeout(() => {
        if (targetItem) 
        {
            targetItem.uploadStatus = 1; 
        }
    }, 5000);
}

//扫描异常返回
const BackScan= () => { 
    //更新列表
    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 OpenNumberSet=()=>{
    console.log("打印考号位数设置");
    showNumberSetDialog.value=true;
}

//关闭考号位数设置
const CloseNumberSet=()=>{
    showNumberSetDialog.value=false;
}

//确定考号设置
const HandleSubmit=()=>{

    if(examCodeStart.value > examCodeEnd.value) {
        ElMessage.error("开始考号位置不能大于结束考号位置");
        return;
    }

    let params={
        examSubjectId:examSubjectId.value,
        examCodeStart:examCodeStart.value,
        examCodeEnd:examCodeEnd.value,
    };
    setExamNumberPosition(params).then(res => {
        if(res.code == 200) 
        {
            ElMessage.success("设置成功!")
            showNumberSetDialog.value=false;
        }
        else
        {
            ElMessage.error(res.msg);
        
        }
    })
}
//切换弹窗模式
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=() => {
    
    //判断是否在扫描 
    if(isScanning.value)
    {
        //正在扫描中 不可重新识别
        ElMessage.error("正在扫描中，请等待扫描完成后再重新识别！");
        return;
    }
    
    //计算总识别张数
    let sumTotal=0;
    tableData.value.forEach((item:any) => {
        sumTotal+=item.uploadNum;
    });
    isReIdentify.value=true;
    // reIdentifyNumber.value=sumTotal;
    reIdentifyTotal.value=sumTotal;
}

//开始扫描
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 OpenImportDialog=() => {
    showUploadImage.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
        scanIdentifyCode.value=res.data.chooseCode;//获取识别码
        //1-单面 2-双面
        examCodeEnd.value=res.data.examCodeEnd;
        examCodeStart.value=res.data.examCodeStart;
        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;
    span
    {
        text-emphasis-style: dot;        /* 实心小圆点 • */
        // text-emphasis-style: circle;     /* 空心圆圈 ○ */
        // text-emphasis-style: double-circle; /* 双圆圈 ◉ */
        // text-emphasis-style: triangle;   /* 三角形 ▲ */

        /* 自定义字符 */
        // text-emphasis-style: '★';        /* 使用星号 */
        // text-emphasis-style: '※';       /* 使用参考标记 */
        text-emphasis-color: red;
        text-emphasis-position: under; /* 下方居中 */
    }

}
.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>