abnormal.vue 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. <template>
  2. <!-- 异常处理 -->
  3. <div class="content_main">
  4. <div class="abnormal_left">
  5. <div class="left_nav">
  6. <div class="nav_list">
  7. <!-- abnormalType:2,//页面异常类型 2-定位异常 3-考号异常 4-客观题异常 5-选做题异常 6-空白卷异常 7 缺页异常 -->
  8. <div class="nav_item" :class="abnormalType==2?'item_active':''" @click="AbnormalChanage(2)">
  9. <div class="nav_number" v-if="abnormalObj.locationErrorNum>0">{{ abnormalObj.locationErrorNum }}</div>
  10. 定位异常
  11. </div>
  12. <div class="nav_item" :class="abnormalType==3?'item_active':''" @click="AbnormalChanage(3)">
  13. <div class="nav_number" v-if="abnormalObj.examNumberErrorNum>0">{{ abnormalObj.examNumberErrorNum }}</div>
  14. 考号异常
  15. </div>
  16. <!-- <div class="nav_item" :class="abnormalType==7?'item_active':''" @click="AbnormalChanage(7)">
  17. <div class="nav_number" v-if="abnormalObj.losePageErrorNum>0">{{ abnormalObj.losePageErrorNum }}</div>
  18. 缺页异常
  19. </div> -->
  20. <div class="nav_item" :class="abnormalType==4?'item_active':''" @click="AbnormalChanage(4)">
  21. <div class="nav_number" v-if="abnormalObj.objectErrorNum>0">{{ abnormalObj.objectErrorNum }}</div>
  22. 客观题异常
  23. </div>
  24. <!-- <div class="nav_item" :class="abnormalType==5?'item_active':''" @click="AbnormalChanage(5)">
  25. <div class="nav_number" v-if="abnormalObj.choiceErrorNum>0">{{ abnormalObj.choiceErrorNum }}</div>
  26. 选做题异常
  27. </div>
  28. <div class="nav_item" :class="abnormalType==6?'item_active':''" @click="AbnormalChanage(6)" v-if="markType==1">
  29. <div class="nav_number" v-if="abnormalObj.subjectiveErrorNum>0">{{ abnormalObj.subjectiveErrorNum }}</div>
  30. 划分异常
  31. </div> -->
  32. </div>
  33. <div class="nav_button el_button">
  34. <div :class="isShowDraw?'is_draw_data':'is_draw_active'" @click="ShowDrawData()" v-if="abnormalType==4">显示画框</div>
  35. <el-select v-if="abnormalType==6" style="width: 100px;" v-model="isShowDrawType" placeholder="显示类型" @change="SubjectDataChange()">
  36. <el-option label="答题卡" value="1"></el-option>
  37. <el-option label="划分区" value="2"></el-option>
  38. </el-select>
  39. <el-button class="refresh_btn" @click="RefreshAbnormalList()"><i class="iconfont icon_shuaxin"></i>刷新</el-button>
  40. <el-button class="fit_screen_btn" @click="FitScreen()">适应屏幕</el-button>
  41. </div>
  42. </div>
  43. <div class="left_image" :class="abnormalType==6 && isShowDrawType==2?'left_image_height_2':'left_image_height_1'">
  44. <!-- 定位异常试卷区 -->
  45. <div class="page_jg_10"></div>
  46. <div v-if="abnormalType==2" class="position_abnormal_content">
  47. <div class="template_content">
  48. <div class="content_header">
  49. <div class="header_left">
  50. 标准模板
  51. </div>
  52. <div class="header_right">
  53. <div :class="item.pageNum==currentTemplatePageIndex?'page_num_active':'page_num_item'" v-for="(item,index) in currentTemplateList" :key="'template_'+index" @click="ChangeTemplatePage(item)">{{item.pageNum}}</div>
  54. </div>
  55. </div>
  56. <div class="content_canvas">
  57. <PositionCanvas ref="PositionCanvas" :usedCardType="usedCardType" :positionList="sourcePoints" :paperImgUrl="currentTemplateUrl" @GetCutPosition="GetCutTemaplatePosition" :paperType="usedCardType==1?'template':'student'" v-if="currentTemplateUrl"> </PositionCanvas>
  58. </div>
  59. </div>
  60. <div class="paper_content">
  61. <div class="content_header">
  62. <div class="header_left">
  63. 答题卡
  64. <span v-if="currentImagePageNo==''" style="color:red;">(当前图片页码未保存)</span>
  65. <span v-else style="color:green;">(当前图片页码已设置为:{{currentImagePageNo}})</span>
  66. </div>
  67. <div class="header_right el_button">
  68. <i class="iconfont icon_nishizhen" @click="AnticlockwiseImage()"></i>
  69. <i class="iconfont icon_shunshizhen" @click="ClockwiseImage()"></i>
  70. <el-button type="primary" class="right_button_editor" @click="MarkBlankPage()">标记为空白页</el-button>
  71. <el-button type="primary" class="right_button_editor" style="margin-left: 0px;" @click="SavePositionImage()">保存</el-button>
  72. </div>
  73. </div>
  74. <div class="content_canvas">
  75. <!-- <PositionCanvas ref="PaperCanvas" :usedCardType="usedCardType" :positionList="targetPoints" :paperImgUrl="currentPaperUrl" @GetCutPosition="GetCutStudentPosition" paperType="student" v-if="currentPaperUrl"> </PositionCanvas> -->
  76. </div>
  77. </div>
  78. </div>
  79. <!-- 考号异常试卷区 -->
  80. <!-- abnormalType:2,//页面异常类型 2-定位异常 3-考号异常 4-客观题异常 5-选做题异常 6-空白卷异常 7 缺页异常 -->
  81. <!-- <div v-if="abnormalType==3 || abnormalType ==6 || abnormalType ==7" class="img_canvas_center">
  82. <ImageCavasShow :paperImgUrl="currentPaperUrl"></ImageCavasShow>
  83. </div> -->
  84. <!-- <div v-if="abnormalType ==4 " class="img_canvas_center">
  85. <ImageCanvas :currentPaperInfo="currentPaperInfo" > </ImageCanvas>
  86. </div> -->
  87. <div v-if="abnormalType==3 || abnormalType ==7 || abnormalType ==4 || abnormalType ==5" class="img_canvas_center">
  88. <ActionImage ref="ActionCanvas" :isDrag="true" :paperInfo="currentPageInfo" :paperImgUrl="currentPaperUrl" :drawData="currentDrawData" :isAbnormal="true"></ActionImage>
  89. </div>
  90. </div>
  91. <div class="page_jg"></div>
  92. <div class="left_bottom" v-if="!(abnormalType==6 && isShowDrawType==2)">
  93. <div class="bottom_draggable draggable_width_100" >
  94. <div v-for="(item,index) in currentPaperList" class="bottom_img_item" :class="currentPaperIndex == index?'img_item_cur':''" @click="ChanageCurrentPaperUrl(index, item)" :key="'paper_'+index">
  95. <img style="width: 100%;height: 100%" :src="item.recognizeUrl" alt="" >
  96. <div class="bottom_img_item_number" v-if="abnormalType==2">{{index+1}}</div>
  97. <div class="bottom_img_item_number" v-else>
  98. <span v-if="item.pageNo>0">{{item.pageNo}}</span>
  99. <span v-else></span>
  100. </div>
  101. </div>
  102. </div>
  103. </div>
  104. </div>
  105. <div class="abnormal_right">
  106. <!-- 定位异常区域 -->
  107. <div class="right_center" v-show="abnormalType==2">
  108. <div class="page_jg_20" ></div>
  109. <div class="right_table">
  110. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" border :data="positionData.pendingList" style="width:100%;" :height="tableHeightRight" align="left" >
  111. <el-table-column align="center" width="40" type="index" label="序号"></el-table-column>
  112. <!-- <el-table-column align="center" prop="batchNo" width="45" label="批次"></el-table-column> -->
  113. <el-table-column align="center" width="65" label="批次">
  114. <template v-slot="scope">
  115. {{GetPositionSelNumber(scope.row)}}
  116. </template>
  117. </el-table-column>
  118. <el-table-column align="center" prop="studentName" label="姓名">
  119. <template v-slot="scope">
  120. <span v-if="scope.row.studentName">{{scope.row.studentName}} </span>
  121. <span v-else>-</span>
  122. </template>
  123. </el-table-column>
  124. <el-table-column align="center" prop="cardNumber" label="考号">
  125. <template v-slot="scope">
  126. <span v-if="scope.row.cardNumber">{{scope.row.cardNumber}} </span>
  127. <span v-else>-</span>
  128. </template>
  129. </el-table-column>
  130. <!-- <el-table-column align="center" prop="examDate" label="班级"></el-table-column> -->
  131. </el-table>
  132. </div>
  133. <div class="right_bottom_button el_button">
  134. <div class="page_jg_20"></div>
  135. <div class="bottom_button_two">
  136. <el-button @click="ReCutPaper()" class="re_cut_btn" :loading="reCutLoading">
  137. {{reCutText}}
  138. </el-button>
  139. <el-button @click="DeleteCurrentPaper()" class="delete_paper_btn">删除当前试卷</el-button>
  140. </div>
  141. <!-- <div class="bottom_button_item">
  142. <el-button @click="recyleMethod" class="recycle_bin_btn">回收站</el-button>
  143. </div> -->
  144. </div>
  145. </div>
  146. <!-- 考号异常区域 -->
  147. <div class="right_center" v-show="abnormalType==3">
  148. <div class="right_table">
  149. <div class="right_title">
  150. 考号异常处理
  151. </div>
  152. <!-- abnormalType 0-正常 1-考号未识别出来 2-无此考生 3-考号重复(1,2,3都代表考号异常) 4-定位异常 5-缺页异常 -->
  153. <el-table ref="numberPendingTable" @row-click="PendingListRowClick" :row-class-name="TableRowClassName" :data="numberData.pendingList" max-height="300" border stripe>
  154. <el-table-column align="center" type="index" width="40" label="序号">
  155. </el-table-column>
  156. <el-table-column align="center" width="65" label="批次">
  157. <template v-slot="scope">
  158. {{GetPositionSelNumber(scope.row)}}
  159. </template>
  160. </el-table-column>
  161. <el-table-column align="center" prop="studentName" width="80" label="姓名">
  162. <template v-slot="scope">
  163. <div v-if="scope.row.studentName" class="table_row_value">
  164. <span class="card_number_repeat" v-if="scope.row.abnormalType==3">重</span> {{scope.row.studentName}}
  165. </div>
  166. <span v-else>-</span>
  167. </template>
  168. </el-table-column>
  169. <el-table-column align="center" prop="cardNumber" label="考号">
  170. <template v-slot="scope">
  171. <span v-if="scope.row.cardNumber" :class="scope.row.abnormalType==2?'card_number_error':''">{{scope.row.cardNumber}} </span>
  172. <span v-else>-</span>
  173. </template>
  174. </el-table-column>
  175. <!-- <el-table-column align="center" prop="schoolClassName" label="班级"></el-table-column> -->
  176. </el-table>
  177. <!-- <el-table :data="numberData.processedList" border max-height="150" v-if="rightTab=='processed'">
  178. <el-table-column align="center" type="index" width="60" label="序号">
  179. </el-table-column>
  180. <el-table-column align="center" prop="studentName" label="姓名"></el-table-column>
  181. <el-table-column align="center" prop="exCode" label="考号"></el-table-column>
  182. <el-table-column align="center" prop="schoolClassName" label="班级"></el-table-column>
  183. </el-table> -->
  184. <div class="right_title">
  185. 查询学生进行认领
  186. </div>
  187. <div class="right_search el_button">
  188. <el-input type="text" style="width: 220px;" @keyup.enter.native="GetSearchStudent" v-model="searchContent" @input="GetSearchStudent" placeholder="学生姓名、考号" >
  189. <el-button slot="append" icon="el-icon-search" style="width:68px;" @click="GetSearchStudent"></el-button>
  190. </el-input>
  191. <el-button class="editor_item" @click="OpenAddStudentDialog" >新增考生</el-button>
  192. </div>
  193. <el-table :data="searchStudetList" border :max-height="searchTableHeight" stripe style="width: 100%;">
  194. <el-table-column align="center" prop="studentName" width="70" label="姓名">
  195. <template v-slot="scope">
  196. <div class="table_row_value" :title="scope.row.studentName">
  197. {{scope.row.studentName}}
  198. </div>
  199. </template>
  200. </el-table-column>
  201. <el-table-column align="center" prop="cardNumber" label="考号" show-overflow-tooltip></el-table-column>
  202. <el-table-column align="center" prop="pageNum" label="页数" width="70" >
  203. <template v-slot="scope">
  204. <div class="table_row_value" >
  205. {{ GetPaperPageNum(scope.row) }}
  206. </div>
  207. </template>
  208. </el-table-column>
  209. <el-table-column align="center" width="90" label="操作">
  210. <template v-slot="scope">
  211. <div class="row_scan_status">
  212. <div class="claim_scan_btn" v-if="scope.row.scanPictureVOS" @click="OpenViewPaper(scope.row)" >
  213. 查看
  214. </div>
  215. <div class="disable_view_btn" v-else>
  216. 查看
  217. </div>
  218. <div class="claim_scan_btn" @click="KaohaoClaimConfirm(scope)">
  219. 认领
  220. </div>
  221. </div>
  222. </template>
  223. </el-table-column>
  224. </el-table>
  225. </div>
  226. <div class="right_bottom_button el_button">
  227. <div class="page_jg_20"></div>
  228. <div class="bottom_button_two">
  229. <!-- <el-button class="re_cut_btn" @click="OpenAddStudentDialog" >新增考生</el-button> -->
  230. <el-button @click="MarkPositionAbnormal" class="abnormal_other_btn">标记定位异常</el-button>
  231. <el-button @click="DeleteCurrentPaper()" class="delete_paper_btn">删除当前试卷</el-button>
  232. </div>
  233. </div>
  234. </div>
  235. <!-- 缺页异常区域 -->
  236. <div class="right_center" v-show="abnormalType==7">
  237. <div class="page_jg_20" ></div>
  238. <div class="right_table">
  239. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" border :data="losePageData.pendingList" stripe :height="losePagetableHeight" align="left" >
  240. <el-table-column align="center" width="60" type="index" label="序号"></el-table-column>
  241. <el-table-column align="center" width="55" label="批次">
  242. <template v-slot="scope">
  243. {{GetPositionSelNumber(scope.row)}}
  244. </template>
  245. </el-table-column>
  246. <el-table-column align="center" prop="studentName" width="70" label="姓名">
  247. <template v-slot="scope">
  248. <span v-if="scope.row.studentName">{{scope.row.studentName}} </span>
  249. <span v-else>-</span>
  250. </template>
  251. </el-table-column>
  252. <el-table-column align="center" prop="cardNumber" label="考号">
  253. <template v-slot="scope">
  254. <span v-if="scope.row.cardNumber">{{scope.row.cardNumber}} </span>
  255. <span v-else>-</span>
  256. </template>
  257. </el-table-column>
  258. <el-table-column align="center" prop="examDate" width="40" label="页数">
  259. <template v-slot="scope">
  260. <span v-if="scope.row.scanPictureVOS">{{scope.row.scanPictureVOS.length}} </span>
  261. <span v-else>-</span>
  262. </template>
  263. </el-table-column>
  264. </el-table>
  265. </div>
  266. <div class="right_bottom_button el_button">
  267. <div class="page_jg_20"></div>
  268. <div class="bottom_button_two">
  269. <el-button @click="MarkPositionAbnormal" class="abnormal_other_btn">标记定位异常</el-button>
  270. <el-button @click="MarkExamNumberAbnormal" class="abnormal_other_btn">标记考号异常</el-button>
  271. </div>
  272. <div class="bottom_button_item">
  273. <!-- <el-button @click="recyleMethod" class="recycle_bin_btn">回收站</el-button> -->
  274. <!-- 缺页异常删除 需要用delete_batch_pic 接口 -->
  275. <el-button @click="LosePageDelete()" class="delete_paper_btn_100">删除当前试卷</el-button>
  276. </div>
  277. </div>
  278. </div>
  279. <!-- 客观题异常区域 -->
  280. <div class="right_center" v-show="abnormalType==4">
  281. <!-- 已处理未开发完成 暂时先屏蔽切换 -->
  282. <div class="right_user_tab">
  283. <div class="tab_system_user" :class="rightTab == 'pending'?'select_cur':''" @click="ChangeTab('pending')">
  284. 待处理({{objectData.pendingList.length}})
  285. </div>
  286. <div class="tab_temporay_user" :class="rightTab == 'processed'?'select_cur':''" @click="ChangeTab('processed')">
  287. 已处理({{objectData.processedList.length}})
  288. </div>
  289. </div>
  290. <div class="page_jg_20"></div>
  291. <div class="right_table" ref="objectQuestionTable">
  292. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" :data="objectData.pendingList" max-height="238" border v-show="rightTab=='pending'">
  293. <el-table-column align="center" type="index" label="序号" width="40"></el-table-column>
  294. <el-table-column align="center" width="55" label="批次">
  295. <template v-slot="scope">
  296. {{GetPositionSelNumber(scope.row)}}
  297. </template>
  298. </el-table-column>
  299. <el-table-column align="center" prop="studentName" width="70" label="姓名" show-overflow-tooltip></el-table-column>
  300. <el-table-column align="center" prop="exCode" label="考号" show-overflow-tooltip></el-table-column>
  301. <el-table-column align="center" prop="adminClassName" width="65" label="班级"></el-table-column>
  302. </el-table>
  303. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" :data="objectData.processedList" border max-height="238" v-show="rightTab=='processed'">
  304. <el-table-column align="center" type="index" width="40" label="序号">
  305. </el-table-column>
  306. <el-table-column align="center" width="55" label="批次">
  307. <template v-slot="scope">
  308. {{GetPositionSelNumber(scope.row)}}
  309. </template>
  310. </el-table-column>
  311. <el-table-column align="center" prop="studentName" width="70" label="姓名" show-overflow-tooltip></el-table-column>
  312. <el-table-column align="center" prop="exCode" label="考号" show-overflow-tooltip></el-table-column>
  313. <el-table-column align="center" prop="adminClassName" width="65" label="班级" show-overflow-tooltip></el-table-column>
  314. </el-table>
  315. <div class="right_title">
  316. <div >客观题异常处理
  317. <span @click="ClearValue()" class="clear_value">清空</span>
  318. </div>
  319. <div ><el-checkbox v-model="isShowAbnormalQuestion" >只显示异常题</el-checkbox></div>
  320. </div>
  321. </div>
  322. <div class="answer_table">
  323. <el-table :data="questionTableData" :height="objectTableHeight" border :row-class-name="ObjectTableClassName" :key="tableKey" >
  324. <el-table-column align="center" prop="objectiveName" label="题号" width="90"></el-table-column>
  325. <el-table-column align="center" prop="studentName" label="选项">
  326. <template v-slot="scope">
  327. <div class="table_row_answer_choose" v-if="scope.row.questionType==3">
  328. <div class="answer_item" @click="ChooseAnswer(scope.row,GetLetterToNumberTF(item))" :class="IsCunzai(scope.row.selectValue,GetLetterToNumberTF(item))?'choose':''" v-for="(item,index) in scope.row.optionNum" :key="index">
  329. {{GetLetterToNumberTF(item)}}
  330. </div>
  331. </div>
  332. <div class="table_row_answer_choose" v-else>
  333. <div class="answer_item" @click="ChooseAnswer(scope.row,GetLetterToNumber(item))" :class="IsCunzai(scope.row.selectValue,GetLetterToNumber(item))?'choose':''" v-for="(item,index) in scope.row.optionNum" :key="index">
  334. {{GetLetterToNumber(item)}}
  335. </div>
  336. </div>
  337. </template>
  338. </el-table-column>
  339. </el-table>
  340. </div>
  341. <!-- <answerPaper :questionList="currentQuestionList" @selectClick="selectClick"></answerPaper> -->
  342. <div class="right_bottom_button el_button">
  343. <div class="bottom_button_two">
  344. <el-button @click="MarkPositionAbnormal" class="abnormal_other_btn">标记定位异常</el-button>
  345. <el-button @click="ObjectiveCheck" class="re_cut_btn" :loading="correctionLoading">校正完成</el-button>
  346. </div>
  347. </div>
  348. </div>
  349. <!-- 选做题异常区域 -->
  350. <div class="right_center" v-show="abnormalType==5">
  351. <!-- 已处理未开发完成 暂时先屏蔽切换 -->
  352. <div class="right_user_tab">
  353. <div class="tab_system_user" :class="rightTab == 'pending'?'select_cur':''" @click="ChangeTab('pending')">
  354. 待处理({{choiceData.pendingList.length}})
  355. </div>
  356. <div class="tab_temporay_user" :class="rightTab == 'processed'?'select_cur':''" @click="ChangeTab('processed')">
  357. 已处理({{choiceData.processedList.length}})
  358. </div>
  359. </div>
  360. <div class="page_jg_20" ></div>
  361. <div class="right_table">
  362. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" border :data="choiceData.pendingList" max-height="238" stripe v-show="rightTab=='pending'">
  363. <el-table-column align="center" width="60" type="index" label="序号"></el-table-column>
  364. <!-- <el-table-column align="left" prop="examName" label="批次"></el-table-column> -->
  365. <el-table-column align="center" prop="studentName" label="姓名"></el-table-column>
  366. <el-table-column align="center" prop="exCode" label="考号"></el-table-column>
  367. <el-table-column align="center" prop="adminClassName" label="班级"></el-table-column>
  368. </el-table>
  369. <el-table @row-click="PendingListRowClick" :data="choiceData.processedList" :row-class-name="TableRowClassName" border v-show="rightTab=='processed'" max-height="238" stripe >
  370. <el-table-column align="center" type="index" width="60" label="序号">
  371. </el-table-column>
  372. <el-table-column align="center" prop="studentName" label="姓名"></el-table-column>
  373. <el-table-column align="center" prop="exCode" label="考号"></el-table-column>
  374. <el-table-column align="center" prop="adminClassName" label="班级"></el-table-column>
  375. </el-table>
  376. <div class="right_title">
  377. <div>选做题异常处理</div>
  378. <!-- <div ><el-checkbox v-model="isShowAbnormalQuestion" @change="ChanageObjectQuestionShow">只显示异常题</el-checkbox></div> -->
  379. </div>
  380. </div>
  381. <div class="answer_table">
  382. <el-table :data="choiceData.choiceQuestion" border :row-class-name="ObjectTableClassName" :key="tableKey" width="100%">
  383. <el-table-column align="center" prop="topicName" label="题号" ></el-table-column>
  384. <el-table-column align="center" :label="'选做'+choice" v-for="(choice,index) in choiceHeader" :key="index" >
  385. <template v-slot="scope">
  386. <div class="table_row_answer_choose" style="justify-content:center !important;">
  387. <!-- <div class="answer_item" :class="scope.row.selectValue==scope.row.answerVOS[index].option?'choose':''" @click="ChoiceAnswer(scope.row,scope.row.answerVOS[index].option)">
  388. {{GetLetterToNumber(scope.row.answerVOS[index].option)}}
  389. </div> -->
  390. <!-- 添加判断,确保 answerVOS[index] 存在 -->
  391. <div v-if="scope.row.answerVOS && scope.row.answerVOS[index]"
  392. class="answer_item"
  393. :class="scope.row.selectValue==scope.row.answerVOS[index].option?'choose':''"
  394. @click="ChoiceAnswer(scope.row,scope.row.answerVOS[index].option)">
  395. {{GetLetterToNumber(scope.row.answerVOS[index].option)}}
  396. </div>
  397. <div v-else>-</div> <!-- 当没有对应选项时显示占位符 -->
  398. </div>
  399. </template>
  400. </el-table-column>
  401. </el-table>
  402. </div>
  403. <div class="right_bottom_button el_button">
  404. <div class="bottom_button_two">
  405. <el-button @click="MarkPositionAbnormal" class="abnormal_other_btn">标记定位异常</el-button>
  406. <el-button @click="ChoiceCheck" class="re_cut_btn" :loading="correctionLoading">校正完成</el-button>
  407. </div>
  408. </div>
  409. </div>
  410. <!-- 划分异常区域 -->
  411. <div class="right_center" v-show="abnormalType==6">
  412. <!-- 已处理未开发完成 暂时先屏蔽切换 -->
  413. <div class="right_user_tab">
  414. <div class="tab_system_user" :class="rightTab == 'pending'?'select_cur':''" @click="ChangeTab('pending')">
  415. 待处理({{subjectiveData.pendingList.length}})
  416. </div>
  417. <div class="tab_temporay_user" :class="rightTab == 'processed'?'select_cur':''" @click="ChangeTab('processed')">
  418. 已处理({{subjectiveData.processedList.length}})
  419. </div>
  420. </div>
  421. <div class="page_jg_20" ></div>
  422. <div class="right_table" ref="subjectiveQuestionTable">
  423. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" border :data="subjectiveData.pendingList" style="width:100%;" max-height="238" v-show="rightTab=='pending'" stripe align="left">
  424. <el-table-column align="center" type="index" label="序号" width="40"></el-table-column>
  425. <el-table-column align="center" width="55" label="批次">
  426. <template v-slot="scope">
  427. {{GetPositionSelNumber(scope.row)}}
  428. </template>
  429. </el-table-column>
  430. <el-table-column align="center" prop="studentName" width="70" label="姓名" show-overflow-tooltip></el-table-column>
  431. <el-table-column align="center" prop="exCode" label="考号" show-overflow-tooltip></el-table-column>
  432. <el-table-column align="center" prop="adminClassName" width="65" label="班级"></el-table-column>
  433. </el-table>
  434. <el-table @row-click="PendingListRowClick" :row-class-name="TableRowClassName" :data="subjectiveData.processedList" border max-height="238" v-show="rightTab=='processed'">
  435. <el-table-column align="center" type="index" width="40" label="序号">
  436. </el-table-column>
  437. <el-table-column align="center" width="55" label="批次">
  438. <template v-slot="scope">
  439. {{GetPositionSelNumber(scope.row)}}
  440. </template>
  441. </el-table-column>
  442. <el-table-column align="center" prop="studentName" width="70" label="姓名" show-overflow-tooltip></el-table-column>
  443. <el-table-column align="center" prop="exCode" label="考号" show-overflow-tooltip></el-table-column>
  444. <el-table-column align="center" prop="adminClassName" width="65" label="班级" show-overflow-tooltip></el-table-column>
  445. </el-table>
  446. <div class="right_title">
  447. <div>
  448. 划分异常处理
  449. <!-- <span @click="ClearValue()" class="clear_value">清空</span> -->
  450. </div>
  451. <div v-if="rightTab == 'pending'"><el-checkbox v-model="isShowAbnormalQuestion" @change="SubjectDataChange">只显示异常题</el-checkbox></div>
  452. </div>
  453. </div>
  454. <div class="answer_table">
  455. <el-table :data="subjectiveTableData" :height="subjectiveTableHeight" border :row-class-name="ObjectTableClassName" :key="tableKey" >
  456. <el-table-column align="center" prop="subjectiveName" label="题号" width="90"></el-table-column>
  457. <el-table-column align="center" prop="score" label="得分">
  458. <template v-slot="scope">
  459. <el-input v-model="scope.row.score" :class="parseFloat(scope.row.score)>parseFloat(scope.row.subjectiveScore)?'input_error':''" placeholder="" maxlength="5" @change="ChangeSubjectScore()">
  460. <!-- <div slot="append" class="score_count_append">
  461. {{scope.row.questionScore || 10.5}}
  462. </div> -->
  463. </el-input>
  464. </template>
  465. </el-table-column>
  466. </el-table>
  467. </div>
  468. <div class="right_bottom_button el_button">
  469. <div class="bottom_button_two">
  470. <el-button @click="MarkPositionAbnormal" class="abnormal_other_btn">标记定位异常</el-button>
  471. <el-button @click="SubjectiveCheck" class="re_cut_btn" :loading="correctionLoading">校正完成</el-button>
  472. </div>
  473. </div>
  474. </div>
  475. </div>
  476. </div>
  477. </template>
  478. <script lang="ts" setup>
  479. import { useExamStore } from '@/store/exam'
  480. import { useRouter } from 'vue-router'
  481. import { onMounted,onUnmounted, ref, computed, nextTick, watch } from 'vue';
  482. import { ElMessage,ElMessageBox } from 'element-plus'
  483. // 引入可能需要的 API (请根据实际路径调整)
  484. import { getExamAbnormalList,getSearchScanStudents,claimAnswerCard, updateAbnormalStatus,markPositionAbnormal, deletePaper } from '@/api/exam'
  485. // 引入子组件 (确保路径正确)
  486. // import PositionCanvas from './components/PositionCanvas.vue' // 假设路径
  487. import ActionImage from '@/components/ActionImage.vue'// 画布图片组件
  488. // import MarkScore from './components/MarkScore.vue' // 假设路径
  489. // 实例化 Store
  490. const examStore = useExamStore()
  491. const router = useRouter()
  492. // ==================== 考试通用数据(可追加)====================
  493. // 考试科目 ID
  494. const examSubjectId = computed(() => {
  495. return examStore.currentExam?.id
  496. })//计算属性
  497. const schoolId = computed(() => {
  498. return 0;
  499. })//学校id
  500. //考试科目code
  501. const examSubjectCode=computed(() => {
  502. return examStore.currentExam?.examSubjectCode
  503. })
  504. // ==================== 状态定义 ====================
  505. // 异常类型: 2-定位异常 3-考号异常 4-客观题异常 5-选做题异常 6-划分异常(空白卷) 7-缺页异常
  506. const abnormalType = ref(2)
  507. const markType = ref(0) // 0-网阅卡 1-手阅卡
  508. // 异常统计数据
  509. const abnormalObj = ref({
  510. locationErrorNum: 0, // 定位异常数
  511. examNumberErrorNum: 0, // 考号异常数
  512. losePageErrorNum: 0, // 缺页异常数
  513. objectErrorNum: 0, // 客观题异常数
  514. choiceErrorNum: 0, // 选做题异常数
  515. subjectiveErrorNum: 0 // 划分异常数
  516. })
  517. // 左侧导航/显示控制
  518. const isShowDraw = ref(false) // 客观题是否显示画框
  519. const isShowDrawType = ref(1) // 划分异常显示类型: 1-答题卡 2-划分区
  520. const isShowAbnormalQuestion = ref(false) // 是否只显示异常题
  521. // 图片与Canvas相关 试卷图片相关数据
  522. const currentIndex= ref(0);//当前表格学生索引
  523. const currentItem= ref<any>({});//当前表格学生数据
  524. const currentTemplateUrl = ref('')//试卷图片模板地址
  525. const currentPaperUrl = ref('')//试卷图片地址
  526. const currentImagePageNo = ref('')//当前图片页码
  527. const currentPaperIndex = ref(0)//当前图片索引
  528. const currentTemplatePageIndex = ref(0)////当前模板页索引
  529. const currentDrawData= ref<any[]>([]);//画框数据
  530. const currentPaperList = ref<any[]>([]) // 底部缩略图列表
  531. const currentPageInfo = ref<any>({}) // 当前页面信息
  532. // 定位异常相关
  533. const usedCardType = ref(1) // 1-模板 2-学生
  534. const sourcePoints = ref<any[]>([]) // 模板点位
  535. const targetPoints = ref<any[]>([]) // 学生点位
  536. const currentTemplateList = ref<any[]>([]) // 模板页码列表
  537. // 右侧表格数据
  538. const positionData = ref({ pendingList: [] }) // 定位异常待处理
  539. const numberData = ref({ pendingList: [], processedList: [] }) // 考号异常
  540. const losePageData = ref({ pendingList: [] }) // 缺页异常
  541. const objectData = ref({ pendingList: [], processedList: [] }) // 客观题异常
  542. const choiceData = ref({ pendingList: [], processedList: [], choiceQuestion: [] }) // 选做题异常
  543. const subjectiveData = ref({ pendingList: [], processedList: [] }) // 划分异常
  544. // 搜索与查询
  545. const searchContent = ref('')//卡号异常搜索关键词
  546. const searchStudetList = ref<any[]>([])//考号异常搜索结果列表
  547. // 用于取消请求的控制器
  548. let searchAbortController: AbortController | null = null;
  549. const searchTimer=ref<number | null>(null);//搜索请求定时器;//搜索请求定时器
  550. const searchTimestamp=0;//search请求时间戳
  551. // 表格高度与Key
  552. const tableHeightRight = ref(200)//定位表格高度
  553. const losePagetableHeight = ref(200)
  554. const searchTableHeight = ref(200)
  555. const objectTableHeight = ref(200)
  556. const subjectiveTableHeight = ref(200)
  557. const tableKey = ref(0)
  558. // 其他状态
  559. const rightTab = ref('pending') // pending | processed
  560. const reCutLoading = ref(false)
  561. const reCutText = ref('重新切割')
  562. const correctionLoading = ref(false)
  563. const subjectStudentIndex = ref(-1)
  564. const subjectStudentAbnormal = ref<any[]>([])
  565. const subjectStudentQuestion = ref<any[]>([])
  566. const questionTableData = ref<any[]>([])
  567. const subjectiveTableData = ref<any[]>([])
  568. const choiceHeader = ref([])
  569. // Canvas Refs
  570. const PositionCanvas = ref()
  571. const PaperCanvas = ref()
  572. const ActionCanvas = ref()
  573. // ==================== 计算属性 ====================
  574. // 示例:如果需要动态计算某些表格数据
  575. const pendingListComputed = computed(() => {
  576. if (abnormalType.value === 2) return positionData.value.pendingList
  577. if (abnormalType.value === 3) return numberData.value.pendingList
  578. if (abnormalType.value === 7) return losePageData.value.pendingList
  579. if (abnormalType.value === 4) return rightTab.value === 'pending' ? objectData.value.pendingList : objectData.value.processedList
  580. if (abnormalType.value === 5) return rightTab.value === 'pending' ? choiceData.value.pendingList : choiceData.value.processedList
  581. if (abnormalType.value === 6) return rightTab.value === 'pending' ? subjectiveData.value.pendingList : subjectiveData.value.processedList
  582. return []
  583. })
  584. // ==================== 方法定义 ====================
  585. // 1. 切换异常类型
  586. const AbnormalChanage = (type: number) => {
  587. abnormalType.value = type
  588. // TODO: 加载对应类型的异常列表数据
  589. console.log('切换异常类型:', type)
  590. //考号异常 3
  591. if(type==3)
  592. {
  593. console.log('考号异常',numberData.value)
  594. if(numberData.value.pendingList.length>0)
  595. {
  596. currentIndex.value=0;
  597. currentItem.value=numberData.value.pendingList[currentIndex.value];//当前学生数据
  598. currentPaperList.value=currentItem.value.scanPictureVOS || [];//试卷图片列表
  599. currentPaperUrl.value=currentPaperList.value[0].recognizeUrl;//当前图片地址
  600. currentImagePageNo.value=currentPaperList.value[0].pageNo;//当前图片的页码
  601. }
  602. }
  603. }
  604. // 2. 刷新异常列表
  605. const RefreshAbnormalList = () => {
  606. // TODO: 调用接口刷新当前 abnormalType 的数据
  607. console.log('刷新列表')
  608. }
  609. // 3. 适应屏幕
  610. const FitScreen = () => {
  611. // TODO: 调用 ActionImage 或 Canvas 组件的 fit 方法
  612. console.log('适应屏幕')
  613. }
  614. // 4. 显示/隐藏画框 (客观题)
  615. const ShowDrawData = () => {
  616. isShowDraw.value = !isShowDraw.value
  617. // TODO: 更新 ActionImage 的 drawData 显示状态
  618. }
  619. // 5. 划分异常显示类型切换
  620. const SubjectDataChange = () => {
  621. // TODO: 根据 isShowDrawType 重新渲染右侧列表或 Canvas
  622. console.log('切换显示类型:', isShowDrawType.value)
  623. }
  624. // 6. 模板页码切换
  625. const ChangeTemplatePage = (item: any) => {
  626. currentTemplatePageIndex.value = item.pageNum
  627. // TODO: 加载对应页码的模板图片
  628. }
  629. // 7. 获取切割点位 (模板)
  630. const GetCutTemaplatePosition = (points: any[]) => {
  631. sourcePoints.value = points
  632. console.log('获取模板点位', points)
  633. }
  634. // 8. 获取切割点位 (学生)
  635. const GetCutStudentPosition = (points: any[]) => {
  636. targetPoints.value = points
  637. console.log('获取学生点位', points)
  638. }
  639. // 9. 图片旋转
  640. const AnticlockwiseImage = () => {
  641. // TODO: 逆时针旋转
  642. console.log('逆时针旋转')
  643. }
  644. const ClockwiseImage = () => {
  645. // TODO: 顺时针旋转
  646. console.log('顺时针旋转')
  647. }
  648. // 10. 标记为空白页
  649. const MarkBlankPage = () => {
  650. // TODO: 调用接口标记当前试卷为空白页
  651. console.log('标记空白页')
  652. }
  653. // 11. 保存定位信息
  654. const SavePositionImage = () => {
  655. // TODO: 提交 sourcePoints 和 targetPoints 到后端
  656. console.log('保存定位')
  657. }
  658. // 12. 底部缩略图切换
  659. const ChanageCurrentPaperUrl = (index: number, item: any) => {
  660. currentPaperIndex.value = index
  661. currentPaperUrl.value = item.recognizeUrl
  662. currentPageInfo.value = item
  663. // TODO: 加载新试卷的详细数据
  664. }
  665. // 13. 右侧表格行点击
  666. const PendingListRowClick = (row: any, column: any, event: Event) => {
  667. // TODO: 高亮选中行,并加载该学生的试卷图片到左侧
  668. console.log('点击行:', row)
  669. if(abnormalType.value==2)
  670. {
  671. }
  672. //考号异常
  673. if(abnormalType.value==3)
  674. {
  675. currentItem.value=row;
  676. currentPaperList.value=currentItem.value.scanPictureVOS || [];//试卷图片列表
  677. currentPaperUrl.value=currentPaperList.value[0].recognizeUrl;//当前图片地址
  678. currentImagePageNo.value=currentPaperList.value[0].pageNo;//当前图片的页码
  679. }
  680. }
  681. // 14. 表格行样式
  682. const TableRowClassName = ({ row, rowIndex }: any) => {
  683. // TODO: 根据 row 的状态返回 class 字符串
  684. //定位异常和考号异常 都以 wholePaperId 为判断条件
  685. if(abnormalType.value==2 || abnormalType.value==3)
  686. {
  687. if(row.wholePaperId==currentItem.value.wholePaperId)
  688. {
  689. return 'selected_row'
  690. }
  691. else
  692. {
  693. return ''
  694. }
  695. }
  696. //客观题异常 以id 为判断条件
  697. if(abnormalType.value==4 )
  698. {
  699. if(row.id==currentItem.value.id)
  700. {
  701. return 'selected_row'
  702. }
  703. else
  704. {
  705. return ''
  706. }
  707. }
  708. return ''
  709. }
  710. // 14. 客观题表格行样式
  711. const ObjectTableClassName=({ row, rowIndex }: any) => {
  712. }
  713. // 15. 获取批次号显示
  714. const GetPositionSelNumber = (row: any) => {
  715. // TODO: 格式化批次号
  716. return row.batchNo || '-'
  717. }
  718. // 16. 重新切割 (定位异常)
  719. const ReCutPaper = () => {
  720. reCutLoading.value = true
  721. // TODO: 调用重新切割接口
  722. setTimeout(() => {
  723. reCutLoading.value = false
  724. ElMessage.success('切割成功')
  725. }, 1000)
  726. }
  727. // 17. 删除当前试卷
  728. const DeleteCurrentPaper = () => {
  729. // TODO: 二次确认后删除
  730. console.log('删除试卷',currentItem.value)
  731. ElMessageBox.confirm('确认删除该试卷吗?', '提示', {
  732. confirmButtonText: '确定',
  733. cancelButtonText: '取消',
  734. type: 'warning',
  735. customClass: 'page_dialog',
  736. }).then(async () => {
  737. const param={
  738. examSubjectId:examSubjectId.value,//考试科目id
  739. pictureIds:currentItem.value.scanPictureVOS.map((item: { id: any }) => item.id),//图片id列表
  740. batchNo:currentItem.value.batchNo,//批次号
  741. schoolId:schoolId.value,//学校id
  742. };
  743. const res = await deletePaper(param)
  744. console.log('删除试卷结果:', res)
  745. if(res.code==200)
  746. {
  747. ElMessage.success('删除成功')
  748. GetAbnormalList();
  749. }
  750. else
  751. {
  752. ElMessage.error(res.msg);
  753. }
  754. })
  755. }
  756. // 18. 考号异常 - 搜索学生
  757. const GetSearchStudent = () => {
  758. // TODO: 根据 searchContent 搜索学生列表
  759. console.log('考号搜索学生:', searchContent.value)
  760. //清除之前的定时器
  761. if(searchTimer.value)
  762. {
  763. clearTimeout(searchTimer.value);
  764. }
  765. //如果搜索的内容为空,清空结果并返回
  766. if (!searchContent.value.trim()) {
  767. searchStudetList.value = [];
  768. return;
  769. }
  770. // 防抖处理:300ms 后执行搜索
  771. searchTimer.value = setTimeout(() => {
  772. GetSearchScanStudentList();
  773. }, 300);
  774. }
  775. // 搜索学生列表
  776. const GetSearchScanStudentList = async () => {
  777. const keyword = searchContent.value.trim();
  778. // 如果内容为空,清空列表并返回
  779. if (!keyword) {
  780. searchStudetList.value = [];
  781. return;
  782. }
  783. //1. 取消上一次未完成的请求
  784. if (searchAbortController) {
  785. searchAbortController.abort();
  786. }
  787. // 2. 创建新的 AbortController
  788. searchAbortController = new AbortController();
  789. const signal = searchAbortController.signal;
  790. const param = {
  791. examSubjectId: examSubjectId.value,
  792. chooseCode:'2',//是学号还是考号
  793. studentName: keyword,
  794. schoolId: schoolId.value,
  795. };
  796. console.log("打印通用查询学生列表的参数", param);
  797. try {
  798. // 3. 发起请求,传入 signal
  799. const res = await getSearchScanStudents(param, { signal });
  800. // 4. 处理成功响应
  801. if (res.code === 200) {
  802. searchStudetList.value = res.data || [];
  803. }
  804. } catch (error: any) {
  805. // 5. 处理错误
  806. if (error.name === 'CanceledError' || error.message === 'The operation was aborted.') {
  807. // 请求被取消,通常不需要做任何操作,静默忽略
  808. console.log('之前的搜索请求已取消');
  809. } else {
  810. console.error('搜索学生列表失败:', error);
  811. }
  812. }
  813. };
  814. // 19. 考号异常 - 新增考生
  815. const OpenAddStudentDialog = () => {
  816. // TODO: 打开新增弹窗
  817. console.log('新增考生')
  818. }
  819. // 20. 考号异常 - 查看试卷
  820. const OpenViewPaper = (row: any) => {
  821. // TODO: 预览该学生的试卷
  822. console.log('查看试卷:', row)
  823. }
  824. // 21. 考号异常 - 认领
  825. const KaohaoClaimConfirm = (scope: any) => {
  826. // TODO: 确认认领逻辑
  827. if (!currentItem.value?.wholePaperId) {
  828. ElMessage.warning('请选择待处理的异常!')
  829. return
  830. }
  831. ElMessageBox.confirm('确定要认领为当前的学生吗?', '提示', {
  832. confirmButtonText: '确定',
  833. cancelButtonText: '取消',
  834. type: 'warning',
  835. customClass: 'page_dialog',
  836. }).then(async () => {
  837. const pictureIds = currentItem.value.scanPictureVOS.map((item: any) => item.id);
  838. const param = {
  839. pictureIds: pictureIds,
  840. studentScanId: scope.row.id,
  841. }
  842. try {
  843. const res = await claimAnswerCard(param);
  844. console.log("打印认领返回结果", res);
  845. if (res.code === 200) {
  846. ElMessage({
  847. type: 'success',
  848. message: '认领成功'
  849. })
  850. searchContent.value = "";
  851. searchStudetList.value = [];
  852. console.log("打印当前选择的异常数据索引", currentIndex.value);
  853. console.log("打印当前的数据", currentItem.value);
  854. // TODO: 调用 GetAbnormalList 更新考号异常列表数据
  855. GetAbnormalList();
  856. } else {
  857. ElMessage({
  858. type: 'error',
  859. message: res.msg + '!'
  860. })
  861. }
  862. } catch (error) {
  863. console.error('认领失败:', error);
  864. ElMessage({
  865. type: 'error',
  866. message: '认领失败,请重试'
  867. })
  868. }
  869. }).catch(() => {
  870. // 用户取消操作
  871. });
  872. }
  873. // 22. 获取页数
  874. const GetPaperPageNum = (row: any) => {
  875. return row.scanPictureVOS ? row.scanPictureVOS.length : '-'
  876. }
  877. // 23. 标记为定位异常 (从考号/缺页转定位)
  878. const MarkPositionAbnormal = () => {
  879. // TODO: 调用接口修改异常类型
  880. console.log('标记为定位异常',currentItem.value)
  881. ElMessageBox.confirm('是否确定标记为定位异常?', '提示', {
  882. confirmButtonText: '确定',
  883. cancelButtonText: '取消',
  884. closeOnClickModal: false,
  885. customClass: 'page_dialog',
  886. }).then(async () => {
  887. const pictureIds = currentItem.value.scanPictureVOS.map((item: { id: any }) => item.id);
  888. const param = {
  889. pictureIds: pictureIds,
  890. studentScanId: currentItem.value.id || '',
  891. }
  892. try {
  893. const res = await markPositionAbnormal(param);
  894. if (res.code === 200) {
  895. ElMessage({
  896. type: 'success',
  897. message: '已成功标记为定位异常'
  898. });
  899. GetAbnormalList();//获取异常列表
  900. }
  901. else {
  902. ElMessage({
  903. type: 'error',
  904. message: res.msg + '!'
  905. })
  906. }
  907. } catch (error) {
  908. console.error('标记定位异常失败:', error);
  909. }
  910. }).catch(() => {
  911. // 用户取消操作
  912. });
  913. }
  914. // 24. 标记为考号异常 (从缺页转考号)
  915. const MarkExamNumberAbnormal = () => {
  916. // TODO: 调用接口修改异常类型
  917. console.log('标记为考号异常')
  918. }
  919. // 25. 缺页删除
  920. const LosePageDelete = () => {
  921. // TODO: 调用 delete_batch_pic 接口
  922. console.log('缺页删除')
  923. }
  924. // 26. 切换待处理/已处理 Tab
  925. const ChangeTab = (tab: string) => {
  926. rightTab.value = tab
  927. // TODO: 可能需要重新加载数据或过滤
  928. }
  929. // 27. 清空选择 (客观题)
  930. const ClearValue = () => {
  931. // TODO: 清空当前题目的选择
  932. console.log('清空')
  933. }
  934. // 28. 客观题 - 选项转换辅助
  935. const GetLetterToNumber = (letter: string) => {
  936. // A->1, B->2...
  937. return letter.charCodeAt(0) - 64
  938. }
  939. const GetLetterToNumberTF = (letter: string) => {
  940. // T/F 处理
  941. return letter
  942. }
  943. // 29. 客观题 - 判断是否存在
  944. const IsCunzai = (selectValue: any, value: any) => {
  945. // TODO: 判断 selectValue 中是否包含 value
  946. return selectValue === value
  947. }
  948. // 30. 客观题 - 选择答案
  949. const ChooseAnswer = (row: any, value: any) => {
  950. // TODO: 更新 row.selectValue
  951. console.log('选择答案:', value)
  952. }
  953. // 31. 客观题校正完成
  954. const ObjectiveCheck = () => {
  955. correctionLoading.value = true
  956. // TODO: 提交客观题修正结果
  957. setTimeout(() => {
  958. correctionLoading.value = false
  959. ElMessage.success('校正成功')
  960. }, 1000)
  961. }
  962. // 32. 选做题 - 选择答案
  963. const ChoiceAnswer = (row: any, option: any) => {
  964. // TODO: 更新选做题选择
  965. console.log('选做选择:', option)
  966. }
  967. // 33. 选做题校正完成
  968. const ChoiceCheck = () => {
  969. correctionLoading.value = true
  970. // TODO: 提交选做题修正结果
  971. setTimeout(() => {
  972. correctionLoading.value = false
  973. ElMessage.success('校正成功')
  974. }, 1000)
  975. }
  976. // 34. 划分异常 - 得分点击
  977. const GetMarkScoreClickItem = (score: number, item: any, index: number) => {
  978. // TODO: 处理主观题打分
  979. console.log('打分:', score)
  980. }
  981. // 35. 划分异常 - 修改分数
  982. const ChangeSubjectScore = () => {
  983. // TODO: 防抖提交分数修改
  984. console.log('分数变更')
  985. }
  986. // 36. 划分异常校正完成
  987. const SubjectiveCheck = () => {
  988. correctionLoading.value = true
  989. // TODO: 提交主观题修正结果
  990. setTimeout(() => {
  991. correctionLoading.value = false
  992. ElMessage.success('校正成功')
  993. }, 1000)
  994. }
  995. //定位异常数据处理
  996. const PositionAbnormal= () => {
  997. console.log("定位异常数据处理");
  998. }
  999. //初始化重置数据
  1000. const ResetData = () => {
  1001. // rotationAngle.value = 0;
  1002. currentPaperIndex.value=0;
  1003. }
  1004. // ==================== API 请求 ==========
  1005. //通用获取异常列表数据
  1006. const GetAbnormalList = async () => {
  1007. const params={
  1008. examSubjectId: examSubjectId.value,//考试id
  1009. schoolId:schoolId.value,
  1010. };
  1011. const res = await getExamAbnormalList(params);
  1012. console.log("打印异常数据",res);
  1013. if(res.code == 200)
  1014. {
  1015. let examInfoCount={
  1016. unScanned:res.data.unScanned,//未扫描
  1017. examMissNum:res.data.examMissNum,//缺考
  1018. scannedNum:res.data.scannedNum,//已上传
  1019. abnormalNum:res.data.abnormalNum,//异常
  1020. examTotal:res.data.totalNum,//总数
  1021. };
  1022. examStore.setExamInfoCount(examInfoCount);//设置扫描数据信息
  1023. //异常数据处理
  1024. if(res.data.abnormalGroupVO)
  1025. {
  1026. //定位异常处理
  1027. if(res.data.abnormalGroupVO.dwAbnormal)
  1028. {
  1029. positionData.value.pendingList = res.data.abnormalGroupVO.dwAbnormal || [];
  1030. }
  1031. //考号异常处理
  1032. if(res.data.abnormalGroupVO.cardNumberAbnormal)
  1033. {
  1034. numberData.value.pendingList = res.data.abnormalGroupVO.cardNumberAbnormal || [];
  1035. }
  1036. //客观题异常处理
  1037. if(res.data.abnormalGroupVO.objectiveAbnormal)
  1038. {
  1039. objectData.value.pendingList = res.data.abnormalGroupVO.objectiveAbnormal || [];
  1040. objectData.value.processedList = res.data.abnormalGroupVO.dealObjectiveAbnormal || [];
  1041. }
  1042. abnormalObj.value={
  1043. locationErrorNum: positionData.value.pendingList.length, // 定位异常数量
  1044. examNumberErrorNum: numberData.value.pendingList.length, // 考号异常数量
  1045. losePageErrorNum: losePageData.value.pendingList.length, // 缺页异常数量
  1046. objectErrorNum: objectData.value.pendingList.length, // 客观题异常数量
  1047. choiceErrorNum: choiceData.value.pendingList.length, // 选做题异常数量
  1048. subjectiveErrorNum: subjectiveData.value.pendingList.length, // 划分异常数量
  1049. };//异常数据
  1050. console.log("打印异常数据",abnormalObj.value);
  1051. console.log("打印考号异常数据",numberData);
  1052. }
  1053. }
  1054. else
  1055. {
  1056. }
  1057. }
  1058. // ==================== 生命周期 ====================
  1059. onMounted(() => {
  1060. if (!examStore.currentExam) {
  1061. console.warn('当前没有选中的考试信息')
  1062. } else {
  1063. // TODO: 初始化加载异常统计数据
  1064. // LoadAbnormalStats()
  1065. // LoadAbnormalList(abnormalType.value)
  1066. }
  1067. GetAbnormalList();
  1068. // 监听窗口变化调整高度
  1069. window.addEventListener('resize', CalculateTableHeight)
  1070. CalculateTableHeight()
  1071. });
  1072. // 组件卸载时清理,防止内存泄漏
  1073. onUnmounted(() => {
  1074. if (searchAbortController) {
  1075. searchAbortController.abort();
  1076. }
  1077. //清除之前的定时器
  1078. if(searchTimer.value)
  1079. {
  1080. clearTimeout(searchTimer.value);
  1081. }
  1082. });
  1083. //计算表格高度
  1084. const CalculateTableHeight = () => {
  1085. nextTick(() => {
  1086. tableHeightRight.value = window.innerHeight - 220;
  1087. // 其他高度同理
  1088. })
  1089. }
  1090. </script>
  1091. <style lang="scss" scoped>
  1092. .content_main
  1093. {
  1094. height: 100% !important;
  1095. }
  1096. </style>