wangyaojie 1 vuosi sitten
vanhempi
commit
5fe19c3011

+ 66 - 25
client/answerWidget.cpp

@@ -71,6 +71,9 @@ answerWidget::answerWidget(QWidget *parent) :
 //    connect(g_httpBllPtr.get(), &CHttpBll::sgnGetOrgPropertiesByGroupWithoutCache, this, &answerWidget::onGetOrgPropertiesByGroupWithoutCache);
     qRegisterMetaType<CStartFaceLiveVerify>("CStartFaceLiveVerify");
     connect(g_httpBllPtr.get(), &CHttpBll::sgnStartFaceLiveVerify, this, &answerWidget::onStartFaceLiveVerify);
+    qRegisterMetaType<CBaseResponsePackage>("CBaseResponsePackage");
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnExamControlCheckTime, this, &answerWidget::onExamControlCheckTime);
+
 	
 #ifdef  _DEBUG
         //g_appInfoPtr->m_oExamInfo.bLivenessCheck = false;
@@ -132,9 +135,13 @@ answerWidget::answerWidget(QWidget *parent) :
     m_pCountDownTimer->setInterval(1000);
     connect(m_pCountDownTimer.get(), &QTimer::timeout, this, [&](){
 		--m_nLeftSeconds;
-		ui->label_lastTime->setText(QString("%1:%2:%3").arg(m_nLeftSeconds/60/60, 2, 10, QChar('0'))
-                                    .arg(m_nLeftSeconds/60%60, 2, 10, QChar('0'))
-                                    .arg(m_nLeftSeconds%60, 2, 10, QChar('0')));
+        if(m_nLeftSeconds >= 0)
+        {
+            ui->label_lastTime->setText(QString("%1:%2:%3").arg(m_nLeftSeconds/60/60, 2, 10, QChar('0'))
+                                        .arg(m_nLeftSeconds/60%60, 2, 10, QChar('0'))
+                                        .arg(m_nLeftSeconds%60, 2, 10, QChar('0')));
+        }
+
         if(m_nLeftSeconds <= 0)
         {
 //            m_pCountDownTimer->stop();
@@ -304,8 +311,15 @@ void answerWidget::onGetSoftwareConfig(CGetSoftwareConfig getSoftwareConfig)
                 QString sRemoteApp = jsonRoot["remoteApp"].asString().c_str();
                 QStringList remoteAppList = sRemoteApp.split("\n", QString::SkipEmptyParts);
 
-                m_sRemoteList += remoteAppList;
-                m_sRemoteTipList += remoteAppList;
+//                m_sRemoteList += remoteAppList;
+//                m_sRemoteTipList += remoteAppList;
+                for(QString remoteApp : remoteAppList)
+                {
+                    QString remoteAppProcess = remoteApp.left(remoteApp.indexOf("@@@"));
+                    QString remoteAppName = remoteApp.right(remoteApp.length() - remoteApp.indexOf("@@@") - 3);
+                    m_sRemoteList<<remoteAppProcess;
+                    m_sRemoteTipList<<remoteAppName;
+                }
             }
         }
 	}
@@ -1139,6 +1153,7 @@ void answerWidget::onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGrou
         g_appInfoPtr->m_oExamInfo.sActionOrder = orgProperties.sActionOrder;
         g_appInfoPtr->m_oExamInfo.nActionDuration = orgProperties.nActionDuration;
         g_appInfoPtr->m_oExamInfo.nActionAlert = orgProperties.nActionAlert;
+        g_appInfoPtr->m_oExamInfo.nFaceThreshold =  orgProperties.nFaceThreshold;
 
         StartFaceLiveVerify();
     }
@@ -1214,6 +1229,7 @@ void answerWidget::heartBreat()
 	CHttpRequestPackage hrp;
 	hrp.sUri = QString("/api/ecs_oe_student/client/exam/process/examHeartbeat");
 	hrp.nRequestType = RequestType::rtExamHeartbeat;
+    hrp.nRetryCount = 0;
 	g_httpBllPtr->post(hrp);
 }
 
@@ -1327,31 +1343,56 @@ void answerWidget::exitExamTip()
     m_pNetWorkErrorTimerPtr->start();
 }
 
-void answerWidget::on_btn_handInPaper_clicked()
+void answerWidget::onExamControlCheckTime(CBaseResponsePackage res)
 {
-    if(m_nFreezeTime*60  > m_nUsedExamSeconds + m_nEnterExamTime - m_nLeftSeconds)
-    {
-        ShowMsg(QString::fromLocal8Bit("冻结时间内不允许交卷"), this, MSG_ICON_TYPE::mit_error);
-        return;
-    }
+    if(res.nCode == 200)
+    {        
+        if(m_pHandinPaper == nullptr)
+        {
+            m_pHandinPaper = std::make_shared<awHandinPaper>(ui->btn_answeredNum->text().toInt(),
+                                                             ui->btn_unansweredNum->text().toInt(),
+                                                             ui->btn_markedNum->text().toInt(), (QWidget*)(this->parent()));
+            connect(m_pHandinPaper.get(), &awHandinPaper::handinPaper, this, [&](){
+                m_pHandinPaper.reset();
+                //交卷
+
+                handinPaper();
+            });
 
-    if(m_pHandinPaper == nullptr)
+            connect(m_pHandinPaper.get(), &awHandinPaper::cancelHandinPaper, this, [&](){
+                m_pHandinPaper.reset();
+            });
+        }
+        m_pHandinPaper->show();
+    }
+    else
     {
-        m_pHandinPaper = std::make_shared<awHandinPaper>(ui->btn_answeredNum->text().toInt(),
-                                                         ui->btn_unansweredNum->text().toInt(),
-                                                         ui->btn_markedNum->text().toInt(), (QWidget*)(this->parent()));
-        connect(m_pHandinPaper.get(), &awHandinPaper::handinPaper, this, [&](){
-            m_pHandinPaper.reset();
-            //交卷            
-			
-            handinPaper();
-        });
+        if(res.sMessage.isEmpty())
+        {
+            res.sMessage = QString::fromLocal8Bit("交卷时间检查失败");
+        }
 
-        connect(m_pHandinPaper.get(), &awHandinPaper::cancelHandinPaper, this, [&](){
-            m_pHandinPaper.reset();
-        });
+        ShowMsg(res.sMessage, this);
     }
-    m_pHandinPaper->show();
+}
+
+void answerWidget::on_btn_handInPaper_clicked()
+{
+//    if(m_nFreezeTime*60  > m_nUsedExamSeconds + m_nEnterExamTime - m_nLeftSeconds)
+//    {
+//        ShowMsg(QString::fromLocal8Bit("冻结时间内不允许交卷"), this, MSG_ICON_TYPE::mit_error);
+//        return;
+//    }
+
+    ui->btn_handInPaper->setEnabled(false);
+    CHttpRequestPackage hrp;
+    hrp.sUri = QString("/api/ecs_oe_student/examControl/check/time");
+    hrp.nRequestType = RequestType::rtExamControlCheckTime;
+    g_httpBllPtr->post(hrp);
+
+    QTimer::singleShot(3000, this, [&](){
+        ui->btn_handInPaper->setEnabled(true);
+    });
 }
 
 bool answerWidget::checkAnswer()

+ 1 - 0
client/answerWidget.h

@@ -47,6 +47,7 @@ private slots:
     void onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWithoutCache orgProperties);
     void onStartFaceLiveVerify(CStartFaceLiveVerify startFaceLiveVerify);
 	void onGetSoftwareConfig(CGetSoftwareConfig getSoftwareConfig);
+    void onExamControlCheckTime(CBaseResponsePackage res);
 
     void on_btn_handInPaper_clicked();
 

+ 1 - 0
client/awBackground.cpp

@@ -48,6 +48,7 @@ awBackground::~awBackground()
 
 void awBackground::initUI()
 {
+    ui->label_cl_company->setVisible(false);
 	//ui->label_awbg_exam->setText(QString::fromLocal8Bit("%1(%2)").arg().arg());
 	ui->label_awbg_student->setText(QString::fromLocal8Bit("%1 | %2 | %3 | %4")
 		.arg(g_appInfoPtr->m_sStudentName).arg(g_appInfoPtr->m_sStudentCode)

+ 6 - 3
client/clMobileLogin.cpp

@@ -5,6 +5,8 @@
 #include "CQREncode.h"
 
 #include <QGraphicsDropShadowEffect>
+#include <QByteArray>
+#include "logproc.h"
 
 clMobileLogin::clMobileLogin(QWidget *parent) :
     QWidget(parent),
@@ -104,9 +106,10 @@ void clMobileLogin::on_btn_downloadApp_clicked()
 }
 
 void clMobileLogin::on_btn_bindUser_clicked()
-{
-    QString sUserInfo = QString(R"({"rootOrgId":%1,"studentCode":"%2","identityNumber":"%3"})")
-            .arg(g_appInfoPtr->m_sRootOrgId).arg(g_appInfoPtr->m_sStudentCode).arg(g_appInfoPtr->m_sStudentIdentityNumber);
+{    
+    QString sUserInfo = QString::fromLocal8Bit("%1@%2").arg(g_appInfoPtr->m_sRootOrgId).arg(g_appInfoPtr->m_sRootOrgName);
+    sUserInfo = QByteArray(sUserInfo.toUtf8()).toBase64();
+
     ui->label_qrcode->setPixmap(CQREncode::GenerateQRcode(sUserInfo, ui->label_qrcode->width()));
     ui->label_useAppScan->setVisible(true);
     setBtnDown(ML_BTN_TYPE::mbt_bindUser);

+ 1 - 1
client/clMobileLogin.ui

@@ -32,7 +32,7 @@
      </rect>
     </property>
     <property name="text">
-     <string>下载安卓apk</string>
+     <string>下载云考APP</string>
     </property>
    </widget>
    <widget class="QPushButton" name="btn_bindUser">

+ 135 - 6
client/clOnlineExam.cpp

@@ -28,6 +28,21 @@ clOnlineExam::clOnlineExam(QWidget *parent) :
 			m_pObjectiveScore.reset();
 		}
 	});
+
+    m_pRefreshTimer = std::make_shared<QTimer>();
+    m_pRefreshTimer->setInterval(1000);
+    connect(m_pRefreshTimer.get(), &QTimer::timeout, this, [&]() {
+        --m_nRefreshSeconds;
+        ui->btn_refresh->setText(QString::fromLocal8Bit("倒计时%1s").arg(m_nRefreshSeconds));
+
+
+        if(m_nRefreshSeconds <= 0)
+        {
+            m_pRefreshTimer->stop();
+            ui->btn_refresh->setEnabled(true);
+            ui->btn_refresh->setText(QString::fromLocal8Bit("刷新"));
+        }
+    });
 }
 
 clOnlineExam::~clOnlineExam()
@@ -38,9 +53,39 @@ clOnlineExam::~clOnlineExam()
 void clOnlineExam::setUI(const int nWidth, const int nHeight)
 {
     setGeometry(0, 0, nWidth, nHeight);
-    ui->tabw_onlineExam->setGeometry(0, 0, nWidth, nHeight);
-    ui->tabw_onlineExam->setTabText(0, QString::fromLocal8Bit("待考列表"));
-    ui->tabw_onlineExam->setTabText(1, QString::fromLocal8Bit("已完成考试"));
+//    ui->tabw_onlineExam->setGeometry(0, 0, nWidth, nHeight);
+//    ui->tabw_onlineExam->setTabText(0, QString::fromLocal8Bit("待考列表"));
+//    ui->tabw_onlineExam->setTabText(1, QString::fromLocal8Bit("已完成考试"));
+    ui->tabw_onlineExam->setCurrentIndex(0);
+    ui->btn_examList->setFixedSize(QSize(g_appInfoPtr->m_fRate*86, g_appInfoPtr->m_fRate*30));
+    ui->btn_endExamList->setFixedSize(QSize(g_appInfoPtr->m_fRate*100, g_appInfoPtr->m_fRate*30));
+    ui->btn_refresh->setFixedSize(QSize(g_appInfoPtr->m_fRate*86, g_appInfoPtr->m_fRate*30));
+    ui->btn_examList->setStyleSheet(QString(R"(QPushButton{
+                                            outline:none;
+                                            border-radius:%1px;
+                                            border:0px solid rgba(255,255,255,1);
+                                            background:rgba(19, 187, 138, 1);
+
+                                            font-size:%2px;
+                                            font-family:"Microsoft YaHei";
+                                            font-weight:500;
+                                            color:rgba(255,255,255,1);
+                                        })").arg((int)(g_appInfoPtr->m_fRate*15))
+                                    .arg((int)(g_appInfoPtr->m_fRate*12)));
+    ui->btn_endExamList->setStyleSheet(QString(R"(QPushButton{
+                                            outline:none;
+                                            border-radius:%1px;
+                                            border:0px solid rgba(255,255,255,1);
+                                            background:rgba(239, 240, 245, 1);
+
+                                            font-size:%2px;
+                                            font-family:"Microsoft YaHei";
+                                            font-weight:500;
+                                            color:rgba(153, 153, 153, 1);
+                                        })").arg((int)(g_appInfoPtr->m_fRate*15))
+                                    .arg((int)(g_appInfoPtr->m_fRate*12)));
+
+
     ui->vlayout_el->setContentsMargins(g_appInfoPtr->m_fRate*30, 0, g_appInfoPtr->m_fRate*30, 0);
     ui->vlayout_fel->setContentsMargins(g_appInfoPtr->m_fRate*30, 0, g_appInfoPtr->m_fRate*30, 0);
 
@@ -152,7 +197,7 @@ void clOnlineExam::onQueryExamList(CQueryExamList queryExamList)
         ui->tablewt_examList->setRowCount(nSize);
 		for (int i = 0; i < nSize; ++i)
 		{
-			CExamCourseInfo eci = queryExamList.vOnlieExamList[i];			
+            CExamCourseInfo eci = queryExamList.vOnlieExamList[i];
 			ui->tablewt_examList->setItem(i, 0, new QTableWidgetItem(eci.sCourseName));
 			ui->tablewt_examList->setItem(i, 1, new QTableWidgetItem(eci.sCourseLevel));
 			ui->tablewt_examList->setItem(i, 2, new QTableWidgetItem(eci.sSpecialtyName));
@@ -177,8 +222,21 @@ void clOnlineExam::onQueryExamList(CQueryExamList queryExamList)
             connect(clo, &clOperation::enterExam, this, [&](CL_OPERATION_TYPE cot, int nRow){
                 if (cot == CL_OPERATION_TYPE::cot_online_exam )
                 {
-                    emit enterExam(cot, m_vOnlieExamList[nRow].nExamId, m_vOnlieExamList[nRow].nExamStudentId,
-                                   m_vOnlieExamList[nRow].sCourseCode, m_vOnlieExamList[nRow].sCourseName);
+                    QString sWeekCycle = CWeekTransform::getWeekCycles(m_vOnlieExamList[nRow].vExamCycleWeek);
+                    QString sTimeRange = m_vOnlieExamList[nRow].sExamCycleTimeRange.join(QString::fromLocal8Bit(","));
+                    QDateTime dtCurrent = QDateTime::fromMSecsSinceEpoch(g_appInfoPtr->serverMTime());
+                    QDateTime dtStartTime = QDateTime::fromString(m_vOnlieExamList[nRow].sStartTime, "yyyy-MM-dd hh:mm:ss");
+                    QDateTime dtEndTime = QDateTime::fromString(m_vOnlieExamList[nRow].sEndTime, "yyyy-MM-dd hh:mm:ss");
+                    bool bIsInExamTime = dtCurrent > dtStartTime && dtCurrent < dtEndTime;
+                    QString sWeek = dtCurrent.toString("ddd");
+                    bool bIsInWeek = sWeekCycle.size() == 0 || sWeekCycle.indexOf(sWeek) >= 0;
+                    QTime tCurrent = QDateTime::fromMSecsSinceEpoch(g_appInfoPtr->serverMTime()).time();
+                    bool bIsInTimeRange = m_vOnlieExamList[nRow].sExamCycleTimeRange.size() == 0 || CWeekTransform::isInTimeRange(tCurrent, m_vOnlieExamList[nRow].sExamCycleTimeRange);
+                    if(bIsInWeek && bIsInTimeRange && bIsInExamTime && m_vOnlieExamList[nRow].nAllowExamCount > 0)
+                    {
+                        emit enterExam(cot, m_vOnlieExamList[nRow].nExamId, m_vOnlieExamList[nRow].nExamStudentId,
+                                       m_vOnlieExamList[nRow].sCourseCode, m_vOnlieExamList[nRow].sCourseName);
+                    }
                 }
             });
 			connect(clo, &clOperation::showObjectiveScore, this, [&](CL_OPERATION_TYPE cot, int nRow) {
@@ -329,3 +387,74 @@ void clOnlineExam::onQueryExamEndList(CQueryExamEndList queryExamEndList)
         }
 	}
 }
+
+void clOnlineExam::on_btn_examList_clicked()
+{
+    ui->tabw_onlineExam->setCurrentIndex(0);
+
+    ui->btn_examList->setStyleSheet(QString(R"(QPushButton{
+                                            outline:none;
+                                            border-radius:%1px;
+                                            border:0px solid rgba(255,255,255,1);
+                                            background:rgba(19, 187, 138, 1);
+
+                                            font-size:%2px;
+                                            font-family:"Microsoft YaHei";
+                                            font-weight:500;
+                                            color:rgba(255,255,255,1);
+                                        })").arg((int)(g_appInfoPtr->m_fRate*15))
+                                    .arg((int)(g_appInfoPtr->m_fRate*12)));
+    ui->btn_endExamList->setStyleSheet(QString(R"(QPushButton{
+                                            outline:none;
+                                            border-radius:%1px;
+                                            border:0px solid rgba(255,255,255,1);
+                                            background:rgba(239, 240, 245, 1);
+
+                                            font-size:%2px;
+                                            font-family:"Microsoft YaHei";
+                                            font-weight:500;
+                                            color:rgba(153, 153, 153, 1);
+                                        })").arg((int)(g_appInfoPtr->m_fRate*15))
+                                    .arg((int)(g_appInfoPtr->m_fRate*12)));
+
+}
+
+void clOnlineExam::on_btn_endExamList_clicked()
+{
+    ui->tabw_onlineExam->setCurrentIndex(1);
+    ui->btn_endExamList->setStyleSheet(QString(R"(QPushButton{
+                                            outline:none;
+                                            border-radius:%1px;
+                                            border:0px solid rgba(255,255,255,1);
+                                            background:rgba(19, 187, 138, 1);
+
+                                            font-size:%2px;
+                                            font-family:"Microsoft YaHei";
+                                            font-weight:500;
+                                            color:rgba(255,255,255,1);
+                                        })").arg((int)(g_appInfoPtr->m_fRate*15))
+                                    .arg((int)(g_appInfoPtr->m_fRate*12)));
+    ui->btn_examList->setStyleSheet(QString(R"(QPushButton{
+                                            outline:none;
+                                            border-radius:%1px;
+                                            border:0px solid rgba(255,255,255,1);
+                                            background:rgba(239, 240, 245, 1);
+
+                                            font-size:%2px;
+                                            font-family:"Microsoft YaHei";
+                                            font-weight:500;
+                                            color:rgba(153, 153, 153, 1);
+                                        })").arg((int)(g_appInfoPtr->m_fRate*15))
+                                    .arg((int)(g_appInfoPtr->m_fRate*12)));
+
+}
+
+
+void clOnlineExam::on_btn_refresh_clicked()
+{
+    ui->btn_refresh->setEnabled(false);
+    refreshExam();
+    m_pRefreshTimer->start();
+    m_nRefreshSeconds = 20;
+    ui->btn_refresh->setText(QString::fromLocal8Bit("倒计时%1s").arg(m_nRefreshSeconds));
+}

+ 7 - 1
client/clOnlineExam.h

@@ -27,6 +27,11 @@ public:
 private slots:
 	void onQueryExamList(CQueryExamList queryExamList);
 	void onQueryExamEndList(CQueryExamEndList queryExamEndList);	
+    void on_btn_examList_clicked();
+
+    void on_btn_endExamList_clicked();
+    void on_btn_refresh_clicked();
+
 private:
 	void showEvent(QShowEvent *event);
 
@@ -35,11 +40,12 @@ private:
     Ui::clOnlineExam *ui;
 
 	std::shared_ptr<QTimer> m_pObjectiveScoreTimer;
+    std::shared_ptr<QTimer> m_pRefreshTimer;
     std::shared_ptr<clObjectiveScore> m_pObjectiveScore;
 	std::vector<CExamCourseInfo> m_vOnlieExamList;
     std::vector<CExamCourseInfo> m_vOnlieEndExamList;
 
-    
+    int m_nRefreshSeconds = 20;
 };
 
 #endif // CLONLINEEXAM_H

+ 154 - 81
client/clOnlineExam.ui

@@ -13,103 +13,176 @@
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <widget class="QTabWidget" name="tabw_onlineExam">
-   <property name="geometry">
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>451</width>
-     <height>411</height>
-    </rect>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <property name="spacing">
+    <number>20</number>
    </property>
-   <property name="tabPosition">
-    <enum>QTabWidget::North</enum>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
    </property>
-   <property name="tabShape">
-    <enum>QTabWidget::Rounded</enum>
+   <property name="rightMargin">
+    <number>0</number>
    </property>
-   <property name="currentIndex">
+   <property name="bottomMargin">
     <number>0</number>
    </property>
-   <widget class="QWidget" name="tab_examList">
-    <attribute name="title">
-     <string>Tab 1</string>
-    </attribute>
-    <layout class="QGridLayout" name="gridLayout_2">
-     <item row="1" column="0">
-      <layout class="QVBoxLayout" name="vlayout_el">
-       <property name="leftMargin">
-        <number>0</number>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <property name="spacing">
+      <number>14</number>
+     </property>
+     <property name="leftMargin">
+      <number>30</number>
+     </property>
+     <property name="topMargin">
+      <number>20</number>
+     </property>
+     <property name="rightMargin">
+      <number>30</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="btn_examList">
+       <property name="minimumSize">
+        <size>
+         <width>86</width>
+         <height>30</height>
+        </size>
        </property>
-       <property name="rightMargin">
-        <number>0</number>
+       <property name="maximumSize">
+        <size>
+         <width>16777215</width>
+         <height>16777215</height>
+        </size>
        </property>
-       <item>
-        <widget class="QTableWidget" name="tablewt_examList"/>
-       </item>
-       <item>
-        <widget class="QWidget" name="widget_el_page" native="true">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-           <horstretch>0</horstretch>
-           <verstretch>62</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="minimumSize">
-          <size>
-           <width>0</width>
-           <height>62</height>
-          </size>
-         </property>
-         <property name="maximumSize">
-          <size>
-           <width>16777215</width>
-           <height>62</height>
-          </size>
-         </property>
-        </widget>
-       </item>
-      </layout>
+       <property name="text">
+        <string>待考列表</string>
+       </property>
+      </widget>
      </item>
-    </layout>
-   </widget>
-   <widget class="QWidget" name="tab_finishExamList">
-    <attribute name="title">
-     <string>Tab 2</string>
-    </attribute>
-    <layout class="QGridLayout" name="gridLayout">
-     <item row="0" column="0">
-      <layout class="QVBoxLayout" name="vlayout_fel">
-       <property name="leftMargin">
-        <number>0</number>
+     <item>
+      <widget class="QPushButton" name="btn_endExamList">
+       <property name="minimumSize">
+        <size>
+         <width>100</width>
+         <height>30</height>
+        </size>
        </property>
-       <property name="rightMargin">
-        <number>0</number>
+       <property name="text">
+        <string>已结束考试</string>
        </property>
-       <item>
-        <widget class="QTableWidget" name="tablew_finishExamList"/>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="btn_refresh">
+       <property name="minimumSize">
+        <size>
+         <width>86</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>刷新</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QStackedWidget" name="tabw_onlineExam">
+     <property name="currentIndex">
+      <number>1</number>
+     </property>
+     <widget class="QWidget" name="tabw_onlineExamPage1" native="true">
+      <layout class="QGridLayout" name="gridLayout_2">
+       <item row="1" column="0">
+        <layout class="QVBoxLayout" name="vlayout_el">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QTableWidget" name="tablewt_examList"/>
+         </item>
+         <item>
+          <widget class="QWidget" name="widget_el_page" native="true">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>62</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>0</width>
+             <height>62</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>62</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+        </layout>
        </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tabw_onlineExamPage2" native="true">
+      <layout class="QVBoxLayout" name="verticalLayout">
        <item>
-        <widget class="QWidget" name="widget_fel_page" native="true">
-         <property name="minimumSize">
-          <size>
-           <width>0</width>
-           <height>62</height>
-          </size>
+        <layout class="QVBoxLayout" name="vlayout_fel">
+         <property name="leftMargin">
+          <number>0</number>
          </property>
-         <property name="maximumSize">
-          <size>
-           <width>16777215</width>
-           <height>62</height>
-          </size>
+         <property name="rightMargin">
+          <number>0</number>
          </property>
-        </widget>
+         <item>
+          <widget class="QTableWidget" name="tablew_finishExamList"/>
+         </item>
+         <item>
+          <widget class="QWidget" name="widget_fel_page" native="true">
+           <property name="minimumSize">
+            <size>
+             <width>0</width>
+             <height>62</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>62</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+        </layout>
        </item>
       </layout>
-     </item>
-    </layout>
-   </widget>
-  </widget>
+     </widget>
+    </widget>
+   </item>
+  </layout>
  </widget>
  <resources/>
  <connections/>

+ 14 - 1
client/clOnlineHomework.cpp

@@ -168,8 +168,21 @@ void clOnlineHomework::onQueryHomeworkList(CQueryHomeworkList queryHomeworkList)
             connect(clo, &clOperation::enterExam, this, [&](CL_OPERATION_TYPE cot, int nRow){
                 if (cot == CL_OPERATION_TYPE::cot_online_homework )
                 {
-                    emit enterExam(cot, m_vHomeworkExamList[nRow].nExamId, m_vHomeworkExamList[nRow].nExamStudentId,
+                    QString sWeekCycle = CWeekTransform::getWeekCycles(m_vHomeworkExamList[nRow].vExamCycleWeek);
+                    QString sTimeRange = m_vHomeworkExamList[nRow].sExamCycleTimeRange.join(",");
+                    QDateTime dtCurrent = QDateTime::fromMSecsSinceEpoch(g_appInfoPtr->serverMTime());
+                    QDateTime dtStartTime = QDateTime::fromString(m_vHomeworkExamList[nRow].sStartTime, "yyyy-MM-dd hh:mm:ss");
+                    QDateTime dtEndTime = QDateTime::fromString(m_vHomeworkExamList[nRow].sEndTime, "yyyy-MM-dd hh:mm:ss");
+                    bool bIsInExamTime = dtCurrent > dtStartTime && dtCurrent < dtEndTime;
+                    QString sWeek = dtCurrent.toString("ddd");
+                    bool bIsInWeek = sWeekCycle.size() == 0 || sWeekCycle.indexOf(sWeek) >= 0;
+                    QTime tCurrent = QDateTime::fromMSecsSinceEpoch(g_appInfoPtr->serverMTime()).time();
+                    bool bIsInTimeRange = m_vHomeworkExamList[nRow].sExamCycleTimeRange.size() == 0 || CWeekTransform::isInTimeRange(tCurrent, m_vHomeworkExamList[nRow].sExamCycleTimeRange);
+                    if(bIsInWeek && bIsInTimeRange && bIsInExamTime)
+                    {
+                        emit enterExam(cot, m_vHomeworkExamList[nRow].nExamId, m_vHomeworkExamList[nRow].nExamStudentId,
                                    m_vHomeworkExamList[nRow].sCourseCode, m_vHomeworkExamList[nRow].sCourseName);
+                    }
                 }
             });
 

+ 14 - 1
client/clOnlinePractice.cpp

@@ -193,8 +193,21 @@ void clOnlinePractice::onQueyPracticeCourseList(CQueryPracticeCourseList queryPr
             connect(clo, &clOperation::enterExam, this, [&](CL_OPERATION_TYPE cot, int nRow){
                 if (cot == CL_OPERATION_TYPE::cot_online_practice )
                 {
-                    emit enterExam(cot, m_vPracticeCourseInfo[nRow].nExamId, m_vPracticeCourseInfo[nRow].nExamStudentId,
+                    QString sWeekCycle = CWeekTransform::getWeekCycles(m_vPracticeCourseInfo[nRow].vExamCycleWeek);
+                    QString sTimeRange = m_vPracticeCourseInfo[nRow].sExamCycleTimeRange.join(",");
+                    QDateTime dtCurrent = QDateTime::fromMSecsSinceEpoch(g_appInfoPtr->serverMTime());
+                    QDateTime dtStartTime = QDateTime::fromString(m_vPracticeCourseInfo[nRow].sStartTime, "yyyy-MM-dd hh:mm:ss");
+                    QDateTime dtEndTime = QDateTime::fromString(m_vPracticeCourseInfo[nRow].sEndTime, "yyyy-MM-dd hh:mm:ss");
+                    bool bIsInExamTime = dtCurrent > dtStartTime && dtCurrent < dtEndTime;
+                    QString sWeek = dtCurrent.toString("ddd");
+                    bool bIsInWeek = sWeekCycle.size() == 0 || sWeekCycle.indexOf(sWeek) >= 0;
+                    QTime tCurrent = QDateTime::fromMSecsSinceEpoch(g_appInfoPtr->serverMTime()).time();
+                    bool bIsInTimeRange = m_vPracticeCourseInfo[nRow].sExamCycleTimeRange.size() == 0 || CWeekTransform::isInTimeRange(tCurrent, m_vPracticeCourseInfo[nRow].sExamCycleTimeRange);
+                    if(bIsInWeek && bIsInTimeRange && bIsInExamTime)
+                    {
+                        emit enterExam(cot, m_vPracticeCourseInfo[nRow].nExamId, m_vPracticeCourseInfo[nRow].nExamStudentId,
                                    m_vPracticeCourseInfo[nRow].sCourseCode, m_vPracticeCourseInfo[nRow].sCourseName);					
+                    }
                 }
             });
             connect(clo, &clOperation::viewPracticeDetail, this, [&](int nRow){

+ 1 - 0
client/client.pro

@@ -169,6 +169,7 @@ INCLUDEPATH += ../common/ \
     $$BREAKPAD_PATH \
 
 LIBS +=-Ld:/workspace/project/oline-exam-cloud/3rdPart/TX_TRTC_SDK/Win32/lib -lliteav \
+    -ladvapi32 \
 
 CONFIG(release, debug|release): LIBS += -L$$BREAKPAD_PATH/client/windows/Release/lib -lcommon -lcrash_generation_client -lcrash_generation_server -lexception_handler
 CONFIG(debug, debug|release): LIBS +=  -L$$BREAKPAD_PATH/client/windows/Debug/lib -lcommon -lcrash_generation_client -lcrash_generation_server -lexception_handler

+ 74 - 1
client/client.qss

@@ -270,7 +270,7 @@ QPushButton#btn_mobileLogin:hover,#btn_studentInfo:hover
 }
 
 
-QLabel#label_currrentPlace,#label_cl_version,#label_serverTime,#label_cl_company,#label_batch
+QLabel#label_currrentPlace,#label_cl_version,#label_cl_company,#label_batch
 {
     font-size:RATE_BASE_SIZE12px;
     font-family:"Microsoft YaHei";
@@ -278,6 +278,14 @@ QLabel#label_currrentPlace,#label_cl_version,#label_serverTime,#label_cl_company
     color:rgba(153,153,153,1);
 }
 
+QLabel#label_serverTime
+{
+    font-size:RATE_BASE_SIZE12px;
+    font-family:"Microsoft YaHei";
+    font-weight:600;
+    color:rgba(255,0,0,1);
+}
+
 QTabWidget::pane
 {
     border-top:1px solid rgba(239,240,245,1);
@@ -1031,6 +1039,16 @@ QPushButton#btn_fc_close
     border-image:url(:/images/btn-fc-close.png);
 }
 
+QPushButton#btn_fl_close
+{
+    background:rgba(254,119,100,1);
+    border-radius:RATE_BASE_SIZE10px;
+    font-size:RATE_BASE_SIZE14px;
+    font-family:"Microsoft YaHei";
+    font-weight:600;
+    color:rgba(255,255,255,1);
+}
+
 QLabel#label_fc_basePhotoTips
 {
     background:rgba(0,0,0,0.3);
@@ -1263,6 +1281,18 @@ QPushButton#btn_handInPaper
     color:rgba(255,255,255,1);
 }
 
+QPushButton#btn_handInPaper:disabled
+{
+    outline:none;
+    border-radius:RATE_BASE_SIZE10px;
+    border:0px solid rgba(255,255,255,1);
+    background:rgba(254,219,200,1);
+
+    font-size:RATE_BASE_SIZE14px;
+    font-family:"Microsoft YaHei";
+    font-weight:600;
+    color:rgba(255,255,255,1);
+}
 
 QLabel#label_lastTimeIcon
 {
@@ -2004,3 +2034,46 @@ QPushButton#btn_aw_minisize
 {
     border-image:url(:/images/icon-aw-minisize.png);
 }
+
+
+QPushButton#btn_refresh
+{
+    outline:none;
+    border-radius:RATE_BASE_SIZE15px;
+    border:0px solid rgba(255,255,255,1);
+    background:rgba(19, 187, 138, 1);
+
+    font-size:RATE_BASE_SIZE12px;
+    font-family:"Microsoft YaHei";
+    font-weight:500;
+    color:rgba(255,255,255,1);
+}
+
+QPushButton#btn_refresh:hover
+{
+    outline:none;
+    border-radius:RATE_BASE_SIZE15px;
+    border:0px solid rgba(255,255,255,1);
+    background:#05966A;
+
+    font-size:RATE_BASE_SIZE12px;
+    font-family:"Microsoft YaHei";
+    font-weight:500;
+    color:rgba(255,255,255,1);
+}
+
+
+QPushButton#btn_refresh:disabled
+{
+    outline:none;
+    border-radius:RATE_BASE_SIZE15px;
+    border:0px solid rgba(255,255,255,1);
+    background:#9DDFCC;
+
+    font-size:RATE_BASE_SIZE12px;
+    font-family:"Microsoft YaHei";
+    font-weight:500;
+    color:rgba(255,255,255,1);
+}
+
+

+ 1 - 0
client/cloeViewPaper.cpp

@@ -37,6 +37,7 @@ void cloeViewPaper::initUI()
 {     
      QDesktopWidget *dekwiget = QApplication::desktop();
      setGeometry(0, 0, dekwiget->width(), dekwiget->height());
+     ui->label_cl_company->setVisible(false);
      ui->widget_awbg_BG->setGeometry(0, 0, width(), height());
      ui->widget_cloe_viewpaper->setGeometry(g_appInfoPtr->m_fRate*20, g_appInfoPtr->m_fRate*56, width() - g_appInfoPtr->m_fRate*20*2,
                                             height() - g_appInfoPtr->m_fRate*(56 + 38));     

+ 9 - 6
client/courseList.cpp

@@ -166,6 +166,7 @@ void courseList::initUI()
 {
     QDesktopWidget *dekwiget = QApplication::desktop();
     setGeometry(0, 0, dekwiget->width(), dekwiget->height());
+    ui->label_cl_company->setVisible(false);
     ui->widget_cl_BG->setGeometry(0, 0, dekwiget->width(), dekwiget->height());
     ui->widget_menu->setGeometry(0, 0, g_appInfoPtr->m_fRate*96, height());
     ui->widget_top->setGeometry(ui->widget_menu->width(), 0, width() - ui->widget_menu->width(), g_appInfoPtr->m_fRate*56);
@@ -540,10 +541,10 @@ void courseList::onGetExamProperty(CGetExamProperty getExamProperty)
 {
     if (getExamProperty.nCode == 200)
 	{
-        if (getExamProperty.sType == "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,WARN_THRESHOLD,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE")
+        if (getExamProperty.sType == "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE")
 		{
             g_appInfoPtr->m_oExamInfo.bIsFaceCheck = getExamProperty.bIsFaceCheck;
-            g_appInfoPtr->m_oExamInfo.nWarnThreshold = getExamProperty.nWarnThreshold;
+//            g_appInfoPtr->m_oExamInfo.nFaceThreshold = getExamProperty.nFaceThreshold;
             g_appInfoPtr->m_oExamInfo.nSnapshotInterval = getExamProperty.nSnapshotInterval;
             g_appInfoPtr->m_oExamInfo.nFaceVerifyStartMinute = getExamProperty.nFaceVerifyStartMinute;
             g_appInfoPtr->m_oExamInfo.nFaceVerifyEndMinute = getExamProperty.nFaceVerifyEndMinute;
@@ -760,6 +761,7 @@ void courseList::onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupW
         g_appInfoPtr->m_oExamInfo.nActionDuration = orgProperties.nActionDuration;
         g_appInfoPtr->m_oExamInfo.nActionAlert = orgProperties.nActionAlert;
         g_appInfoPtr->m_oExamInfo.nAllActionDuration = orgProperties.nAllActionDuration;
+        g_appInfoPtr->m_oExamInfo.nFaceThreshold =  orgProperties.nFaceThreshold;
 
         if(!g_appInfoPtr->m_oExamInfo.bIsExamInProgress)
         {
@@ -1002,6 +1004,7 @@ void courseList::getStudentInfoBySession()
 	CHttpRequestPackage hrp;
 	hrp.sUri = "/api/ecs_core/student/getStudentInfoBySession";
 	hrp.nRequestType = RequestType::rtGetStudentInfoBySession;
+    hrp.nRetryCount = 3;
 	g_httpBllPtr->get(hrp);
 }
 
@@ -1175,9 +1178,9 @@ void courseList::onCheckExamInProgress(CCheckExamInProgress checkExamInProgress)
                 //环境监测
                 CHttpRequestPackage hrp;
                 hrp.sUri = QString("/api/ecs_exam_work/exam/getExamPropertyFromCacheByStudentSession/%1/%2")
-                    .arg(g_appInfoPtr->m_oExamInfo.nExamId).arg("CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,WARN_THRESHOLD,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE");
+                    .arg(g_appInfoPtr->m_oExamInfo.nExamId).arg("CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE");
                 hrp.nRequestType = RequestType::rtGetExamProperty;
-                hrp.sCommonStr = "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,WARN_THRESHOLD,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE";
+                hrp.sCommonStr = "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE";
                 g_httpBllPtr->get(hrp);
 
 			}
@@ -1208,9 +1211,9 @@ void courseList::onCheckExamInProgress(CCheckExamInProgress checkExamInProgress)
                 //环境监测
                 CHttpRequestPackage hrp;
                 hrp.sUri = QString("/api/ecs_exam_work/exam/getExamPropertyFromCacheByStudentSession/%1/%2")
-                    .arg(g_appInfoPtr->m_oExamInfo.nExamId).arg("CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,WARN_THRESHOLD,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE");
+                    .arg(g_appInfoPtr->m_oExamInfo.nExamId).arg("CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE");
                 hrp.nRequestType = RequestType::rtGetExamProperty;
-                hrp.sCommonStr = "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,WARN_THRESHOLD,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE";
+                hrp.sCommonStr = "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,FACE_VERIFY_START_MINUTE,FACE_VERIFY_END_MINUTE,IS_STRANGER_ENABLE,IS_FACE_VERIFY_BEFORE";
                 g_httpBllPtr->get(hrp);
 			}						
 		}		

+ 1 - 0
client/courseList.h

@@ -82,6 +82,7 @@ private slots:
     void onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWithoutCache orgProperties);
 
     void onEndExam(CEndExam endExam);
+
 private:
     void initUI();
     void setCheck(COURSE_MENU_BTN_TYPE cmbt);

+ 2 - 2
client/courseList.ui

@@ -70,7 +70,7 @@
       </rect>
      </property>
      <property name="text">
-      <string>手机端登录(Android)</string>
+      <string>手机端登录</string>
      </property>
     </widget>
     <widget class="QPushButton" name="btn_studentInfo">
@@ -83,7 +83,7 @@
       </rect>
      </property>
      <property name="text">
-      <string>何乐乐</string>
+      <string/>
      </property>
     </widget>
     <widget class="QLabel" name="label_currentPlaceIcon">

+ 21 - 1
client/login.cpp

@@ -14,6 +14,8 @@
 #include "CLiveViodeProc.h"
 #include <QDateTime>
 #include "CKeyBoardHook.h"
+#include "CWindowsFireWall.h"
+#include <process.h>
 
 login::login(QWidget *parent)
     : QWidget(parent)
@@ -134,6 +136,13 @@ login::~login()
         g_logPtr.reset();
     }
 
+    HWND task = nullptr;
+    task=FindWindow(L"Shell_TrayWnd",nullptr);
+    if(task)
+    {
+        ShowWindow(task,SW_SHOW);//隐藏任务栏
+    }
+
     awMsgBox::clear();
     delete ui;
 }
@@ -539,6 +548,15 @@ void login::onStudentClientConfig(CStudentClientConfig studentClientConfig)
             
             g_keyBoardHookPtr = std::make_shared<CKeyBoardHook>();
             g_keyBoardHookPtr->Hotkey_Install(0);
+
+            HWND task = nullptr;
+            task=FindWindow(L"Shell_TrayWnd",nullptr);
+            if(task)
+            {
+                ShowWindow(task,SW_HIDE);//隐藏任务栏
+            }
+
+            g_windowsFireWallPtr = std::make_shared<CWindowsFireWall>(_getpid());
         }
   
         
@@ -592,7 +610,7 @@ void login::onLoginLimit(CLoginLimit loginLimit)
 			hrp.sParamList.push_back(QString::fromLocal8Bit("rootOrgId,%1").arg(g_appInfoPtr->m_sRootOrgId));
 			g_httpBllPtr->post(hrp);
 		}
-		else
+        else
 		{
 			//等待重试
             if(m_nRetryCount >= 3)
@@ -648,6 +666,8 @@ void login::onLoginInfo(CLoginInfo loginInfo)
 	if (loginInfo.nCode == 200)
 	{
 		g_appInfoPtr->m_nStudentId = loginInfo.nUserId;
+        g_appInfoPtr->m_sRootOrgId = QString::number(loginInfo.nRootOrgId);
+        g_appInfoPtr->m_sRootOrgName = loginInfo.sRootOrgName;
 		if (m_pCourseList == nullptr)
 		{
 			m_pCourseList = std::make_shared<courseList>(this);

+ 6 - 0
client/main.cpp

@@ -7,6 +7,7 @@
 #include <windows.h>
 #include <DbgHelp.h>
 #include "CLogTrack.h"
+#include <QProcess>
 #include "client/windows/handler/exception_handler.h"
 
 
@@ -113,6 +114,11 @@ int main(int argc, char *argv[])
     login w;
     w.show();
 
+    QProcess process;
+    process.start("taskkill /f /im launcher.exe");
+    process.waitForFinished();
+
+
 	if (argc > 1)
 	{
 		QString sParam = argv[1];

+ 1 - 0
common/CAppInfo.cpp

@@ -19,6 +19,7 @@ CAppInfo::CAppInfo()
 	m_bFullScreenTop = false;
 	m_bDisableVirtualCamera = false;
 	m_sRootOrgId = "";
+    m_sRootOrgName = "";
 	m_bShowQmthLogo = false;
     m_sMenuLogoUrl = "";
 	m_bShowStudentClientAppQrcode = false;

+ 3 - 2
common/CAppInfo.h

@@ -28,7 +28,7 @@ public:
     int nDuration;
     bool bFaceCheck;
     bool bLivenessCheck;    
-    int nWarnThreshold;//预警阈值
+    int nFaceThreshold;//人脸比对阈值
     bool bIsFaceCheck;//进入考试是否验证人脸识别(强制、非强制)
     bool bIsLivenessBefore;//考前活体检测
     int nSnapshotInterval;//抓拍间隔时间
@@ -58,7 +58,7 @@ public:
         nDuration = 0;
         bFaceCheck = false;
         bLivenessCheck = false;
-        nWarnThreshold = 0;
+        nFaceThreshold = 50;
         bIsFaceCheck = false;
         nSnapshotInterval = 0;
         nFaceVerifyStartMinute = 0;
@@ -94,6 +94,7 @@ public:
 	bool m_bFullScreenTop;//屏幕前置
 	bool m_bDisableVirtualCamera;//虚拟摄像头
 	QString m_sRootOrgId;
+    QString m_sRootOrgName;
 	bool m_bShowQmthLogo;
     QString m_sMenuLogoUrl;
 	bool m_bShowStudentClientAppQrcode;

+ 137 - 40
common/CHttpBll.cpp

@@ -79,6 +79,13 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
     {
         if(!doPost(requestPkg, sResponse, nCode))
         {
+            --requestPkg.nRetryCount;
+            if(requestPkg.nRetryCount > 0)
+            {
+                post(requestPkg);
+                return;
+            }
+
             sErrorMsg =  QString::fromLocal8Bit("接口%1调用失败!").arg(requestPkg.sUri);
         }
     }
@@ -86,6 +93,12 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
     {
         if(!doGet(requestPkg, sResponse, nCode))
         {
+            --requestPkg.nRetryCount;
+            if(requestPkg.nRetryCount > 0)
+            {
+                get(requestPkg);
+                return;
+            }
             sErrorMsg =  QString::fromLocal8Bit("接口%1调用失败!").arg(requestPkg.sUri);
         }
     }
@@ -93,12 +106,18 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
 	{
 		if (!doPut(requestPkg, sResponse, nCode))
 		{
+            --requestPkg.nRetryCount;
+            if(requestPkg.nRetryCount > 0)
+            {
+                put(requestPkg);
+                return;
+            }
 			sErrorMsg = QString::fromLocal8Bit("接口%1调用失败!").arg(requestPkg.sUri);
 		}
 	}
     __int64 nEndTime = g_appInfoPtr->serverMTime();
     myServerLog()<< requestPkg.sUri << ":resCode," << nCode<<"response:"<<sResponse.c_str() << "requestTime(ms):" << nEndTime - nStartTime;
-    myDebug() << requestPkg.sUri << ":"<< sResponse.c_str();
+    myDebug() << requestPkg.sUri << ":resCode," << nCode<<"response:"<< sResponse.c_str();
 
 	if (nCode != 200)
 	{
@@ -981,23 +1000,23 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
 		}
 		break;
 
-		case RequestType::rtProcessUpload:
-		{
-			CProcessUpload pu;
-            pu.sCommonStr = requestPkg.sCommonStr;
-			pu.nCode = nCode;
-			if (sErrorMsg != "" || nCode != 200)
-			{
-				pu.sMessage = sErrorMsg;
-			}
-			else
-			{
-				genProcessUpload(&pu, sResponse);
-			}
-
-			emit sgnProcessUpload(pu);
-		}
-		break;
+//		case RequestType::rtProcessUpload:
+//		{
+//			CProcessUpload pu;
+//            pu.sCommonStr = requestPkg.sCommonStr;
+//			pu.nCode = nCode;
+//			if (sErrorMsg != "" || nCode != 200)
+//			{
+//				pu.sMessage = sErrorMsg;
+//			}
+//			else
+//			{
+//				genProcessUpload(&pu, sResponse);
+//			}
+
+//			emit sgnProcessUpload(pu);
+//		}
+//		break;
 		
 		case RequestType::rtSaveFaceCompareResult:
 		{
@@ -1088,6 +1107,49 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
 		}
 		break;
 
+        case RequestType::rtClientExamProcessUploadSign:
+        {
+            CClientExamProcessUploadSign cepus;
+            cepus.sCommonStr = requestPkg.sCommonStr;
+            cepus.sFilePath = requestPkg.sCommonStr1;
+            cepus.nCode = nCode;
+            if (sErrorMsg != "" || nCode != 200)
+            {
+                cepus.sMessage = sErrorMsg;
+            }
+            else
+            {
+                genClientExamProcessUploadSign(&cepus, sResponse);
+            }
+            emit sgnClientExamProcessUploadSign(cepus);
+        }
+        break;
+
+        case RequestType::rtUploadFileToAliyun:
+        {
+            CUploadFileToAliyun ufta;
+            ufta.sCommonStr = requestPkg.sCommonStr;
+            ufta.sFileUrl = requestPkg.sCommonStr1;
+            ufta.nCode = nCode;
+            if (sErrorMsg != "" || nCode != 200)
+            {
+                ufta.sMessage = sErrorMsg;
+            }
+            emit sgnUploadFileToAliyun(ufta);
+        }
+        break;
+
+    case RequestType::rtExamControlCheckTime:
+        {
+            CBaseResponsePackage res;
+            res.nCode = nCode;
+            if (sErrorMsg != "" || nCode != 200)
+            {
+                res.sMessage = sErrorMsg;
+            }
+            emit sgnExamControlCheckTime(res);
+        }
+        break;
         default:
         break;
     }
@@ -1198,6 +1260,10 @@ void CHttpBll::genStudentClientConfig(CStudentClientConfig *pStudentClientConfig
             {
                 pStudentClientConfig->bDisableVirtualCamera = true;
             }
+            else if (sType == "DISABLE_VIRTUAL_MACHINE")
+            {
+                pStudentClientConfig->bDisableVirtualMachine = true;
+            }
         }
 
         pStudentClientConfig->sRootOrgId = jsonRoot["ROOT_ORG_ID"].asString().c_str();// " : "0",
@@ -1512,10 +1578,10 @@ void CHttpBll::genGetExamProperty(CGetExamProperty *pGetExamProperty, const std:
             pGetExamProperty->bCheckEnvironment = QVariant(jsonRoot["CHECK_ENVIRONMENT"].asString().c_str()).toBool();
         }
 
-        if (jsonRoot.isMember("WARN_THRESHOLD"))
-        {
-            pGetExamProperty->nWarnThreshold = QVariant(jsonRoot["WARN_THRESHOLD"].asString().c_str()).toInt();
-        }
+//        if (jsonRoot.isMember("PC_CLIENT_FACE_THRESHOLD"))
+//        {
+//            pGetExamProperty->nFaceThreshold = QVariant(jsonRoot["PC_CLIENT_FACE_THRESHOLD"].asString().c_str()).toInt();
+//        }
 
         if (jsonRoot.isMember("IS_FACE_CHECK"))
         {
@@ -2511,24 +2577,24 @@ void CHttpBll::genGetWXQrCode(CGetWXQrCode *pGetWXQrCode, const std::string &sRe
 	pGetWXQrCode->sUrl = sResponse.c_str();
 }
 
-void CHttpBll::genProcessUpload(CProcessUpload *pProcessUpload, const std::string &sResponse)
-{
-    try
-    {
-        Json::Reader reader;
-        Json::Value jsonRoot = Json::Value::null;
-        if (!reader.parse(sResponse, jsonRoot))
-        {
-            pProcessUpload->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
-            myDebug() << pProcessUpload->sMessage << sResponse.c_str();
-        }
-        pProcessUpload->sFileUrl = jsonRoot["fileUrl"].asString().c_str();
-    }
-    catch (const std::exception &e)
-    {
-        myServerLog()<<sResponse.c_str()<<",exception error"<<e.what();
-    }
-}
+//void CHttpBll::genProcessUpload(CProcessUpload *pProcessUpload, const std::string &sResponse)
+//{
+//    try
+//    {
+//        Json::Reader reader;
+//        Json::Value jsonRoot = Json::Value::null;
+//        if (!reader.parse(sResponse, jsonRoot))
+//        {
+//            pProcessUpload->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+//            myDebug() << pProcessUpload->sMessage << sResponse.c_str();
+//        }
+//        pProcessUpload->sFileUrl = jsonRoot["fileUrl"].asString().c_str();
+//    }
+//    catch (const std::exception &e)
+//    {
+//        myServerLog()<<sResponse.c_str()<<",exception error"<<e.what();
+//    }
+//}
 
 void CHttpBll::genGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWithoutCache *pOrgProperties, const std::string &sResponse)
 {
@@ -2547,6 +2613,10 @@ void CHttpBll::genGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWi
         pOrgProperties->nActionDuration = QVariant(jsonRoot["ACTION_DURATION"].asString().c_str()).toInt();
         pOrgProperties->nActionAlert = QVariant(jsonRoot["ACTION_ALERT"].asString().c_str()).toInt();
         pOrgProperties->nAllActionDuration = QVariant(jsonRoot["ALL_ACTION_DURATION"].asString().c_str()).toInt();
+        if(jsonRoot.isMember("PC_CLIENT_FACE_THRESHOLD"))
+        {
+            pOrgProperties->nFaceThreshold = QVariant(jsonRoot["PC_CLIENT_FACE_THRESHOLD"].asString().c_str()).toInt();
+        }
     }
     catch (const std::exception &e)
     {
@@ -2576,3 +2646,30 @@ void CHttpBll::genStartFaceLiveVerify(CStartFaceLiveVerify *pStartFaceLiveVerify
         myServerLog()<<sResponse.c_str()<<",exception error"<<e.what();
     }
 }
+
+void CHttpBll::genClientExamProcessUploadSign(CClientExamProcessUploadSign *pClientExamProcessUploadSign, const std::string &sResponse)
+{
+    try
+    {
+        Json::Reader reader;
+        Json::Value jsonRoot = Json::Value::null;
+        if (!reader.parse(sResponse, jsonRoot))
+        {
+            pClientExamProcessUploadSign->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            myDebug() << pClientExamProcessUploadSign->sMessage << sResponse.c_str();
+        }
+
+        pClientExamProcessUploadSign->sType = jsonRoot["fsType"].asString().c_str();
+        pClientExamProcessUploadSign->sAccessUrl = jsonRoot["accessUrl"].asString().c_str();
+        pClientExamProcessUploadSign->sSignIdentifier = jsonRoot["signIdentifier"].asString().c_str();
+        pClientExamProcessUploadSign->sFormUrl = jsonRoot["formUrl"].asString().c_str();
+        pClientExamProcessUploadSign->sOssAcessKeyId = jsonRoot["formParams"]["OSSAccessKeyId"].asString().c_str();
+        pClientExamProcessUploadSign->sSignature = jsonRoot["formParams"]["Signature"].asString().c_str();
+        pClientExamProcessUploadSign->sKey = jsonRoot["formParams"]["key"].asString().c_str();
+        pClientExamProcessUploadSign->sPolicy = jsonRoot["formParams"]["policy"].asString().c_str();
+    }
+    catch (const std::exception &e)
+    {
+        myServerLog()<<sResponse.c_str()<<",exception error"<<e.what();
+    }
+}

+ 6 - 2
common/CHttpBll.h

@@ -65,12 +65,15 @@ signals:
 	void sgnGetExamRecordPaperStruct(CGetExamRecordPaperStruct getExamRecordPaperStruct);
 	void sgnGetWXQrCode(CGetWXQrCode getWXQrCode);
 	void sgnSaveUploadedFileAcknowledgeStatus(CSaveUploadedFileAcknowledgeStatus saveUploadedFileAcknowledgeStatus);
-	void sgnProcessUpload(CProcessUpload processUpload); //文件上传
+//	void sgnProcessUpload(CProcessUpload processUpload); //文件上传
 	void sgnSaveFaceCompareResult(CBaseResponsePackage res);//保存人脸识别比对验证结果
 	void sgnSaveFaceCaptureResult(CBaseResponsePackage res);//保存人脸抓拍比对验证结果
 	void sgnSaveFaceLiveVerifyResult(CBaseResponsePackage res);//保存人脸活体验证结果
 	void sgnGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWithoutCache orgProperties);
 	void sgnStartFaceLiveVerify(CStartFaceLiveVerify startFaceLiveVerify);
+    void sgnClientExamProcessUploadSign(CClientExamProcessUploadSign clientExamProcessUploadSign);
+    void sgnUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun);
+    void sgnExamControlCheckTime(CBaseResponsePackage res);
 public:
     CHttpBll();
 
@@ -129,9 +132,10 @@ private:
 	void genGetExamRecordPaperStruct(CGetExamRecordPaperStruct *pGetExamRecordPaperStruct, const std::string &sResponse);
 	void genGetEndExamInfo(CGetEndExamInfo *pGetEndExamInfo, const std::string &sResponse);
 	void genGetWXQrCode(CGetWXQrCode *pGetWXQrCode, const std::string &sResponse);
-	void genProcessUpload(CProcessUpload *pProcessUpload, const std::string &sResponse);
+//	void genProcessUpload(CProcessUpload *pProcessUpload, const std::string &sResponse);
 	void genGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWithoutCache *pOrgProperties, const std::string &sResponse);
 	void genStartFaceLiveVerify(CStartFaceLiveVerify *pStartFaceLiveVerify, const std::string &sResponse);
+    void genClientExamProcessUploadSign(CClientExamProcessUploadSign *pClientExamProcessUploadSign, const std::string &sResponse);
 
 	void genExamCourseInfo(const Json::Value &jExamItem, CExamCourseInfo &eci);
 

+ 23 - 4
common/CHttpInterceptor.cpp

@@ -1,6 +1,7 @@
 #include "CHttpInterceptor.h"
-//#include "logproc.h"
+#include "logproc.h"
 #include "CCommonTools.h"
+#include <QHostAddress>
 
 CHttpInterceptor::CHttpInterceptor()
 {
@@ -18,13 +19,30 @@ CHttpInterceptor::~CHttpInterceptor()
 
 void CHttpInterceptor::init(QString sIp, QString sPort, bool bUseHttps)
 {
+    bool bIsIp = false;
+    QHostAddress test;
+    if (test.setAddress(sIp))
+    {
+        bIsIp = true;
+    }
+
     if(bUseHttps)
     {
         m_sUrl = QString("https://%1:%2").arg(sIp).arg(sPort);
+        m_wxUrl = m_sUrl;
+        if(!bIsIp)
+        {
+            m_wxUrl = QString("https://www%1:%2").arg(sIp.right(sIp.length() - sIp.indexOf("."))).arg(sPort);
+        }
     }
     else
     {
         m_sUrl = QString("http://%1:%2").arg(sIp).arg(sPort);
+        m_wxUrl = m_sUrl;
+        if(!bIsIp)
+        {
+            m_wxUrl = QString("http://www%1:%2").arg(sIp.right(sIp.length() - sIp.indexOf("."))).arg(sPort);
+        }
     }
 }
 
@@ -66,7 +84,7 @@ void CHttpInterceptor::get(CHttpRequestPackage requestPkg)
 
 QString CHttpInterceptor::getHttpUrl() const
 {
-    return m_sUrl;
+    return m_wxUrl;
 }
 
 void CHttpInterceptor::getUrl(CHttpRequestPackage requestPkg)
@@ -116,7 +134,7 @@ bool CHttpInterceptor::doPost(const CHttpRequestPackage &requestPkg, std::string
                 QString sKey = sParams.left(sParams.indexOf(","));
                 QString sValue = sParams.right(sParams.length() - sParams.indexOf(",") - 1);
                 jPost[sKey.toStdString()] = sValue.toStdString();
-//				myDebug() << sParams;
+                myServerLog() << sParams;
             }
 
             sPostStr = jPost.toStyledString().c_str();
@@ -173,7 +191,8 @@ bool CHttpInterceptor::doPost(const CHttpRequestPackage &requestPkg, std::string
 				m_httpClient.addFormData(fdt_content, sKey.toStdString(), sValue.toStdString());
 			}			
 		}
-		std::string sUrl = (m_sUrl + requestPkg.sUri).toStdString();
+
+        std::string sUrl = requestPkg.bNoHostPrefix ?  requestPkg.sUri.toStdString() : (m_sUrl + requestPkg.sUri).toStdString();
 		if (m_httpClient.postFormData(sUrl, sResponseStr, nCode))
 		{
 			return true;

+ 2 - 1
common/CHttpInterceptor.h

@@ -45,7 +45,8 @@ private:
 
     CHttpClient m_httpClient;
 
-    QString m_sUrl;
+    QString m_sUrl = "";
+    QString m_wxUrl = "";
 };
 
 #endif // CHTTPINTERCEPTOR_H

+ 2 - 0
common/common.pri

@@ -62,6 +62,8 @@ LIBS += -L$$PLUGINS_DIR/curl-7.69.1/builds/x86/lib  -llibcurl \
     -lDbgHelp \
     -lIphlpapi
 
+
+
 win32:CONFIG(release, debug|release):{
     LIBS +=  -L$$PLUGINS_DIR/jsoncpp/lib/x86 -llib_json \
         -L$$OPENCV_DIR/x86/lib -lopencv_world342

+ 45 - 14
common/httpDataDef.h

@@ -80,12 +80,15 @@ enum class RequestType
     rtDownLoadFile, //下载文件
 	rtGetWXQrCode,//获取微信二维码
 	rtSaveUploadedFileAcknowledgeStatus,//修改上传音频或图片结果推送状态
-	rtProcessUpload, //文件上传
+//	rtProcessUpload, //文件上传
 	rtSaveFaceCompareResult,//保存人脸识别比对验证结果
 	rtSaveFaceCaptureResult,//保存人脸抓拍比对验证结果
 	rtSaveFaceLiveVerifyResult,//保存人脸活体验证结果
 	rtStartFaceLiveVerify,//开始人脸活体验证接口,如:活检次数,活检开始时间等	
-	rtGetOrgPropertiesByGroupWithoutCache//获取活检配置参数接口
+    rtGetOrgPropertiesByGroupWithoutCache,//获取活检配置参数接口
+    rtClientExamProcessUploadSign,//文件上传签名信息
+    rtUploadFileToAliyun,
+    rtExamControlCheckTime, //交卷冻结时间检查
 };
 
 class CHttpRequestPackage
@@ -101,6 +104,7 @@ public:
     QStringList sParamList;
     QStringList sHeadList;
     int nRetryCount;
+    bool bNoHostPrefix;//不需要加http://host:port
     CHttpRequestPackage()
     {
         nRequestType = RequestType::rtUndefine;
@@ -111,6 +115,7 @@ public:
         sCommonStr1 = "";
 		sAdditionStr = "";
         nRetryCount = 0;
+        bNoHostPrefix = false;
     }
 };
 
@@ -181,6 +186,7 @@ public:
 	QString sOeStudentSysName;//" : "网考 - 33d34sss3d",
 	bool bDisableMutiScreen;
 	bool bDisableRemoteAssistance;
+    bool bDisableVirtualMachine;
 	bool bFullScreenTop; 	
 	bool bDisableVirtualCamera;
 	QString sRootOrgId;// " : "0",
@@ -199,6 +205,7 @@ public:
 		sOeStudentSysName = "";
         bDisableMutiScreen = false;
         bDisableRemoteAssistance = false;
+        bDisableVirtualMachine = false;
         bFullScreenTop = false;
         bDisableVirtualCamera = false;
 		sRootOrgId = "";// " : "0",
@@ -428,7 +435,7 @@ public:
 	QString sType;
 	QString sBeforeExamRemark;//考前说明
 	bool bCheckEnvironment;//环境监测
-	int nWarnThreshold;//预警阈值
+//    int nFaceThreshold;//预警阈值
 	bool bIsFaceCheck;//进入考试是否验证人脸识别(强制、非强制)
 	int nSnapshotInterval;//抓拍间隔时间
 	int nFaceVerifyStartMinute;//活体检测开始分钟数
@@ -452,7 +459,7 @@ public:
 		sType = "";
 		sBeforeExamRemark = "";
 		bCheckEnvironment = false;
-		nWarnThreshold = 0;//预警阈值
+//        nFaceThreshold = 50;//预警阈值
 		bIsFaceCheck = false;//进入考试是否验证人脸识别(强制、非强制)
 		nSnapshotInterval = 0;
 		nFaceVerifyStartMinute = 0;//活体检测开始分钟数
@@ -1359,16 +1366,16 @@ public:
     }
 };
 
-class CProcessUpload : public CBaseResponsePackage
-{
-public:
-	QString sFileUrl;
-    QString sCommonStr;
-	CProcessUpload()
-	{
-		sFileUrl = "";
-	}
-};
+//class CProcessUpload : public CBaseResponsePackage
+//{
+//public:
+//	QString sFileUrl;
+//    QString sCommonStr;
+//	CProcessUpload()
+//	{
+//		sFileUrl = "";
+//	}
+//};
 
 
 class CGetOrgPropertiesByGroupWithoutCache : public CBaseResponsePackage
@@ -1380,6 +1387,7 @@ public:
 	int nActionDuration;//单个动作最大时长
 	int nActionAlert;//指定动作检测提醒N秒后开始检测
     int nAllActionDuration;//整体动作时长
+    int nFaceThreshold; //人脸比对阈值
 
 	CGetOrgPropertiesByGroupWithoutCache()
 	{
@@ -1389,6 +1397,7 @@ public:
 		nActionDuration = 0;
         nActionAlert = 15;
         nAllActionDuration = 120;
+        nFaceThreshold = 50;
 	}
 };
 
@@ -1406,5 +1415,27 @@ public:
 	}
 };
 
+class CClientExamProcessUploadSign : public CBaseResponsePackage
+{
+public:
+    QString sCommonStr = "";
+    QString sFilePath = "";
+    QString sType = "";
+    QString sAccessUrl = "";
+    QString sSignIdentifier = "";
+    QString sFormUrl = "";
+    QString sOssAcessKeyId = "";
+    QString sSignature = "";
+    QString sKey = "";
+    QString sPolicy = "";
+
+};
+
+class CUploadFileToAliyun : public CBaseResponsePackage
+{
+public:
+    QString sCommonStr = "";
+    QString sFileUrl = "";
+};
 
 #endif // HTTPDATADEF_H

+ 941 - 0
component/CWindowsFireWall.cpp

@@ -0,0 +1,941 @@
+#include "CWindowsFireWall.h"
+
+
+#include <crtdbg.h>
+#include <objbase.h>
+#include <oleauto.h>
+#include <stdio.h>
+#include <tlhelp32.h>
+#include <Psapi.h>
+#include <strsafe.h>
+#include <QStringList>
+#include <QDebug>
+#include <QFileInfo>
+#include <QSettings>
+#include <comutil.h>
+#include <atlcomcli.h>
+#include<QDateTime>
+#include "logproc.h"
+
+#pragma comment( lib, "ole32.lib" )
+#pragma comment( lib, "oleaut32.lib" )
+
+std::shared_ptr<CWindowsFireWall> g_windowsFireWallPtr = nullptr;
+
+#define STRING_BUFFER_SIZE  500
+
+
+BOOL EnableDebugPrivilege()
+{
+    HANDLE hToken;
+    BOOL fOk = FALSE;
+    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
+    {
+        TOKEN_PRIVILEGES tp;
+        tp.PrivilegeCount = 1;
+        LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
+        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+        AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
+        fOk = (GetLastError() == ERROR_SUCCESS);
+        CloseHandle(hToken);
+    }
+    return fOk;
+}
+
+CWindowsFireWall::CWindowsFireWall(DWORD pid, bool bcheck) : m_pid(pid), m_bcheck(bcheck)
+{   
+    EnableDebugPrivilege();
+
+    QFileInfo file("coe.cfgi");
+    QString sFilePath = file.absoluteFilePath();
+    QSettings set(sFilePath, QSettings::IniFormat);
+    m_bModifyFireWall = set.value("wallConfig/ModifyWall", false).toBool();
+    m_fw_profile2_domain_enabled = set.value("wallConfig/profile2_domain_enabled", VARIANT_TRUE).toInt();
+    m_fw_profile2_private_enabled = set.value("wallConfig/profile2_private_enabled", VARIANT_TRUE).toInt();
+    m_fw_profile2_public_enabled = set.value("wallConfig/profile2_public_enabled", VARIANT_TRUE).toInt();
+
+    init();
+
+    if(bcheck)
+    {
+        m_pThrd = new std::thread(std::bind(&CWindowsFireWall::threadProc, this));
+    }
+}
+
+CWindowsFireWall::~CWindowsFireWall()
+{
+    m_bIsRun = false;
+    if(m_bcheck)
+    {
+        m_pThrd->join();
+        cleanup();
+    }
+}
+
+void CWindowsFireWall::threadProc()
+{
+    setWallOn();
+    removeLastRules();
+    setAllRulesEnabled(VARIANT_FALSE);
+
+    disableAllApp();
+    __int64 nLastTime = QDateTime::currentDateTime().toSecsSinceEpoch();
+
+    while(m_bIsRun)
+    {
+        __int64 nCurrentTime = QDateTime::currentDateTime().toSecsSinceEpoch();
+        if(nCurrentTime - nLastTime > m_inprogressCheckSeconds)
+        {
+            nLastTime = nCurrentTime;
+            checkInprogressFireWall();
+        }
+        Sleep(100);
+    }
+}
+
+void CWindowsFireWall::checkInprogressFireWall()
+{
+    //检测防火墙是否开启
+    HRESULT hr;
+
+    VARIANT_BOOL fw_profile2_domain_enabled = VARIANT_FALSE;
+    VARIANT_BOOL fw_profile2_private_enabled = VARIANT_FALSE;
+    VARIANT_BOOL fw_profile2_public_enabled = VARIANT_FALSE;
+    hr = m_pNetFwPolicy2->get_FirewallEnabled(NET_FW_PROFILE2_DOMAIN, &fw_profile2_domain_enabled);
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("put_FirewallEnabled failed for Domain: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        myServerLog()<<m_sErrMsg;
+    }
+
+    hr = m_pNetFwPolicy2->get_FirewallEnabled(NET_FW_PROFILE2_PRIVATE, &fw_profile2_private_enabled);
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("put_FirewallEnabled failed for private: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        myServerLog()<<m_sErrMsg;
+    }
+
+    hr = m_pNetFwPolicy2->get_FirewallEnabled(NET_FW_PROFILE2_PUBLIC, &fw_profile2_public_enabled);
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("put_FirewallEnabled failed for public: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        myServerLog()<<m_sErrMsg;
+    }
+
+    if(fw_profile2_domain_enabled != VARIANT_TRUE ||
+            fw_profile2_private_enabled != VARIANT_TRUE ||
+            fw_profile2_public_enabled != VARIANT_TRUE)
+    {
+        myServerLog()<<QString::fromLocal8Bit("考试中防火墙被关闭 ")<<",fw_profile2_domain_enabled:"<<fw_profile2_domain_enabled
+                    <<",fw_profile2_private_enabled:"<<fw_profile2_private_enabled
+                   <<",fw_profile2_public_enabled:"<<fw_profile2_public_enabled;
+        setWallOn();
+    }
+
+    //遍历进程
+    checkRulesIsEnabled();
+
+    disableAllApp();
+}
+
+void CWindowsFireWall::checkRulesIsEnabled()
+{
+    HRESULT hr = S_OK;
+    CComVariant var;
+    ULONG cFetched = 0;
+    IUnknown *pEnumerator;
+    IEnumVARIANT* pVariant = NULL;
+    INetFwRules *pFwRules = NULL;
+    INetFwRule *pFwRule = NULL;
+
+    long fwRuleCount;
+
+    // Retrieve INetFwRules
+    hr = m_pNetFwPolicy2->get_Rules(&pFwRules);
+    if (FAILED(hr))
+    {
+        wprintf(L"get_Rules failed: 0x%08lx\n", hr);
+    }
+
+    // Obtain the number of Firewall rules
+    hr = pFwRules->get_Count(&fwRuleCount);
+    if (FAILED(hr))
+    {
+        wprintf(L"get_Count failed: 0x%08lx\n", hr);
+    }
+
+    wprintf(L"The number of rules in the Windows Firewall are %d\n", fwRuleCount);
+
+    // Iterate through all of the rules in pFwRules
+    pFwRules->get__NewEnum(&pEnumerator);
+
+    if(pEnumerator)
+    {
+        hr = pEnumerator->QueryInterface(__uuidof(IEnumVARIANT), (void **) &pVariant);
+    }
+
+    while(SUCCEEDED(hr) && hr != S_FALSE)
+    {
+        var.Clear();
+        hr = pVariant->Next(1, &var, &cFetched);
+
+        if (S_FALSE != hr)
+        {
+            if (SUCCEEDED(hr))
+            {
+                hr = var.ChangeType(VT_DISPATCH);
+            }
+            if (SUCCEEDED(hr))
+            {
+                hr = (V_DISPATCH(&var))->QueryInterface(__uuidof(INetFwRule), reinterpret_cast<void**>(&pFwRule));
+            }
+
+            if (SUCCEEDED(hr))
+            {
+                BSTR szRuleName;
+                pFwRule->get_Name(&szRuleName);
+                QString sRuleName = QString::fromStdWString(szRuleName);
+                VARIANT_BOOL bEnable = VARIANT_FALSE;
+                pFwRule->put_Enabled(bEnable);
+                if(sRuleName.startsWith("disable_coe_"))
+                {
+                    if(bEnable == VARIANT_FALSE)
+                    {
+                        pFwRule->put_Enabled(VARIANT_TRUE);
+                    }
+                }
+                else
+                {
+                    if(bEnable == VARIANT_TRUE)
+                    {
+                        pFwRule->put_Enabled(VARIANT_FALSE);
+                    }
+                }
+
+            }
+        }
+    }
+
+    // Release pFwRule
+    if (pFwRule != NULL)
+    {
+        pFwRule->Release();
+    }
+
+    if(pFwRules != NULL)
+    {
+        pFwRules->Release();
+    }
+}
+
+void CWindowsFireWall::uploadAppLog(std::vector<CProcessData> &vAppList)
+{
+    QStringList appList;
+    for(CProcessData data : vAppList)
+    {
+        appList << QString::fromStdWString(data.sExeName);
+    }
+    myServerLog()<<appList.join(",");
+}
+// Instantiate INetFwPolicy2
+HRESULT CWindowsFireWall::WFCOMInitialize(INetFwPolicy2** ppNetFwPolicy2)
+{
+    HRESULT hr = S_OK;
+
+    hr = CoCreateInstance(
+        __uuidof(NetFwPolicy2),
+        NULL,
+        CLSCTX_INPROC_SERVER,
+        __uuidof(INetFwPolicy2),
+        (void**)ppNetFwPolicy2);
+
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("CoCreateInstance for INetFwPolicy2 failed: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+
+    }
+
+    return hr;
+}
+
+bool CWindowsFireWall::init()
+{   
+    HRESULT hr = S_OK;
+
+    // Initialize COM.
+    m_comInit = CoInitializeEx(
+                    0,
+                    COINIT_APARTMENTTHREADED
+                    );
+
+    // Ignore RPC_E_CHANGED_MODE; this just means that COM has already been
+    // initialized with a different mode. Since we don't care what the mode is,
+    // we'll just use the existing mode.
+    if (m_comInit != RPC_E_CHANGED_MODE)
+    {
+        if (FAILED(m_comInit))
+        {            
+            m_sErrMsg = QString("CoInitializeEx for INetFwPolicy2 failed: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            return false;
+        }
+    }
+
+    // Retrieve INetFwPolicy2
+    hr = WFCOMInitialize(&m_pNetFwPolicy2);
+    if (FAILED(hr))
+    {        
+        return false;
+    }
+    return true;
+}
+
+void CWindowsFireWall::cleanup()
+{   
+    if(m_vDisableRuleNames.size() > 0)
+    {
+        INetFwRules *pNetFwRules = NULL;
+        HRESULT hr = m_pNetFwPolicy2->get_Rules(&pNetFwRules);
+        if (SUCCEEDED(hr))
+        {
+            for(std::wstring sRuleName: m_vDisableRuleNames)
+            {
+                pNetFwRules->Remove(const_cast<BSTR>(sRuleName.c_str()));
+            }			
+        }
+    }
+
+    setAllRulesEnabled(VARIANT_TRUE);
+
+    if(m_bModifyFireWall)
+    {
+        HRESULT hr = m_pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_DOMAIN, m_fw_profile2_domain_enabled);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("put_FirewallEnabled failed for Domain: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        }
+
+        hr = m_pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_PRIVATE, m_fw_profile2_private_enabled);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("put_FirewallEnabled failed for Private: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        }
+
+        hr = m_pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_PUBLIC, m_fw_profile2_public_enabled);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("put_FirewallEnabled failed for Public: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        }
+
+        m_bModifyFireWall = false;
+        m_fw_profile2_domain_enabled = VARIANT_TRUE;
+        m_fw_profile2_private_enabled = VARIANT_TRUE;
+        m_fw_profile2_public_enabled = VARIANT_TRUE;
+        QFileInfo file("coe.cfgi");
+        QString sFilePath = file.absoluteFilePath();
+        QSettings set(sFilePath, QSettings::IniFormat);
+        set.setValue("wallConfig/ModifyWall", m_bModifyFireWall);
+        set.setValue("wallConfig/profile2_domain_enabled", m_fw_profile2_domain_enabled);
+        set.setValue("wallConfig/profile2_private_enabled", m_fw_profile2_private_enabled);
+        set.setValue("wallConfig/profile2_public_enabled", m_fw_profile2_public_enabled);
+    }
+
+    if (m_pNetFwPolicy2 != NULL)
+    {
+        m_pNetFwPolicy2->Release();
+    }
+
+    if (SUCCEEDED(m_comInit))
+    {
+        CoUninitialize();
+    }    
+}
+
+bool CWindowsFireWall::setWallOn()
+{
+    HRESULT hr;
+    if(!m_bModifyFireWall)
+    {
+        hr = m_pNetFwPolicy2->get_FirewallEnabled(NET_FW_PROFILE2_DOMAIN, &m_fw_profile2_domain_enabled);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("put_FirewallEnabled failed for Domain: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            return false;
+        }
+
+        hr = m_pNetFwPolicy2->get_FirewallEnabled(NET_FW_PROFILE2_PRIVATE, &m_fw_profile2_private_enabled);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("put_FirewallEnabled failed for private: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            return false;
+        }
+
+        hr = m_pNetFwPolicy2->get_FirewallEnabled(NET_FW_PROFILE2_PUBLIC, &m_fw_profile2_public_enabled);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("put_FirewallEnabled failed for public: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            return false;
+        }
+    }
+
+    hr = m_pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_DOMAIN, TRUE);
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("put_FirewallEnabled failed for Domain: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        return false;
+    }
+
+    hr = m_pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_PRIVATE, TRUE);
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("put_FirewallEnabled failed for Private: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        return false;
+    }
+
+    hr = m_pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_PUBLIC, TRUE);
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("put_FirewallEnabled failed for Public: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+        return false;
+    }
+
+    if(m_fw_profile2_domain_enabled != VARIANT_TRUE ||
+            m_fw_profile2_private_enabled != VARIANT_TRUE ||
+            m_fw_profile2_public_enabled != VARIANT_TRUE )
+    {
+        m_bModifyFireWall = true;
+        QFileInfo file("coe.cfgi");
+        QString sFilePath = file.absoluteFilePath();
+        QSettings set(sFilePath, QSettings::IniFormat);
+        set.setValue("wallConfig/ModifyWall", m_bModifyFireWall);
+        set.setValue("wallConfig/profile2_domain_enabled", m_fw_profile2_domain_enabled);
+        set.setValue("wallConfig/profile2_private_enabled", m_fw_profile2_private_enabled);
+        set.setValue("wallConfig/profile2_public_enabled", m_fw_profile2_public_enabled);
+    }
+    return true;
+}
+
+void CWindowsFireWall::setAllRulesEnabled(VARIANT_BOOL bEnable)
+{
+    HRESULT hr = S_OK;
+    CComVariant var;
+    ULONG cFetched = 0;
+    IUnknown *pEnumerator;
+    IEnumVARIANT* pVariant = NULL;
+    INetFwRules *pFwRules = NULL;
+    INetFwRule *pFwRule = NULL;
+
+    long fwRuleCount;
+
+    // Retrieve INetFwRules
+    hr = m_pNetFwPolicy2->get_Rules(&pFwRules);
+    if (FAILED(hr))
+    {
+        wprintf(L"get_Rules failed: 0x%08lx\n", hr);
+    }
+
+    // Obtain the number of Firewall rules
+    hr = pFwRules->get_Count(&fwRuleCount);
+    if (FAILED(hr))
+    {
+        wprintf(L"get_Count failed: 0x%08lx\n", hr);
+    }
+
+    wprintf(L"The number of rules in the Windows Firewall are %d\n", fwRuleCount);
+
+    // Iterate through all of the rules in pFwRules
+    pFwRules->get__NewEnum(&pEnumerator);
+
+    if(pEnumerator)
+    {
+        hr = pEnumerator->QueryInterface(__uuidof(IEnumVARIANT), (void **) &pVariant);
+    }
+
+    while(SUCCEEDED(hr) && hr != S_FALSE)
+    {
+        var.Clear();
+        hr = pVariant->Next(1, &var, &cFetched);
+
+        if (S_FALSE != hr)
+        {
+            if (SUCCEEDED(hr))
+            {
+                hr = var.ChangeType(VT_DISPATCH);
+            }
+            if (SUCCEEDED(hr))
+            {
+                hr = (V_DISPATCH(&var))->QueryInterface(__uuidof(INetFwRule), reinterpret_cast<void**>(&pFwRule));
+            }
+
+            if (SUCCEEDED(hr))
+            {
+                // Output the properties of this rule
+             //   DumpFWRulesInCollection(pFwRule);
+                pFwRule->put_Enabled(bEnable);
+            }                        
+        }
+    }
+
+	// Release pFwRule
+	if (pFwRule != NULL)
+	{
+		pFwRule->Release();
+	}
+
+    if(pFwRules != NULL)
+    {
+        pFwRules->Release();
+    }
+}
+
+void CWindowsFireWall::removeLastRules()
+{
+    HRESULT hr = S_OK;
+    CComVariant var;
+    ULONG cFetched = 0;
+    IUnknown *pEnumerator;
+    IEnumVARIANT* pVariant = NULL;
+    INetFwRules *pFwRules = NULL;
+    INetFwRule *pFwRule = NULL;
+
+    long fwRuleCount;
+
+    // Retrieve INetFwRules
+    hr = m_pNetFwPolicy2->get_Rules(&pFwRules);
+    if (FAILED(hr))
+    {
+        wprintf(L"get_Rules failed: 0x%08lx\n", hr);
+    }
+
+    // Obtain the number of Firewall rules
+    hr = pFwRules->get_Count(&fwRuleCount);
+    if (FAILED(hr))
+    {
+        wprintf(L"get_Count failed: 0x%08lx\n", hr);
+    }
+
+    wprintf(L"The number of rules in the Windows Firewall are %d\n", fwRuleCount);
+
+    // Iterate through all of the rules in pFwRules
+    pFwRules->get__NewEnum(&pEnumerator);
+
+    if(pEnumerator)
+    {
+        hr = pEnumerator->QueryInterface(__uuidof(IEnumVARIANT), (void **) &pVariant);
+    }
+
+    QStringList RuleNamelist;
+
+    while(SUCCEEDED(hr) && hr != S_FALSE)
+    {
+        var.Clear();
+        hr = pVariant->Next(1, &var, &cFetched);
+
+        if (S_FALSE != hr)
+        {
+            if (SUCCEEDED(hr))
+            {
+                hr = var.ChangeType(VT_DISPATCH);
+            }
+            if (SUCCEEDED(hr))
+            {
+                hr = (V_DISPATCH(&var))->QueryInterface(__uuidof(INetFwRule), reinterpret_cast<void**>(&pFwRule));
+            }
+
+            if (SUCCEEDED(hr))
+            {
+                // Output the properties of this rule
+             //   DumpFWRulesInCollection(pFwRule);
+                BSTR szRuleName;
+                pFwRule->get_Name(&szRuleName);
+                QString sRuleName = QString::fromStdWString(szRuleName);
+                if(sRuleName.startsWith("disable_coe_"))
+                {
+                    RuleNamelist<<sRuleName;
+                }
+            }
+        }
+        
+    }
+
+    for(QString &sRuleName : RuleNamelist)
+    {
+        std::wstring sName = sRuleName.toStdWString();
+        pFwRules->Remove(const_cast<BSTR>(sName.c_str()));
+    }
+
+	// Release pFwRule
+	if (pFwRule != NULL)
+	{
+		pFwRule->Release();
+	}
+
+    if(pFwRules != NULL)
+    {
+        pFwRules->Release();
+    }
+}
+
+bool CWindowsFireWall::disableAllApp()
+{   
+    HRESULT hr = S_OK;
+
+    std::vector<CProcessData> vAppList;
+    if(getAllAppNameList(vAppList))
+    {
+        uploadAppLog(vAppList);
+    }
+
+    INetFwRules *pNetFwRules = NULL;
+    hr = m_pNetFwPolicy2->get_Rules(&pNetFwRules);
+
+    if (FAILED(hr))
+    {
+        m_sErrMsg = QString("Failed to retrieve firewall rules collection : 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+    }
+
+    for(CProcessData &data : vAppList)
+    {
+        if(data.bDisabled)
+        {
+            continue;
+        }
+
+        bool bSucceed = true;
+
+        INetFwRule  *pNetFwRule = NULL;
+        INetFwRule2 *pNetFwRule2 = NULL;
+
+        WCHAR pwszTemp[STRING_BUFFER_SIZE] = L"";
+
+        BSTR RuleName = NULL;
+        BSTR RuleGroupName = NULL;
+        BSTR RuleDescription = NULL;
+        BSTR RuleAppPath = NULL;
+
+        hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, (L"disable_coe_" + data.sExeName).c_str());
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("Failed to compose a resource identifier string: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        RuleName = SysAllocString(pwszTemp);
+        if (NULL == RuleName)
+        {
+            m_sErrMsg = QString("ERROR: Insufficient memory");
+            bSucceed = false;
+        }
+
+        hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, L"coe");
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("Failed to compose a resource identifier string: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+        RuleGroupName = SysAllocString(pwszTemp);  // Used for grouping together multiple rules
+        if (NULL == RuleGroupName)
+        {
+            m_sErrMsg = QString("ERROR: Insufficient memory");
+            bSucceed = false;
+        }
+
+        hr = StringCchPrintfW(pwszTemp, STRING_BUFFER_SIZE, (L"disable " + data.sExeName).c_str());
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("Failed to compose a resource identifier string: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+        RuleDescription = SysAllocString(pwszTemp);
+        if (NULL == RuleDescription)
+        {
+            m_sErrMsg = "ERROR: Insufficient memory";
+            bSucceed = false;
+        }
+
+        RuleAppPath = SysAllocString(data.sExePath.c_str());
+        if (NULL == RuleAppPath)
+        {
+            m_sErrMsg = "ERROR: Insufficient memory";
+            bSucceed = false;
+        }
+
+//        hr = m_pNetFwPolicy2->get_Rules(&pNetFwRules);
+
+//        if (FAILED(hr))
+//        {
+//            m_sErrMsg = QString("Failed to retrieve firewall rules collection : 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+//            bSucceed = false;
+//        }
+
+        hr = CoCreateInstance(
+            __uuidof(NetFwRule),    //CLSID of the class whose object is to be created
+            NULL,
+            CLSCTX_INPROC_SERVER,
+            __uuidof(INetFwRule),   // Identifier of the Interface used for communicating with the object
+            (void**)&pNetFwRule);
+
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("CoCreateInstance for INetFwRule failed: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+
+
+        hr = pNetFwRule->put_Name(RuleName);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Name failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_Grouping(RuleGroupName);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Grouping failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_Description(RuleDescription);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Description failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_Direction(NET_FW_RULE_DIR_OUT);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Direction failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_Action(NET_FW_ACTION_BLOCK);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Action failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_ApplicationName(RuleAppPath);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_ApplicationName failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_Profiles(NET_FW_PROFILE2_DOMAIN | NET_FW_PROFILE2_PRIVATE | NET_FW_PROFILE2_PUBLIC);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Profiles failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
+        if ( FAILED(hr) )
+        {
+            m_sErrMsg = QString("Failed INetFwRule::put_Enabled failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+
+        // Check if INetFwRule2 interface is available (i.e Windows7+)
+        // If supported, then use EdgeTraversalOptions
+        // Else use the EdgeTraversal boolean flag.
+
+        if (SUCCEEDED(pNetFwRule->QueryInterface(__uuidof(INetFwRule2), (void**)&pNetFwRule2)))
+        {
+            hr = pNetFwRule2->put_EdgeTraversalOptions(NET_FW_EDGE_TRAVERSAL_TYPE_DENY);
+            if ( FAILED(hr) )
+            {
+                m_sErrMsg = QString("Failed INetFwRule::put_EdgeTraversalOptions failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            }
+        }
+        else
+        {
+            hr = pNetFwRule->put_EdgeTraversal(VARIANT_FALSE);
+            if ( FAILED(hr) )
+            {
+                m_sErrMsg = QString("Failed INetFwRule::put_EdgeTraversal failed with error: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+                bSucceed = false;
+            }
+        }
+
+        hr = pNetFwRules->Add(pNetFwRule);
+        if (FAILED(hr))
+        {
+            m_sErrMsg = QString("Failed to add firewall rule to the firewall rules collection: 0x%1").arg(hr, 8, 16, QLatin1Char('0'));
+            bSucceed = false;
+        }
+
+        if(bSucceed)
+        {
+            data.bDisabled = true;
+            m_vDisableRuleNames.push_back(RuleName);
+            qDebug()<<QString::fromStdWString(RuleName);
+        }
+        else
+        {
+            qDebug()<<RuleName<<":"<<m_sErrMsg;
+        }
+
+        SysFreeString(RuleName);
+        SysFreeString(RuleGroupName);
+        SysFreeString(RuleDescription);
+        SysFreeString(RuleAppPath);
+
+        if (pNetFwRule2 != NULL)
+        {
+            pNetFwRule2->Release();
+        }
+
+        if (pNetFwRule != NULL)
+        {
+            pNetFwRule->Release();
+        }
+
+    }
+
+    if (pNetFwRules != NULL)
+    {
+        pNetFwRules->Release();
+    }
+
+    return hr;
+}
+
+std::wstring GetPathByProcessID(DWORD pid)
+{
+    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+    if (!hProcess)
+    {
+        return L"";
+    }
+    WCHAR filePath[MAX_PATH];
+    DWORD ret = GetModuleFileNameEx(hProcess, NULL, filePath, MAX_PATH) ;
+
+    CloseHandle(hProcess);
+    return ret == 0 ? L"" : filePath;
+}
+
+// dos 文件路径转 windows 文件路径
+BOOL DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath)
+{
+    TCHAR			szDriveStr[500];
+    TCHAR			szDrive[3];
+    TCHAR			szDevName[100];
+    INT				cchDevName;
+    INT				i;
+
+    //检查参数
+    if(!pszDosPath || !pszNtPath )
+        return FALSE;
+
+    //获取本地磁盘字符串
+    if(GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr))
+    {
+        for(i = 0; szDriveStr[i]; i += 4)
+        {
+            if(!lstrcmpi(&(szDriveStr[i]), _T("A:\\")) || !lstrcmpi(&(szDriveStr[i]), _T("B:\\"))){continue;}
+
+            szDrive[0] = szDriveStr[i];
+            szDrive[1] = szDriveStr[i + 1];
+            szDrive[2] = '\0';
+            // 查询 Dos 设备名
+            if(!QueryDosDevice(szDrive, szDevName, 100)){return FALSE;}
+
+            // 命中
+            cchDevName = lstrlen(szDevName);
+            if(_tcsnicmp(pszDosPath, szDevName, cchDevName) == 0){
+                // 复制驱动器
+                lstrcpy(pszNtPath, szDrive);
+
+                // 复制路径
+                lstrcat(pszNtPath, pszDosPath + cchDevName);
+
+                return TRUE;
+            }
+        }
+    }
+
+    lstrcpy(pszNtPath, pszDosPath);
+
+    return FALSE;
+}
+
+// 获取进程全路径
+BOOL GetProcessFullPath(DWORD dwPID, std::wstring &fullPath){
+    TCHAR		szImagePath[MAX_PATH]={'\0'};
+    TCHAR		pszFullPath[MAX_PATH]={'\0'};
+    HANDLE		hProcess;
+
+
+    // 获取进程句柄失败
+    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPID);
+    if(!hProcess){return FALSE;}
+
+    // 获取进程完整路径失败
+    if(!GetProcessImageFileName(
+        hProcess,					// 进程句柄
+        szImagePath,				// 接收进程所属文件全路径的指针
+        MAX_PATH					// 缓冲区大小
+    )){
+        CloseHandle(hProcess);
+        return FALSE;
+    }
+
+    // 路径转换失败
+    if(!DosPathToNtPath(szImagePath, pszFullPath)){
+        CloseHandle(hProcess);
+        return FALSE;
+    }
+
+    CloseHandle(hProcess);
+
+    // 导出文件全路径
+    fullPath = pszFullPath;
+
+    return TRUE;
+}
+
+bool CWindowsFireWall::getAllAppNameList(std::vector<CProcessData> &vAppList)
+{
+    bool bRet = false;
+    PROCESSENTRY32 pe32;
+    pe32.dwSize = sizeof(pe32);
+    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if(hProcessSnap == INVALID_HANDLE_VALUE)
+    {
+        return bRet;
+    }
+
+    BOOL bMore = Process32First(hProcessSnap,&pe32);
+    QStringList list;
+    while(bMore)
+    {
+        std::wstring sExePath = L"";
+        GetProcessFullPath( pe32.th32ProcessID, sExePath);
+        QString sPath = QString::fromStdWString(sExePath).toLower();
+
+        if(pe32.th32ProcessID != m_pid &&
+                !sExePath.empty() &&
+//                sPath.indexOf("c:\\windows\\system32") < 0 &&
+                sPath.toLower().indexOf("svchost.exe") < 0 &&
+//                sPath.toLower().indexOf("upgrade") < 0 &&
+                list.indexOf(QString::fromStdWString(pe32.szExeFile).toLower()) < 0)
+        {
+            list<<QString::fromStdWString(pe32.szExeFile).toLower();
+            CProcessData data;
+            data.pid = pe32.th32ProcessID;
+            data.sExeName = pe32.szExeFile;
+            data.sExePath = sExePath;
+
+            vAppList.push_back(data);
+            bRet = true;
+        }
+        bMore = Process32Next(hProcessSnap,&pe32);
+    }
+    CloseHandle(hProcessSnap);
+    return bRet;
+}
+

+ 65 - 0
component/CWindowsFireWall.h

@@ -0,0 +1,65 @@
+#ifndef CWINDOWSFIREWALL_H
+#define CWINDOWSFIREWALL_H
+
+#include <windows.h>
+#include <netfw.h>
+#include <QString>
+#include <vector>
+#include <thread>
+
+class CProcessData
+{
+public:
+    DWORD pid = 0;
+    std::wstring sExeName = L"";
+    std::wstring sExePath = L"";
+    bool bDisabled = false;
+};
+
+class CWindowsFireWall
+{
+public:
+    CWindowsFireWall()=delete;
+    CWindowsFireWall(DWORD pid, bool bcheck = true);
+    ~CWindowsFireWall();
+
+    void removeLastRules();
+private:
+    bool init();
+    bool setWallOn();
+    bool disableAllApp();
+
+    void cleanup();
+    bool getAllAppNameList(std::vector<CProcessData> &vAppList);
+    HRESULT WFCOMInitialize(INetFwPolicy2** ppNetFwPolicy2);
+    void setAllRulesEnabled(VARIANT_BOOL bEnable);
+
+
+    void threadProc();
+    void checkInprogressFireWall();
+    void uploadAppLog(std::vector<CProcessData> &vAppList);
+    void checkRulesIsEnabled();
+
+    std::thread *m_pThrd;
+    DWORD m_wthreadID;
+    bool m_bIsRun = true;
+
+    HRESULT m_comInit = E_FAIL;
+    INetFwPolicy2 *m_pNetFwPolicy2 = NULL;
+
+
+    QString m_sErrMsg;
+
+    std::vector<std::wstring> m_vDisableRuleNames;
+    VARIANT_BOOL m_fw_profile2_domain_enabled = VARIANT_TRUE;
+    VARIANT_BOOL m_fw_profile2_private_enabled = VARIANT_TRUE;
+    VARIANT_BOOL m_fw_profile2_public_enabled = VARIANT_TRUE;
+    bool m_bModifyFireWall = false;
+    DWORD m_pid = 0;
+
+    const int m_inprogressCheckSeconds = 60*5;
+    bool m_bcheck = true;
+};
+
+extern std::shared_ptr<CWindowsFireWall> g_windowsFireWallPtr;
+#endif // CWINDOWSFIREWALL_H

+ 7 - 0
component/clOperation.cpp

@@ -3,6 +3,7 @@
 
 #include "CAppInfo.h"
 #include "logproc.h"
+#include <QTimer>
 
 clOperation::clOperation(const int nRow, QWidget *parent) :
     QWidget(parent),
@@ -205,7 +206,13 @@ void clOperation::on_btn1_clicked()
             || m_operationType == CL_OPERATION_TYPE::cot_online_homework)
     {
         //进入考试
+        ui->btn1->setEnabled(false);
+
         enterExam(m_operationType, m_nRow);
+
+        QTimer::singleShot(3000, this, [&](){
+            ui->btn1->setEnabled(true);
+        });
     }
     else if(m_operationType == CL_OPERATION_TYPE::cot_online_practice_result)
     {

+ 2 - 0
component/component.pri

@@ -3,6 +3,7 @@ QT       += websockets
 HEADERS += \
     $$PWD/CKeyBoardHook.h \
     $$PWD/CWebsocketProc.h \
+    $$PWD/CWindowsFireWall.h \
     $$PWD/CheckHeaderView.h \
     $$PWD/CustomIconStyle.h \
     $$PWD/PagingWidget.h \
@@ -11,6 +12,7 @@ HEADERS += \
 SOURCES += \
     $$PWD/CKeyBoardHook.cpp \
     $$PWD/CWebsocketProc.cpp \
+    $$PWD/CWindowsFireWall.cpp \
     $$PWD/CheckHeaderView.cpp \
     $$PWD/CustomIconStyle.cpp \
     $$PWD/PagingWidget.cpp \

+ 62 - 14
face/faceCompare.cpp

@@ -25,9 +25,12 @@ faceCompare::faceCompare(QWidget *parent) :
     m_bStartCompare = false;
 
     qRegisterMetaType<CBaseResponsePackage>("CBaseResponsePackage");
-	qRegisterMetaType<CProcessUpload>("CProcessUpload");
-    connect(g_httpBllPtr.get(), &CHttpBll::sgnProcessUpload, this, &faceCompare::onProcessUpload);
+    qRegisterMetaType<CClientExamProcessUploadSign>("CClientExamProcessUploadSign");
+    qRegisterMetaType<CUploadFileToAliyun>("CUploadFileToAliyun");
+
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnClientExamProcessUploadSign, this, &faceCompare::onClientExamProcessUploadSign);
     connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceCompareResult, this, &faceCompare::onSaveFaceCompareResult);
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnUploadFileToAliyun, this, &faceCompare::onUploadFileToAliyun);
 
 
     QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
@@ -267,9 +270,9 @@ void faceCompare::threadProc()
                     else
                     {
 #ifdef _DEBUG
-						g_appInfoPtr->m_oExamInfo.nWarnThreshold = 1;
+                        g_appInfoPtr->m_oExamInfo.nFaceThreshold = 1;
 #endif // _DEBUG
-                        if(fScore*100 > g_appInfoPtr->m_oExamInfo.nWarnThreshold)
+                        if(fScore*100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold)
                         {
 							m_fScore = fScore;
 							m_nFaceCount = nFaceCount;
@@ -280,13 +283,14 @@ void faceCompare::threadProc()
                             imgCompare.save(sFileName, "PNG");
 
                             CHttpRequestPackage hrp;
-                            hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload";
-                            hrp.nRequestType = RequestType::rtProcessUpload;
+                            hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload/sign";
+                            hrp.nRequestType = RequestType::rtClientExamProcessUploadSign;
                             hrp.sCommonStr = __FILE__;
-                            hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(sFileName));
-                            hrp.sParamList.push_back(QString("md5,%1").arg(CCommonTools::fileMd5(sFileName)));
+                            hrp.sCommonStr1 = sFileName;
+                            hrp.sParamList.push_back(QString("fileSuffix,%1").arg(".png"));
+                            hrp.sParamList.push_back(QString("fileMd5,%1").arg(CCommonTools::fileMd5(sFileName)));
 
-                            hrp.eParamType = HttpParamType::hptFormdata;
+                            hrp.eParamType = HttpParamType::hptBody;
                             g_httpBllPtr->post(hrp);
                         }
                         else
@@ -296,7 +300,7 @@ void faceCompare::threadProc()
                         }
                     }
                 }
-				m_bStartCompare = false;
+                m_bStartCompare = false;
             }
         }
         else
@@ -307,20 +311,64 @@ void faceCompare::threadProc()
 }
 
 //文件上传
-void faceCompare::onProcessUpload(CProcessUpload processUpload)
+void faceCompare::onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload)
 {
     try
     {
         if(processUpload.sCommonStr == __FILE__)
         {
             if(processUpload.nCode == 200)
+            {
+                CHttpRequestPackage hrp;
+                hrp.sUri = processUpload.sFormUrl;
+                hrp.nRequestType = RequestType::rtUploadFileToAliyun;
+                hrp.sCommonStr = __FILE__;
+                hrp.sCommonStr1 = processUpload.sAccessUrl;
+                hrp.sParamList.push_back(QString("OSSAccessKeyId,%1").arg(processUpload.sOssAcessKeyId));
+                hrp.sParamList.push_back(QString("Signature,%1").arg(processUpload.sSignature));
+                hrp.sParamList.push_back(QString("key,%1").arg(processUpload.sKey));
+                hrp.sParamList.push_back(QString("policy,%1").arg(processUpload.sPolicy));
+                hrp.sParamList.push_back(QString("success_action_status,%1").arg(200));
+                hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(processUpload.sFilePath));
+                hrp.bNoHostPrefix = true;
+                hrp.eParamType = HttpParamType::hptFormdata;
+                g_httpBllPtr->post(hrp);
+
+            }
+            else
+            {
+                if(processUpload.sMessage.isEmpty())
+                {
+                    ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
+                }
+                else
+                {
+                    ShowMsg(processUpload.sMessage, this, MSG_ICON_TYPE::mit_error);
+                }
+            }
+        }
+    }
+    catch (const std::exception &e)
+    {
+        ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
+        myServerLog()<<"exception error"<<e.what();
+    }
+}
+
+void faceCompare::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun)
+{
+    try
+    {
+        if(uploadFileToAliyun.sCommonStr == __FILE__)
+        {
+            if(uploadFileToAliyun.nCode == 200)
             {
                 CHttpRequestPackage hrp;
                 hrp.sUri = "/api/ecs_oe_student/client/exam/process/saveFaceCompareResult";
                 hrp.nRequestType = RequestType::rtSaveFaceCompareResult;
                 Json::Value jBody = Json::Value::null;
                 jBody["faceCompareResult"] = QString::number(m_fScore).toStdString();
-                jBody["fileUrl"] = processUpload.sFileUrl.toStdString();
+                jBody["fileUrl"] = uploadFileToAliyun.sFileUrl.toStdString();
                 jBody["pass"] = true;
                 jBody["processTime"] = m_nTime;
                 jBody["stranger"] = m_nFaceCount > 1;
@@ -331,13 +379,13 @@ void faceCompare::onProcessUpload(CProcessUpload processUpload)
             }
             else
             {
-                if(processUpload.sMessage.isEmpty())
+                if(uploadFileToAliyun.sMessage.isEmpty())
                 {
                     ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
                 }
                 else
                 {
-                    ShowMsg(processUpload.sMessage, this, MSG_ICON_TYPE::mit_error);
+                    ShowMsg(uploadFileToAliyun.sMessage, this, MSG_ICON_TYPE::mit_error);
                 }
             }
         }

+ 2 - 1
face/faceCompare.h

@@ -33,7 +33,8 @@ private slots:
 
     void on_btn_fc_close_clicked();
 
-    void onProcessUpload(CProcessUpload processUpload); //文件上传
+    void onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload); //文件上传
+    void onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun);
     void onSaveFaceCompareResult(CBaseResponsePackage res);//保存人脸识别比对验证结果
 
     void onDownLoadFile(CDownLoadFileInfo downLoadFileInfo);

+ 80 - 31
face/faceLiveness.cpp

@@ -22,18 +22,22 @@ faceLiveness::faceLiveness(FACE_LIVENESS_TYPE livenessType, QWidget *parent) :
     initUI();
 
     qRegisterMetaType<CBaseResponsePackage>("CBaseResponsePackage");
-    qRegisterMetaType<CProcessUpload>("CProcessUpload");
-    connect(g_httpBllPtr.get(), &CHttpBll::sgnProcessUpload, this, &faceLiveness::onProcessUpload);
+    qRegisterMetaType<CClientExamProcessUploadSign>("CClientExamProcessUploadSign");
+    qRegisterMetaType<CUploadFileToAliyun>("CUploadFileToAliyun");
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnClientExamProcessUploadSign, this, &faceLiveness::onClientExamProcessUploadSign);
     connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceLiveVerifyResult, this, &faceLiveness::onSaveFaceLiveVerifyResult);
     connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceCompareResult, this, &faceLiveness::onSaveFaceCompareResult);
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnUploadFileToAliyun, this, &faceLiveness::onUploadFileToAliyun);
 
     if(m_livenessType == FACE_LIVENESS_TYPE::flt_inprogress)
     {
         ui->label_fl_time->setVisible(true);
+        ui->btn_fl_close->setVisible(false);
     }
     else
     {
         ui->label_fl_time->setVisible(false);
+        ui->btn_fl_close->setVisible(true);
     }
 
     m_nMaxSeconds = g_appInfoPtr->m_oExamInfo.nAllActionDuration;
@@ -222,9 +226,9 @@ void faceLiveness::initUI()
                                     ui->label_fl_title->width(), ui->label_fl_title->height());
     ui->label_fl_time->setGeometry(ui->label_fl_title->x() + ui->label_fl_title->width(), ui->label_fl_title->y(),
                                    g_appInfoPtr->m_fRate*200, ui->label_fl_title->height());
-    ui->btn_fc_close->setGeometry(ui->widget_fc_BG->width() - g_appInfoPtr->m_fRate*(20 + 16),
-                                  g_appInfoPtr->m_fRate*16, g_appInfoPtr->m_fRate*16, g_appInfoPtr->m_fRate*16);
-    ui->btn_fc_close->setVisible(false);
+    ui->btn_fl_close->setGeometry(ui->widget_fc_BG->width() - g_appInfoPtr->m_fRate*(20 + 100),
+                                  g_appInfoPtr->m_fRate*16, g_appInfoPtr->m_fRate*100, g_appInfoPtr->m_fRate*36);
+
     ui->widget_fc_camera->setGeometry(g_appInfoPtr->m_fRate*30, g_appInfoPtr->m_fRate*75,
                                      g_appInfoPtr->m_fRate*740, g_appInfoPtr->m_fRate*320);
     ui->btn_fl_startVerify->setGeometry((ui->widget_fc_camera->width() - g_appInfoPtr->m_fRate*160)/2,
@@ -348,7 +352,7 @@ void faceLiveness::verifyAction(cv::Mat matImage)
 				return;
 			}
 
-			if (fScore * 100 > g_appInfoPtr->m_oExamInfo.nWarnThreshold)
+            if (fScore * 100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold)
 			{
 				bool bRealness = false;
 				if (!g_faceRecProcPtr->faceRealness(matImage, bRealness))
@@ -452,11 +456,6 @@ void faceLiveness::verifyAction(cv::Mat matImage)
 	}
 }
 
-void faceLiveness::on_btn_fc_close_clicked()
-{
-
-}
-
 bool faceLiveness::setBaseImage()
 {
     QString sFileName = g_appInfoPtr->m_sStudentPhotoPath.right(g_appInfoPtr->m_sStudentPhotoPath.length() - g_appInfoPtr->m_sStudentPhotoPath.lastIndexOf("/") - 1);
@@ -587,13 +586,14 @@ void faceLiveness::saveLivenessResult()
 				img.save(sImageFile, "PNG");
 				//上传图片
 				CHttpRequestPackage hrp;
-				hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload";
-				hrp.nRequestType = RequestType::rtProcessUpload;
-                hrp.sCommonStr = __FILE__;
-				hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(sImageFile));
-				hrp.sParamList.push_back(QString("md5,%1").arg(CCommonTools::fileMd5(sImageFile)));
-
-				hrp.eParamType = HttpParamType::hptFormdata;
+                hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload/sign";
+                hrp.nRequestType = RequestType::rtClientExamProcessUploadSign;
+                hrp.sCommonStr = __FILE__;			
+                hrp.sCommonStr1 = sImageFile;
+                hrp.sParamList.push_back(QString("fileSuffix,%1").arg(".png"));
+                hrp.sParamList.push_back(QString("fileMd5,%1").arg(CCommonTools::fileMd5(sImageFile)));
+
+                hrp.eParamType = HttpParamType::hptBody;
 				g_httpBllPtr->post(hrp);
 				break;
 			}
@@ -644,7 +644,7 @@ void faceLiveness::saveLivenessResult()
 			hrp.eParamType = HttpParamType::hptCustomBody;
 			hrp.sParamList.push_back(QString("CustomBody,%1").arg(jLiveness.toStyledString().c_str()));
 
-			g_httpBllPtr->post(hrp);
+            g_httpBllPtr->post(hrp);
 
 		}
 	}
@@ -809,16 +809,60 @@ void faceLiveness::actionTimer()
 }
 
 //文件上传
-void faceLiveness::onProcessUpload(CProcessUpload processUpload)
+void faceLiveness::onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload)
 {
-	try
-	{
+    try
+    {
         if(processUpload.sCommonStr == __FILE__)
         {
-            if (processUpload.nCode == 200)
+            if(processUpload.nCode == 200)
+            {
+                CHttpRequestPackage hrp;
+                hrp.sUri = processUpload.sFormUrl;
+                hrp.nRequestType = RequestType::rtUploadFileToAliyun;
+                hrp.sCommonStr = __FILE__;
+                hrp.sCommonStr1 = processUpload.sAccessUrl;
+                hrp.sParamList.push_back(QString("OSSAccessKeyId,%1").arg(processUpload.sOssAcessKeyId));
+                hrp.sParamList.push_back(QString("Signature,%1").arg(processUpload.sSignature));
+                hrp.sParamList.push_back(QString("key,%1").arg(processUpload.sKey));
+                hrp.sParamList.push_back(QString("policy,%1").arg(processUpload.sPolicy));
+                hrp.sParamList.push_back(QString("success_action_status,%1").arg(200));
+                hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(processUpload.sFilePath));
+                hrp.bNoHostPrefix = true;
+                hrp.eParamType = HttpParamType::hptFormdata;
+                g_httpBllPtr->post(hrp);
+
+            }
+            else
+            {
+                if(processUpload.sMessage.isEmpty())
+                {
+                    ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
+                }
+                else
+                {
+                    ShowMsg(processUpload.sMessage, this, MSG_ICON_TYPE::mit_error);
+                }
+            }
+        }
+    }
+    catch (const std::exception &e)
+    {
+        ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
+        myServerLog()<<"exception error"<<e.what();
+    }
+}
+
+void faceLiveness::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun)
+{
+    try
+    {
+        if(uploadFileToAliyun.sCommonStr == __FILE__)
+        {
+            if (uploadFileToAliyun.nCode == 200)
             {
                 m_nRetryCount = 0;
-                m_livenessList[m_nCurIndex].sUrl = processUpload.sFileUrl;
+                m_livenessList[m_nCurIndex].sUrl = uploadFileToAliyun.sFileUrl;
                 if(m_livenessType == FACE_LIVENESS_TYPE::flt_entry_exam &&
                         m_livenessList[m_nCurIndex].sActionType == ACTION_TYPE::AT_FACE_DETECT)
                 {
@@ -832,13 +876,13 @@ void faceLiveness::onProcessUpload(CProcessUpload processUpload)
             }
             else
             {
-                if (processUpload.sMessage.isEmpty())
+                if (uploadFileToAliyun.sMessage.isEmpty())
                 {
                     ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
                 }
                 else
                 {
-                    ShowMsg(processUpload.sMessage, this, MSG_ICON_TYPE::mit_error);
+                    ShowMsg(uploadFileToAliyun.sMessage, this, MSG_ICON_TYPE::mit_error);
                 }
 
                 if(m_nRetryCount < 4)
@@ -852,11 +896,11 @@ void faceLiveness::onProcessUpload(CProcessUpload processUpload)
                 }
             }
         }
-	}
-	catch (const std::exception &e)
-	{
-		myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what());
-	}
+    }
+    catch (const std::exception &e)
+    {
+        myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what());
+    }
 }
 
 void faceLiveness::saveFaceCampareResult()
@@ -991,3 +1035,8 @@ void faceLiveness::onSaveFaceLiveVerifyResult(CBaseResponsePackage res)
 		myDebug() << QString::fromLocal8Bit("人脸比对失败,%1").arg(e.what());
 	}
 }
+
+void faceLiveness::on_btn_fl_close_clicked()
+{
+    emit faceLivenessFaild();
+}

+ 4 - 2
face/faceLiveness.h

@@ -99,16 +99,18 @@ public:
     ~faceLiveness();
 
 private slots:
-    void on_btn_fc_close_clicked();
 
     void on_btn_fl_startVerify_clicked();
 
-    void onProcessUpload(CProcessUpload processUpload); //文件上传
+    void onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload); //文件上传
+    void onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun);
     void onSaveFaceLiveVerifyResult(CBaseResponsePackage res);//保存人脸活体验证结果
     void onSaveFaceCompareResult(CBaseResponsePackage res);
 
     void actionTimer();
     void countdownTimer();
+    void on_btn_fl_close_clicked();
+
 private:
     void initUI();
     void initAcionIcon();

+ 2 - 2
face/faceLiveness.ui

@@ -44,7 +44,7 @@
       <string>人脸检测</string>
      </property>
     </widget>
-    <widget class="QPushButton" name="btn_fc_close">
+    <widget class="QPushButton" name="btn_fl_close">
      <property name="geometry">
       <rect>
        <x>544</x>
@@ -57,7 +57,7 @@
       <enum>Qt::NoFocus</enum>
      </property>
      <property name="text">
-      <string/>
+      <string>退出</string>
      </property>
     </widget>
     <widget class="QLabel" name="label_fl_tips">

+ 65 - 25
face/inprogressFace.cpp

@@ -10,11 +10,13 @@ std::shared_ptr<CInprogressFace> g_inProcessFace = nullptr;
 
 CInprogressFace::CInprogressFace()
 {
-	qRegisterMetaType<CProcessUpload>("CProcessUpload");
-	connect(g_httpBllPtr.get(), &CHttpBll::sgnProcessUpload, this, &CInprogressFace::onProcessUpload);
+    qRegisterMetaType<CClientExamProcessUploadSign>("CClientExamProcessUploadSign");
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnClientExamProcessUploadSign, this, &CInprogressFace::onClientExamProcessUploadSign);
 	qRegisterMetaType<CBaseResponsePackage>("CBaseResponsePackage");
 	connect(g_httpBllPtr.get(), &CHttpBll::sgnSaveFaceCaptureResult, this, &CInprogressFace::onSaveFaceCaptureResult);
-	
+    qRegisterMetaType<CUploadFileToAliyun>("CUploadFileToAliyun");
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnUploadFileToAliyun, this, &CInprogressFace::onUploadFileToAliyun);
+
     genCameraInfo();
 
     m_bIsRun = true;
@@ -211,17 +213,18 @@ void CInprogressFace::uploadFile(cv::Mat faceMat, int nFaceCount, float fScore,
     imgCompare.save(sFileName, "PNG");
 
     CHttpRequestPackage hrp;
-    hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload";
-    hrp.nRequestType = RequestType::rtProcessUpload;
-    hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(sFileName));
-    hrp.sParamList.push_back(QString("md5,%1").arg(CCommonTools::fileMd5(sFileName)));
+    hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload/sign";
+    hrp.nRequestType = RequestType::rtClientExamProcessUploadSign;
+    hrp.sParamList.push_back(QString("fileSuffix,%1").arg(".png"));
+    hrp.sParamList.push_back(QString("fileMd5,%1").arg(CCommonTools::fileMd5(sFileName)));
     hrp.sCommonStr = QString("%1,%2,%3,%4").arg(__FILE__).arg(nFaceCount).arg(fScore).arg(nRealness);
-    hrp.eParamType = HttpParamType::hptFormdata;
+    hrp.sCommonStr1 = sFileName;
+    hrp.eParamType = HttpParamType::hptBody;
     g_httpBllPtr->post(hrp);
 }
 
 //文件上传
-void CInprogressFace::onProcessUpload(CProcessUpload processUpload)
+void CInprogressFace::onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload)
 {    
     QStringList list = processUpload.sCommonStr.split(",");
     if(list.count() == 4)
@@ -235,22 +238,21 @@ void CInprogressFace::onProcessUpload(CProcessUpload processUpload)
         {
 			if (processUpload.nCode == 200)
 			{
-				CHttpRequestPackage hrp;
-				hrp.sUri = "/api/ecs_oe_student/client/exam/process/saveFaceCaptureResult";
-				hrp.nRequestType = RequestType::rtSaveFaceCaptureResult;
-				Json::Value jBody = Json::Value::null;
-				jBody["examRecordDataId"] = g_appInfoPtr->m_oExamInfo.nExamRecordDataId;
-				jBody["faceCompareResult"] = fScore;
-				jBody["facelivenessResult"] = nRealness;
-				jBody["fileUrl"] = processUpload.sFileUrl.toStdString();
-				jBody["pass"] = (fScore * 100 > g_appInfoPtr->m_oExamInfo.nWarnThreshold) ? true : false;
-				jBody["stranger"] = nFaceCount > 1;
-                jBody["hasVirtualCamera"] = m_bHasVirtualCamera;
-                jBody["cameraInfos"] = m_sCameraInfo.toStdString();
-				hrp.sParamList.push_back(QString("CustomBody,%1").arg(jBody.toStyledString().c_str()));
-				hrp.eParamType = HttpParamType::hptCustomBody;
-				myDebug() << jBody.toStyledString().c_str();
-				g_httpBllPtr->post(hrp);
+                CHttpRequestPackage hrp;
+                hrp.sUri = processUpload.sFormUrl;
+                hrp.nRequestType = RequestType::rtUploadFileToAliyun;
+                hrp.sCommonStr = QString("%1,%2,%3,%4").arg(__FILE__).arg(nFaceCount).arg(fScore).arg(nRealness);;
+                hrp.sCommonStr1 = processUpload.sAccessUrl;
+                hrp.sParamList.push_back(QString("OSSAccessKeyId,%1").arg(processUpload.sOssAcessKeyId));
+                hrp.sParamList.push_back(QString("Signature,%1").arg(processUpload.sSignature));
+                hrp.sParamList.push_back(QString("key,%1").arg(processUpload.sKey));
+                hrp.sParamList.push_back(QString("policy,%1").arg(processUpload.sPolicy));
+                hrp.sParamList.push_back(QString("success_action_status,%1").arg(200));
+                hrp.sParamList.push_back(QString("formdataFileType,file,%1").arg(processUpload.sFilePath));
+                hrp.bNoHostPrefix = true;
+                hrp.eParamType = HttpParamType::hptFormdata;
+                g_httpBllPtr->post(hrp);
+
 			}
 			else
 			{
@@ -260,6 +262,44 @@ void CInprogressFace::onProcessUpload(CProcessUpload processUpload)
     }   
 }
 
+void CInprogressFace::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun)
+{
+    QStringList list = uploadFileToAliyun.sCommonStr.split(",");
+    if(list.count() == 4)
+    {
+        QString sFile = list[0];
+        int nFaceCount = list[1].toInt();
+        float fScore = list[2].toFloat();
+        int nRealness = list[3].toInt();
+
+        if(__FILE__ == sFile)
+        {
+            if (uploadFileToAliyun.nCode == 200)
+            {
+                CHttpRequestPackage hrp;
+                hrp.sUri = "/api/ecs_oe_student/client/exam/process/saveFaceCaptureResult";
+                hrp.nRequestType = RequestType::rtSaveFaceCaptureResult;
+                Json::Value jBody = Json::Value::null;
+                jBody["examRecordDataId"] = g_appInfoPtr->m_oExamInfo.nExamRecordDataId;
+                jBody["faceCompareResult"] = fScore;
+                jBody["facelivenessResult"] = nRealness;
+                jBody["fileUrl"] = uploadFileToAliyun.sFileUrl.toStdString();
+                jBody["pass"] = (fScore * 100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold) ? true : false;
+                jBody["stranger"] = nFaceCount > 1;
+                jBody["hasVirtualCamera"] = m_bHasVirtualCamera;
+                jBody["cameraInfos"] = m_sCameraInfo.toStdString();
+                hrp.sParamList.push_back(QString("CustomBody,%1").arg(jBody.toStyledString().c_str()));
+                hrp.eParamType = HttpParamType::hptCustomBody;
+                myDebug() << jBody.toStyledString().c_str();
+                g_httpBllPtr->post(hrp);
+            }
+            else
+            {
+
+            }
+        }
+    }
+}
 
 //保存人脸抓拍比对验证结果
 void CInprogressFace::onSaveFaceCaptureResult(CBaseResponsePackage res)

+ 2 - 1
face/inprogressFace.h

@@ -23,7 +23,8 @@ public:
 
     void uploadFile(cv::Mat faceMat, int nFaceCount, float fScore, int nRealness);
 private slots:
-    void onProcessUpload(CProcessUpload processUpload); //文件上传
+    void onClientExamProcessUploadSign(CClientExamProcessUploadSign processUpload); //文件上传
+    void onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun);
     void onSaveFaceCaptureResult(CBaseResponsePackage res);//保存人脸抓拍比对验证结果
 private:
     std::thread m_thread;

+ 73 - 15
launcher/envCheck.cpp

@@ -109,6 +109,7 @@ void envCheck::onStudentClientConfig(CStudentClientConfig studentClientConfig)
         g_appInfoPtr->m_bDisableRemoteAssistance = studentClientConfig.bDisableRemoteAssistance;
 
         g_appInfoPtr->m_bDisableVirtualCamera = studentClientConfig.bDisableVirtualCamera;
+        m_bDisableVirtualMachine = studentClientConfig.bDisableVirtualMachine;
     }
     else
     {
@@ -150,9 +151,16 @@ void envCheck::onGetSoftwareConfig(CGetSoftwareConfig getSoftwareConfig)
 
                 m_sCameraList += cameraList;
 
-                m_sRemoteList += remoteAppList;
-                m_sRemoteTipList += remoteAppList;
-            }
+                for(QString remoteApp : remoteAppList)
+                {
+                    QString remoteAppProcess = remoteApp.left(remoteApp.indexOf("@@@"));
+                    QString remoteAppName = remoteApp.right(remoteApp.length() - remoteApp.indexOf("@@@") - 3);
+                    m_sRemoteList<<remoteAppProcess;
+                    m_sRemoteTipList<<remoteAppName;
+                }
+//                m_sRemoteList += remoteAppList;
+//                m_sRemoteTipList += remoteAppList;
+           }
         }
     }
 
@@ -187,6 +195,27 @@ void envCheck::initUI()
 void envCheck::checkProc()
 {
     QString sCheckStr = "";
+
+    if(m_bDisableVirtualMachine)
+    {
+        ui->label_checkItem->setText(QString::fromLocal8Bit("正在检测是否在虚拟机上运行 …"));
+        bool IsInsideVM;
+        QString sErrMsg;
+        if(IsInsideVirtualMachine(IsInsideVM, sErrMsg))
+        {
+            if(IsInsideVM)
+            {
+                m_unpasslist.push_back(QString::fromLocal8Bit("请勿在虚拟机上运行考试程序"));
+                myServerLog()<<QString::fromLocal8Bit("请勿在虚拟机上运行考试程序");
+            }
+        }
+        else if(!sErrMsg.isEmpty())
+        {
+            m_unpasslist.push_back(sErrMsg);
+            myServerLog()<<sErrMsg;
+        }
+    }
+
     if(g_appInfoPtr->m_bDisableRemoteAssistance)
     {
         ui->label_checkItem->setText(QString::fromLocal8Bit("正在检测是否存在远程桌面 …"));
@@ -222,6 +251,8 @@ void envCheck::checkProc()
         CCommonTools::listCameraDevices(cameraList, UnpassList, m_sCameraList);
         for(CameraInfo ci : cameraList)
         {
+            myServerLog()<<QString::fromLocal8Bit("摄像头信息,vid:%1,pid%2:,name:%3")
+                           .arg(ci.vid).arg(ci.pid).arg(ci.name);
             if(ci.vid.empty() || ci.pid.empty())
             {
                 if(UnpassList.indexOf(ci.name, Qt::CaseInsensitive) >= 0)
@@ -260,23 +291,24 @@ void envCheck::checkProc()
         {
             for(int i = 0; i < appList.count(); i++)
             {
-                if(sCheckStr.isEmpty())
-                {
+//                if(sCheckStr.isEmpty())
+//                {
                     sCheckStr = QString::fromLocal8Bit("请检测是否开启%1").arg(appList[i]);
-                }
-                else
-                {
-                    sCheckStr += QString::fromLocal8Bit("、%1").arg(appList[i]);
-                }
+                    m_unpasslist.push_back(sCheckStr);
+//                }
+//                else
+//                {
+//                    sCheckStr += QString::fromLocal8Bit("、%1").arg(appList[i]);
+//                }
             }
         }
     }
 
-    if(!sCheckStr.isEmpty())
-    {
-        m_unpasslist.push_back(sCheckStr);
-        myServerLog()<<QString::fromLocal8Bit("环境检测异常,")<<sCheckStr;
-    }
+//    if(!sCheckStr.isEmpty())
+//    {
+//        m_unpasslist.push_back(sCheckStr);
+//        myServerLog()<<QString::fromLocal8Bit("环境检测异常,")<<sCheckStr;
+//    }
 
     if(m_unpasslist.count() > 0)
     {
@@ -291,6 +323,32 @@ void envCheck::checkProc()
 
 }
 
+
+bool envCheck::IsInsideVirtualMachine(bool &IsInsideVM, QString &sErrMsg)
+{
+    typedef bool(_stdcall *VMCfn)(void);
+
+    //需要的时候调用DLL
+    HMODULE hModule = LoadLibrary(L"VMC.dll");
+    if (NULL == hModule)
+    {
+        sErrMsg = QString::fromLocal8Bit("程序文件丢失,请重新安装!");
+        return false;
+    }
+
+    VMCfn fn = (VMCfn)GetProcAddress(hModule, "IsIVM");
+    if(NULL == fn)
+    {
+        sErrMsg = QString::fromLocal8Bit("");
+        return false;
+    }
+    IsInsideVM = fn();
+    //释放DLL
+    FreeLibrary(hModule);
+
+    return true;
+}
+
 void envCheck::startCheck()
 {
     CHttpRequestPackage hrp;

+ 3 - 0
launcher/envCheck.h

@@ -30,6 +30,7 @@ private slots:
 private:
     void initUI();
     void checkProc();
+    bool IsInsideVirtualMachine(bool &IsInsideVM, QString &sErrMsg);
 
     Ui::envCheck *ui;
 
@@ -42,6 +43,8 @@ private:
     QStringList m_sRemoteTipList;
 
     std::shared_ptr<CMultiMonitorEnumerator> m_MonitorEnumeratorPtr;
+
+    bool m_bDisableVirtualMachine = false;
 };
 
 #endif // ENVCHECK_H

+ 15 - 0
launcher/launcher.cpp

@@ -17,6 +17,10 @@
 #include <QFileInfo>
 #include <QProcess>
 
+#include "CWindowsFireWall.h"
+#include <process.h>
+
+
 launcher::launcher(QWidget *parent)
     : QWidget(parent)
     , ui(new Ui::launcher)
@@ -27,6 +31,9 @@ launcher::launcher(QWidget *parent)
 
     initParam();
 
+    CWindowsFireWall wfw(_getpid(), false);
+    wfw.removeLastRules();
+
     QDesktopWidget *dekwiget = QApplication::desktop();
     int nWidth = dekwiget->width();
     int nHeight = dekwiget->height();
@@ -62,6 +69,13 @@ launcher::launcher(QWidget *parent)
     setStyleSheet(qss);
 
     initUI();
+
+    QProcess process;
+    process.start("systeminfo");
+    process.waitForFinished();
+    QByteArray qbt = process.readAllStandardOutput();
+    QString sInfo = QString::fromLocal8Bit(qbt.data());
+    myServerLog()<<sInfo;
 }
 
 launcher::~launcher()
@@ -273,6 +287,7 @@ void launcher::onUpdateSucceed(bool bUpdateOeLauncher)
     }
 
     QProcess::startDetached(file.absoluteFilePath(), sParam);
+
     close();
 }
 

+ 6 - 0
launcher/launcher.pro

@@ -16,6 +16,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
 SOURCES += \
+    ../component/CWindowsFireWall.cpp \
     envCheck.cpp \
     envResult.cpp \
     envResultItem.cpp \
@@ -25,6 +26,7 @@ SOURCES += \
 
 
 HEADERS += \
+    ../component/CWindowsFireWall.h \
     envCheck.h \
     envResult.h \
     envResultItem.h \
@@ -50,6 +52,10 @@ RC_ICONS = images/coe.ico
 include(../common/common.pri)
 
 INCLUDEPATH += ../common/ \
+    ../component
+
+LIBS += \
+    -ladvapi32\
 
 # Default rules for deployment.
 qnx: target.path = /tmp/$${TARGET}/bin

+ 1 - 1
launcher/upgrade.cpp

@@ -223,7 +223,7 @@ void upgrade::onDownLoadFile(CDownLoadFileInfo downLoadFileInfo)
             else
             {
 
-                    if(m_curInfo.nType == 3)
+//                    if(m_curInfo.nType == 3)
                     {
                         QString sql = QString("update t_sysinfo set version_id='%1',version_code='%2'")
                                 .arg(g_appInfoPtr->m_nVersionId).arg(g_appInfoPtr->m_sVersionCode);

+ 1 - 0
question/questionOption.cpp

@@ -43,6 +43,7 @@ int questionOption::setUI(const int nWidth)
 
 
     m_nListHeight = 0;
+    ui->list_options->setFixedWidth(nWidth - ui->chkb_option->x() - ui->chkb_option->width());
     initOption();
     ui->list_options->setGeometry(ui->chkb_option->x() + ui->chkb_option->width(), g_appInfoPtr->m_fRate*0,
                                 nWidth - ui->chkb_option->x() - ui->chkb_option->width(),