clOfflineExam.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. #include "clOfflineExam.h"
  2. #include "ui_clOfflineExam.h"
  3. #include "CAppInfo.h"
  4. #include "clOperation.h"
  5. #include "awMsgBox.h"
  6. #include <QScrollBar>
  7. #include <QFileDialog>
  8. clOfflineExam::clOfflineExam(QWidget *parent) :
  9. QWidget(parent),
  10. ui(new Ui::clOfflineExam)
  11. {
  12. ui->setupUi(this);
  13. setStyleSheet(g_appInfoPtr->m_sQssStr);
  14. qRegisterMetaType<CGetOfflineCourse>("CGetOfflineCourse");
  15. connect(g_httpBllPtr.get(), &CHttpBll::sgnGetOfflineCourse, this, &clOfflineExam::onGetOfflineCourse);
  16. qRegisterMetaType<CGetOffLineExamAnswerSheet>("CGetOffLineExamAnswerSheet");
  17. connect(g_httpBllPtr.get(), &CHttpBll::sgnGetOffLineExamAnswerSheet, this, &clOfflineExam::onGetOffLineExamAnswerSheet);
  18. qRegisterMetaType<CStartOfflineExam>("CStartOfflineExam");
  19. connect(g_httpBllPtr.get(), &CHttpBll::sgnStartOfflineExam, this, &clOfflineExam::onStartOfflineExam);
  20. qRegisterMetaType<CGetOffLineExamPaper>("CGetOffLineExamPaper");
  21. connect(g_httpBllPtr.get(), &CHttpBll::sgnGetOffLineExamPaper, this, &clOfflineExam::onGetOffLineExamPaper);
  22. qRegisterMetaType<CPreviewOffLineExamPaper>("CPreviewOffLineExamPaper");
  23. connect(g_httpBllPtr.get(), &CHttpBll::sgnPreviewOffLineExamPaper, this, &clOfflineExam::onPreviewOffLineExamPaper);
  24. qRegisterMetaType<CGetExamProperty>("CGetExamProperty");
  25. connect(g_httpBllPtr.get(), &CHttpBll::sgnGetExamProperty, this, &clOfflineExam::onGetExamProperty);
  26. qRegisterMetaType<CDownLoadFileInfo>("CDownLoadFileInfo");
  27. connect(g_httpBllPtr.get(), &CHttpBll::sgnDownLoadFile, this, &clOfflineExam::onDownLoadFile);
  28. }
  29. clOfflineExam::~clOfflineExam()
  30. {
  31. delete ui;
  32. }
  33. void clOfflineExam::setUI(const int nWidth, const int nHeight)
  34. {
  35. setGeometry(0, 0, nWidth, nHeight);
  36. ui->widget_offlineExam->setGeometry(0, 0, width(), height());
  37. ui->widget_op_top->setGeometry(0, 0, width(), g_appInfoPtr->m_fRate*72);
  38. ui->btn_downloadAnswerSheet->setGeometry(ui->widget_op_top->width() - g_appInfoPtr->m_fRate*30 - g_appInfoPtr->m_fRate*144,
  39. (ui->widget_op_top->height() - g_appInfoPtr->m_fRate*32)/2,
  40. g_appInfoPtr->m_fRate*144, g_appInfoPtr->m_fRate*32);
  41. ui->btn_downloadAnswerSheet->setVisible(false);
  42. ui->btn_downloadAnswerSheet->setIconSize(QSize(g_appInfoPtr->m_fRate*14, g_appInfoPtr->m_fRate*14));
  43. ui->btn_downloadAnswerSheet->setIcon(QIcon(":/images/icon-download-answer-sheet.png"));
  44. ui->tablewt_examList->setGeometry(g_appInfoPtr->m_fRate*30, ui->widget_op_top->height() + g_appInfoPtr->m_fRate*10,
  45. ui->widget_offlineExam->width() - g_appInfoPtr->m_fRate*30*2,
  46. ui->widget_offlineExam->height() - ui->widget_op_top->height() - g_appInfoPtr->m_fRate*(10 + 62));
  47. ui->tablewt_examList->setEditTriggers(QAbstractItemView::NoEditTriggers);
  48. //整行选中的方式
  49. ui->tablewt_examList->setSelectionBehavior(QAbstractItemView::SelectRows);
  50. //设置为只能选中一行
  51. ui->tablewt_examList->setSelectionMode(QAbstractItemView::SingleSelection);
  52. //隐藏列表头
  53. ui->tablewt_examList->verticalHeader()->setVisible(false);
  54. //隐藏边框
  55. ui->tablewt_examList->setShowGrid(false);
  56. //表头不高亮显示
  57. ui->tablewt_examList->horizontalHeader()->setHighlightSections(false);
  58. //设置行数
  59. ui->tablewt_examList->setRowCount(10);
  60. //设置列数
  61. ui->tablewt_examList->setColumnCount(5);
  62. ui->tablewt_examList->setHorizontalScrollMode(QTableWidget::ScrollPerPixel);
  63. ui->tablewt_examList->horizontalScrollBar()->setSingleStep(g_appInfoPtr->m_fRate*5);
  64. QStringList sHeadStr;
  65. sHeadStr << QString::fromLocal8Bit("课程") <<
  66. QString::fromLocal8Bit("专业") <<
  67. QString::fromLocal8Bit("进入考试时间") <<
  68. QString::fromLocal8Bit("状态") <<
  69. QString::fromLocal8Bit("操作");
  70. ui->tablewt_examList->setHorizontalHeaderLabels(sHeadStr);
  71. ui->tablewt_examList->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
  72. ui->tablewt_examList->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
  73. ui->tablewt_examList->verticalHeader()->setDefaultSectionSize(g_appInfoPtr->m_fRate*48);
  74. ui->tablewt_examList->setColumnWidth(0, g_appInfoPtr->m_fRate*240);
  75. ui->tablewt_examList->setColumnWidth(1, g_appInfoPtr->m_fRate*220);
  76. ui->tablewt_examList->setColumnWidth(2, g_appInfoPtr->m_fRate*340);
  77. ui->tablewt_examList->setColumnWidth(3, g_appInfoPtr->m_fRate*90);
  78. ui->tablewt_examList->setColumnWidth(4, g_appInfoPtr->m_fRate*232);
  79. ui->tablewt_examList->horizontalHeader()->setStretchLastSection(true);
  80. }
  81. void clOfflineExam::showEvent(QShowEvent *)
  82. {
  83. CHttpRequestPackage hrp1;
  84. hrp1.sUri = "/api/ecs_core/org/getAnswersUrl/" + g_appInfoPtr->m_sRootOrgId;
  85. hrp1.nRequestType = RequestType::rtGetOffLineExamAnswerSheet;
  86. g_httpBllPtr->get(hrp1);
  87. CHttpRequestPackage hrp;
  88. hrp.sUri = "/api/ecs_oe_admin/client/exam/process/getOfflineCourse";
  89. hrp.nRequestType = RequestType::rtGetOfflineCourse;
  90. g_httpBllPtr->post(hrp);
  91. }
  92. void clOfflineExam::onGetOfflineCourse(CGetOfflineCourse getOfflineCourse)
  93. {
  94. if (getOfflineCourse.nCode == 200)
  95. {
  96. int nSize = getOfflineCourse.vOfflineCourseInfo.size();
  97. for (int i = 0; i < nSize; ++i)
  98. {
  99. COfflineCourseInfo oci = getOfflineCourse.vOfflineCourseInfo[i];
  100. ui->tablewt_examList->setItem(i, 0, new QTableWidgetItem(oci.sCourseName));
  101. ui->tablewt_examList->setItem(i, 1, new QTableWidgetItem(oci.sSpecialtyName));
  102. ui->tablewt_examList->setItem(i, 2, new QTableWidgetItem(QString::fromLocal8Bit("%1 ~ %2").arg(oci.sStartTime).arg(oci.sEndTime)));
  103. CL_OPERATION_TYPE sAnswerStatus = CL_OPERATION_TYPE::cot_offline_status_null;
  104. CL_OPERATION_TYPE otStatus = CL_OPERATION_TYPE::cot_offline_init_exam;
  105. if (!oci.sStatus.isEmpty())
  106. {
  107. otStatus = CL_OPERATION_TYPE::cot_offline_exam;
  108. if (oci.vOfflineFileInfo.size() > 0)
  109. {
  110. sAnswerStatus = CL_OPERATION_TYPE::cot_offline_status_download;
  111. }
  112. }
  113. clOperation *cloStatus = new clOperation(i, ui->tablewt_examList);
  114. connect(cloStatus, &clOperation::downloadOfflineAnswer, this, [&](int nRow){
  115. QString sExportDir = QFileDialog::getExistingDirectory(
  116. this, QString::fromLocal8Bit("选择导出目录"),
  117. "/");
  118. if (sExportDir.isEmpty())
  119. {
  120. return;
  121. }
  122. //导出
  123. if (sExportDir.right(1) != "/")
  124. {
  125. sExportDir += "/";
  126. }
  127. COfflineCourseInfo oci = m_vOfflineCourseInfo[nRow];
  128. for (COfflineFileInfo &fileInfo : oci.vOfflineFileInfo)
  129. {
  130. QString sFileName = fileInfo.sOfflineFileUrl.right(fileInfo.sOfflineFileUrl.length() - fileInfo.sOfflineFileUrl.lastIndexOf("/") - 1);
  131. QString sAnswerFile = sExportDir + sFileName;
  132. fileInfo.sLocalFileName = sAnswerFile;
  133. CHttpRequestPackage hrp;
  134. hrp.sUri = fileInfo.sOfflineFileUrl;
  135. hrp.sCommonStr = QString("%1,%2").arg(sAnswerFile).arg(QString::number(nRow));
  136. hrp.sCommonStr1 = __FILE__;
  137. hrp.nRequestType = RequestType::rtDownLoadFile;
  138. g_httpBllPtr->downLoad(hrp);
  139. }
  140. });
  141. cloStatus->setUI(ui->tablewt_examList->columnWidth(4), ui->tablewt_examList->rowHeight(i), sAnswerStatus);
  142. ui->tablewt_examList->setCellWidget(i, 3, cloStatus);
  143. clOperation *clo = new clOperation(i, ui->tablewt_examList);
  144. connect(clo, &clOperation::offlineExamStart, this, [&](int nRow){
  145. COfflineCourseInfo oci = m_vOfflineCourseInfo[nRow];
  146. CHttpRequestPackage hrp;
  147. hrp.sUri = "/api/ecs_oe_admin/client/exam/process/startOfflineExam";
  148. hrp.sParamList.push_back(QString("examStudentId,%1").arg(oci.nExamStudentId));
  149. hrp.nRequestType = RequestType::rtStartOfflineExam;
  150. hrp.eParamType = HttpParamType::hptUrl;
  151. hrp.sCommonStr = QString::number(nRow);
  152. g_httpBllPtr->post(hrp);
  153. });
  154. connect(clo, &clOperation::viewOfflinePaper, this, [&](int nRow){
  155. COfflineCourseInfo oci = m_vOfflineCourseInfo[nRow];
  156. CHttpRequestPackage hrp;
  157. hrp.sUri = QString("/api/branch_ecs_ques/paper/%1").arg(oci.sPaperId);
  158. hrp.nRequestType = RequestType::rtPreviewOffLineExamPaper;
  159. hrp.sCommonStr = QString::number(nRow);
  160. g_httpBllPtr->get(hrp);
  161. });
  162. connect(clo, &clOperation::downloadOfflinePaper, this, [&](int nRow){
  163. COfflineCourseInfo oci = m_vOfflineCourseInfo[nRow];
  164. QString sExportDir = QFileDialog::getExistingDirectory(
  165. this, QString::fromLocal8Bit("选择下载目录"),
  166. "/");
  167. if (sExportDir.isEmpty())
  168. {
  169. return;
  170. }
  171. //导出
  172. if (sExportDir.right(1) != "/")
  173. {
  174. sExportDir += "/";
  175. }
  176. QString sPaperFile = sExportDir + oci.sCourseCode + "_" + oci.sCourseName + ".zip";
  177. if (!QFile::exists(sPaperFile))
  178. {
  179. CHttpRequestPackage hrp;
  180. hrp.sUri = QString("/api/branch_ecs_ques/paper/export/%1/PAPER/offLine").arg(oci.sPaperId);
  181. hrp.nRequestType = RequestType::rtGetOffLineExamPaper;
  182. hrp.sCommonStr = sPaperFile;
  183. g_httpBllPtr->get(hrp);
  184. }
  185. });
  186. connect(clo, &clOperation::uploadOfflineAnswer, this, [&](int nRow){
  187. COfflineCourseInfo oci = m_vOfflineCourseInfo[nRow];
  188. CHttpRequestPackage hrp;
  189. hrp.sUri = QString("/api/ecs_exam_work/exam/getExamPropertyFromCacheByStudentSession/%1/%2")
  190. .arg(oci.nExamId).arg("OFFLINE_UPLOAD_FILE_TYPE");
  191. hrp.nRequestType = RequestType::rtGetExamProperty;
  192. hrp.sCommonStr = "OFFLINE_UPLOAD_FILE_TYPE;" + QString::number(oci.nExamRecordDataId);
  193. g_httpBllPtr->get(hrp);
  194. });
  195. clo->setUI(ui->tablewt_examList->columnWidth(4), ui->tablewt_examList->rowHeight(i), otStatus);
  196. ui->tablewt_examList->setCellWidget(i, 4, clo);
  197. }
  198. m_vOfflineCourseInfo.swap(getOfflineCourse.vOfflineCourseInfo);
  199. }
  200. else
  201. {
  202. if(getOfflineCourse.sMessage.isEmpty())
  203. {
  204. ShowMsg(QString::fromLocal8Bit("获取离线考试信息失败"), (QWidget*)(this->parent()));
  205. }
  206. else
  207. {
  208. ShowMsg(getOfflineCourse.sMessage, (QWidget*)(this->parent()));
  209. }
  210. }
  211. }
  212. void clOfflineExam::onDownLoadFile(CDownLoadFileInfo downLoadFileInfo)
  213. {
  214. if (downLoadFileInfo.sModuleName == __FILE__)
  215. {
  216. QStringList list = downLoadFileInfo.sFileName.split(",");
  217. if(list.count() == 2)
  218. {
  219. if(downLoadFileInfo.nCode == 200)
  220. {
  221. if(list[1] == "downloadAnswerSheet")
  222. {
  223. ShowMsg(QString::fromLocal8Bit("下载完成"), (QWidget*)(this->parent()));
  224. }
  225. else
  226. {
  227. int nRow = list[1].toInt();
  228. COfflineCourseInfo oci = m_vOfflineCourseInfo[nRow];
  229. QString sLocalFileName = oci.vOfflineFileInfo[oci.vOfflineFileInfo.size() - 1].sLocalFileName;
  230. if(sLocalFileName == list[0])
  231. {
  232. ShowMsg(QString::fromLocal8Bit("下载完成"), (QWidget*)(this->parent()));
  233. }
  234. }
  235. }
  236. else
  237. {
  238. if(downLoadFileInfo.sMessage.isEmpty())
  239. {
  240. ShowMsg(QString::fromLocal8Bit("下载失败"), g_appInfoPtr->m_pAnsBgWidget);
  241. }
  242. else
  243. {
  244. ShowMsg(downLoadFileInfo.sMessage, this);
  245. }
  246. }
  247. }
  248. }
  249. // downLoadFileInfo
  250. // QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
  251. // QString sAudioFile = g_appInfoPtr->m_sCacheFileDir + "cache/" + sFileName;
  252. // if (downLoadFileInfo.sFileName == sAudioFile)
  253. // {
  254. // if (downLoadFileInfo.nCode == 200)
  255. // {
  256. // int nSecord = g_audioPalyerPtr->GetMediaDuration(sAudioFile);
  257. // m_nMaxTestSecord = nSecord;
  258. // QString sText = QString("00:00 / %1:%2")
  259. // .arg((int)(nSecord/60), 2, 10, QChar('0'))
  260. // .arg((int)(nSecord%60), 2, 10, QChar('0'));
  261. // ui->label_ap_time->setText(sText);
  262. // }
  263. // else
  264. // {
  265. // }
  266. // }
  267. }
  268. void clOfflineExam::onGetOffLineExamAnswerSheet(CGetOffLineExamAnswerSheet getOffLineExamAnswerSheet)
  269. {
  270. if (getOffLineExamAnswerSheet.nCode == 200)
  271. {
  272. if (!getOffLineExamAnswerSheet.sAnswerSheetUrl.isEmpty())
  273. {
  274. m_sAnswerSheetUrl = getOffLineExamAnswerSheet.sAnswerSheetUrl;
  275. ui->btn_downloadAnswerSheet->setVisible(true);
  276. }
  277. }
  278. else
  279. {
  280. if(getOffLineExamAnswerSheet.sMessage.isEmpty())
  281. {
  282. ShowMsg(QString::fromLocal8Bit("获取离线考试信息失败"), (QWidget*)(this->parent()));
  283. }
  284. else
  285. {
  286. ShowMsg(getOffLineExamAnswerSheet.sMessage, (QWidget*)(this->parent()));
  287. }
  288. }
  289. }
  290. void clOfflineExam::onStartOfflineExam(CStartOfflineExam startOfflineExam)
  291. {
  292. if (startOfflineExam.nCode == 200)
  293. {
  294. int nRow = startOfflineExam.nRow;
  295. COfflineCourseInfo &oci = m_vOfflineCourseInfo[nRow];
  296. oci.sStatus = "EXAM_ING";
  297. clOperation *op = dynamic_cast<clOperation*>(ui->tablewt_examList->cellWidget(nRow, 4));
  298. if (op)
  299. {
  300. op->setOperationType(CL_OPERATION_TYPE::cot_offline_exam);
  301. }
  302. CHttpRequestPackage hrp;
  303. hrp.sUri = QString("/api/branch_ecs_ques/paper/export/%1/PAPER/offLine").arg(oci.sPaperId);
  304. hrp.nRequestType = RequestType::rtGetOffLineExamPaper;
  305. hrp.sCommonStr = QString::number(nRow);
  306. g_httpBllPtr->get(hrp);
  307. }
  308. else
  309. {
  310. if(startOfflineExam.sMessage.isEmpty())
  311. {
  312. ShowMsg(QString::fromLocal8Bit("离线考试开考失败"), (QWidget*)(this->parent()));
  313. }
  314. else
  315. {
  316. ShowMsg(startOfflineExam.sMessage, (QWidget*)(this->parent()));
  317. }
  318. }
  319. }
  320. void clOfflineExam::onGetOffLineExamPaper(CGetOffLineExamPaper getOffLineExamPaper)
  321. {
  322. if (getOffLineExamPaper.nCode == 200)
  323. {
  324. ShowMsg(QString::fromLocal8Bit("下载试卷完成"), this);
  325. }
  326. else
  327. {
  328. if(getOffLineExamPaper.sMessage.isEmpty())
  329. {
  330. ShowMsg(QString::fromLocal8Bit("离线考试下载试卷失败"), (QWidget*)(this->parent()));
  331. }
  332. else
  333. {
  334. ShowMsg(getOffLineExamPaper.sMessage, (QWidget*)(this->parent()));
  335. }
  336. }
  337. }
  338. void clOfflineExam::onPreviewOffLineExamPaper(CPreviewOffLineExamPaper previewOffLineExamPaper)
  339. {
  340. if (previewOffLineExamPaper.nCode == 200)
  341. {
  342. if (m_pViewPaper == nullptr)
  343. {
  344. m_pViewPaper = std::make_shared<cloeViewPaper>(previewOffLineExamPaper.sUrl, (QWidget*)this->parent()->parent());
  345. connect(m_pViewPaper.get(), &cloeViewPaper::goback, this, [&](){
  346. m_pViewPaper.reset();
  347. });
  348. }
  349. m_pViewPaper->show();
  350. }
  351. else
  352. {
  353. if(previewOffLineExamPaper.sMessage.isEmpty())
  354. {
  355. ShowMsg(QString::fromLocal8Bit("离线考试下载试卷失败"), (QWidget*)(this->parent()));
  356. }
  357. else
  358. {
  359. ShowMsg(previewOffLineExamPaper.sMessage, (QWidget*)(this->parent()));
  360. }
  361. }
  362. }
  363. void clOfflineExam::onGetExamProperty(CGetExamProperty getExamProperty)
  364. {
  365. if (getExamProperty.nCode == 200)
  366. {
  367. QStringList sList = getExamProperty.sType.split(";");
  368. if (sList.count() != 2)
  369. {
  370. return;
  371. }
  372. if (sList[0] == "OFFLINE_UPLOAD_FILE_TYPE")
  373. {
  374. if(m_pUploadFile == nullptr)
  375. {
  376. m_pUploadFile = std::make_shared<cloeUploadFile>(sList[1].toLongLong(), getExamProperty.vOfflineUploadFileType, (QWidget*)this->parent()->parent());
  377. connect(m_pUploadFile.get(), &cloeUploadFile::cancel, this, [&](){
  378. m_pUploadFile.reset();
  379. });
  380. connect(m_pUploadFile.get(), &cloeUploadFile::uploadSucceed, this, [&]() {
  381. m_pUploadFile.reset();
  382. CHttpRequestPackage hrp;
  383. hrp.sUri = "/api/ecs_oe_admin/client/exam/process/getOfflineCourse";
  384. hrp.nRequestType = RequestType::rtGetOfflineCourse;
  385. g_httpBllPtr->post(hrp);
  386. });
  387. }
  388. m_pUploadFile->show();
  389. }
  390. }
  391. else
  392. {
  393. if(getExamProperty.sMessage.isEmpty())
  394. {
  395. ShowMsg(QString::fromLocal8Bit("获取离线考试信息失败"), (QWidget*)(this->parent()));
  396. }
  397. else
  398. {
  399. ShowMsg(getExamProperty.sMessage, (QWidget*)(this->parent()));
  400. }
  401. }
  402. }
  403. void clOfflineExam::on_btn_downloadAnswerSheet_clicked()
  404. {
  405. QString sExportDir = QFileDialog::getExistingDirectory(
  406. this, QString::fromLocal8Bit("选择下载目录"),
  407. "/");
  408. if (sExportDir.isEmpty())
  409. {
  410. return;
  411. }
  412. //导出
  413. if (sExportDir.right(1) != "/")
  414. {
  415. sExportDir += "/";
  416. }
  417. QString sFileName = m_sAnswerSheetUrl.right(m_sAnswerSheetUrl.length() - m_sAnswerSheetUrl.lastIndexOf("/") - 1);
  418. QString sAnswerFile = sExportDir + sFileName;
  419. CHttpRequestPackage hrp;
  420. hrp.sUri = m_sAnswerSheetUrl;
  421. hrp.sCommonStr = QString("%1,%2").arg(sAnswerFile).arg("downloadAnswerSheet");
  422. hrp.sCommonStr1 = __FILE__;
  423. hrp.nRequestType = RequestType::rtDownLoadFile;
  424. g_httpBllPtr->downLoad(hrp);
  425. }