Browse Source

Squashed commit of the following:

commit dd581014ef27dbe15f21335103a27eb1106b1aa5
Author: wangyaojie <wangyaojie@qmth.com.cn>
Date:   Tue Oct 8 11:29:58 2024 +0800

    bugfix

commit 735076a27e968d161e2f6f038f8e023582d3368e
Author: wangyaojie <wangyaojie@qmth.com.cn>
Date:   Tue Sep 3 18:42:09 2024 +0800

    1.1.2.2
wangyaojie 8 months ago
parent
commit
b2f216ccb8

+ 39 - 22
client/answerWidget.cpp

@@ -10,6 +10,7 @@
 #include "logproc.h"
 #include "inprogressFace.h"
 #include "popMsgBox.h"
+#include "CWebsocketProc.h"
 
 answerWidget::answerWidget(QWidget *parent) :
     QWidget(parent),
@@ -185,14 +186,21 @@ answerWidget::answerWidget(QWidget *parent) :
                         g_appInfoPtr->m_oExamInfo.nFaceLiveVerifyId = 0;
                         m_pFaceLiveness.reset();
 
-                        if(g_appInfoPtr->m_oExamInfo.nFaceVerifyTimes < 2)
+                        if(g_appInfoPtr->m_bInprogressFaceLivenessFailedForceExit)
                         {
-                            emit gobackLogin();
+                            if(g_appInfoPtr->m_oExamInfo.nFaceVerifyTimes < 2)
+                            {
+                                emit gobackLogin();
+                            }
+                            else
+                            {
+                                //交卷
+                                handinPaper(true);
+                            }
                         }
-                        else
+                        else if (g_appInfoPtr->m_oExamInfo.bFaceCheck)
                         {
-                            //交卷
-                            handinPaper(true);
+                            startCapture();
                         }
                     });
 
@@ -238,6 +246,11 @@ answerWidget::answerWidget(QWidget *parent) :
 
 answerWidget::~answerWidget()
 {
+    if (g_websocketPtr != nullptr)
+    {
+        g_websocketPtr->close();
+    }
+
     awMsgBox::clear(this);
 	if (g_inProcessFace)
 	{
@@ -351,23 +364,27 @@ void answerWidget::checkRemoteBreach()
 			bExit = true;
 		}
 
-		QStringList appList;
-		CCommonTools::getAllAppNameList(appList, m_sRemoteList, m_sRemoteTipList);
-		if (appList.count() > 0)
-		{
-			bExit = true;
-			for (int i = 0; i < appList.count(); i++)
-			{
-				if (sCheckStr.isEmpty())
-				{
-					sCheckStr = QString::fromLocal8Bit("请检测是否开启%1").arg(appList[i]);
-				}
-				else
-				{
-					sCheckStr += QString::fromLocal8Bit("、%1").arg(appList[i]);
-				}
-			}
-		}
+
+        if(g_appInfoPtr->m_bInprogressCheckRemoteAssistance)
+        {
+            QStringList appList;
+            CCommonTools::getAllAppNameList(appList, m_sRemoteList, m_sRemoteTipList);
+            if (appList.count() > 0)
+            {
+                bExit = true;
+                for (int i = 0; i < appList.count(); i++)
+                {
+                    if (sCheckStr.isEmpty())
+                    {
+                        sCheckStr = QString::fromLocal8Bit("请检测是否开启%1").arg(appList[i]);
+                    }
+                    else
+                    {
+                        sCheckStr += QString::fromLocal8Bit("、%1").arg(appList[i]);
+                    }
+                }    
+            }
+        }
 		QApplication::processEvents();
 
 		if (bExit)

+ 5 - 5
client/awMsgBox.cpp

@@ -95,8 +95,8 @@ void awMsgBox::initUI(MSG_ICON_TYPE type)
     QDesktopWidget *dekwiget = QApplication::desktop();
 
     setGeometry((dekwiget->width() - nCW - g_appInfoPtr->m_fRate*10)/2,
-                g_appInfoPtr->m_fRate*84 + vMsgList.size()*g_appInfoPtr->m_fRate * 90, 
-				nCW + g_appInfoPtr->m_fRate*10, g_appInfoPtr->m_fRate*90);
+                g_appInfoPtr->m_fRate*84 + vMsgList.size()*g_appInfoPtr->m_fRate * 90,
+                nCW + g_appInfoPtr->m_fRate*10, g_appInfoPtr->m_fRate*90);
     ui->widget_awmb_BG->setGeometry(5, 5 , nCW, g_appInfoPtr->m_fRate*80);
     ui->label_awmb_icon->setGeometry(g_appInfoPtr->m_fRate*40, g_appInfoPtr->m_fRate*26,
                                    g_appInfoPtr->m_fRate*28, g_appInfoPtr->m_fRate*28);
@@ -114,14 +114,14 @@ void awMsgBox::initUI(MSG_ICON_TYPE type)
 
 void ShowMsg(QString sMsg, QWidget *parent, MSG_ICON_TYPE type)
 {
-	std::shared_ptr<awMsgBox> msg = std::make_shared<awMsgBox>(parent);
+    std::shared_ptr<awMsgBox> msg = std::make_shared<awMsgBox>(parent);
 
 
     msg->setMsg(sMsg);
     msg->initUI(type);
     msg->show();
-	std::scoped_lock lock(awMsgBox::msgMutex);
-	awMsgBox::vMsgList.push_back(msg);
+    std::scoped_lock lock(awMsgBox::msgMutex);
+    awMsgBox::vMsgList.push_back(msg);
 }
 
 void awMsgBox::setMsg(QString sMsg)

+ 0 - 2
client/client.qss

@@ -86,7 +86,6 @@ QLineEdit#edt_account
     font-weight:400;
     color:rgba(153,153,153,1);
     padding-left:RATE_BASE_SIZE39px;
-    border-image:url(:/images/edt-account.png);
 }
 
 QLineEdit#edt_password
@@ -99,7 +98,6 @@ QLineEdit#edt_password
     font-weight:400;
     color:rgba(153,153,153,1);
     padding-left:RATE_BASE_SIZE39px;
-    border-image:url(:/images/edt-password.png);
 }
 
 QPushButton#btn_login

+ 53 - 12
client/courseList.cpp

@@ -49,7 +49,8 @@ courseList::courseList(QWidget *parent) :
     connect(g_httpBllPtr.get(), &CHttpBll::sgnEndExam, this, &courseList::onEndExam);
     qRegisterMetaType<CGetOrgPropertiesByGroupWithoutCache>("CGetOrgPropertiesByGroupWithoutCache");
     connect(g_httpBllPtr.get(), &CHttpBll::sgnGetOrgPropertiesByGroupWithoutCache, this, &courseList::onGetOrgPropertiesByGroupWithoutCache);
-
+    qRegisterMetaType<CSkipFaceCheckParam>("CSkipFaceCheckParam");
+    connect(g_httpBllPtr.get(), &CHttpBll::sgnSkipFaceCheckParam, this, &courseList::onSkipFaceCheckParam);
 
 	sqlite3_stmt *stmt;
 	QString sSql = QString("select agreement from t_agreement where student_id=%1")
@@ -316,7 +317,8 @@ void courseList::on_btn_cl_close_clicked()
 {
 //    logout();
 //    close();
-    QCoreApplication::quit();
+//    QCoreApplication::quit();
+    qApp->exit();
 }
 
 void courseList::setCheck(COURSE_MENU_BTN_TYPE cmbt)
@@ -544,7 +546,7 @@ void courseList::onGetExamProperty(CGetExamProperty getExamProperty)
 {
     if (getExamProperty.nCode == 200)
 	{
-        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")
+        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,FACE_VERIFY_FORCE_EXIT")
 		{
             g_appInfoPtr->m_oExamInfo.bIsFaceCheck = getExamProperty.bIsFaceCheck;
 //            g_appInfoPtr->m_oExamInfo.nFaceThreshold = getExamProperty.nFaceThreshold;
@@ -553,6 +555,7 @@ void courseList::onGetExamProperty(CGetExamProperty getExamProperty)
             g_appInfoPtr->m_oExamInfo.nFaceVerifyEndMinute = getExamProperty.nFaceVerifyEndMinute;
             g_appInfoPtr->m_oExamInfo.bIsStrangerEnable = getExamProperty.bIsStrangerEnable;
             g_appInfoPtr->m_oExamInfo.bIsLivenessBefore = getExamProperty.bIsLivenessBefore;
+            g_appInfoPtr->m_bInprogressFaceLivenessFailedForceExit = getExamProperty.bFaceVerifyForceExit;
 
             if (getExamProperty.bCheckEnvironment && !g_appInfoPtr->m_oExamInfo.bIsExamInProgress)
 			{
@@ -768,14 +771,12 @@ void courseList::onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupW
         g_appInfoPtr->m_oExamInfo.nFaceThreshold =  orgProperties.nFaceThreshold;
 
         if(!g_appInfoPtr->m_oExamInfo.bIsExamInProgress)
-        {
-            if(g_appInfoPtr->m_oExamInfo.bIsLivenessBefore && g_appInfoPtr->m_oExamInfo.bIsFaceCheck)
-            {
-                doLiveness();
-            }
-            else if(g_appInfoPtr->m_oExamInfo.bFaceCheck)
+        {            
+            if((g_appInfoPtr->m_oExamInfo.bIsLivenessBefore && g_appInfoPtr->m_oExamInfo.bIsFaceCheck) ||
+                    g_appInfoPtr->m_oExamInfo.bFaceCheck)
             {
-                doFaceCompare();
+                //获取是否跳过人脸识别参数
+                getSkipFaceCheckParam();
             }
             else
             {
@@ -800,6 +801,46 @@ void courseList::onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupW
     }
 }
 
+void courseList::onSkipFaceCheckParam(CSkipFaceCheckParam skipFaceCheckParam)
+{
+    if(skipFaceCheckParam.nCode == 200)
+    {
+        g_appInfoPtr->m_bSkipFaceCheck = skipFaceCheckParam.bSkipFaceCheck;
+        if(g_appInfoPtr->m_oExamInfo.bIsLivenessBefore && g_appInfoPtr->m_oExamInfo.bIsFaceCheck && !g_appInfoPtr->m_bSkipFaceCheck)
+        {
+            doLiveness();
+        }
+        else
+        {
+            doFaceCompare();
+        }
+
+    }
+    else
+    {
+        if(skipFaceCheckParam.sMessage.isEmpty())
+        {
+            ShowMsg(QString::fromLocal8Bit("获取人脸参数失败"), this, MSG_ICON_TYPE::mit_error);
+        }
+        else
+        {
+            ShowMsg(skipFaceCheckParam.sMessage, this, MSG_ICON_TYPE::mit_error);
+        }
+    }
+}
+
+void courseList::getSkipFaceCheckParam()
+{
+    CHttpRequestPackage hrp;
+    hrp.sUri = QString("/api/ecs_exam_work/exam/skip/face/check") ;
+    hrp.sParamList.push_back(QString("examId,%1").arg(g_appInfoPtr->m_oExamInfo.nExamId));
+    hrp.sParamList.push_back(QString("examStudentId,%1").arg(g_appInfoPtr->m_oExamInfo.nExamStudentId));
+    hrp.nRequestType = RequestType::rtSkipFaceCheckParam;
+    hrp.eParamType = HttpParamType::hptUrl;
+    g_httpBllPtr->post(hrp);
+}
+
+
 void courseList::enterWaitExam()
 {
 	//进入待考
@@ -1229,9 +1270,9 @@ void courseList::getExamProperty()
 {
     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,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,FACE_VERIFY_FORCE_EXIT");
     hrp.nRequestType = RequestType::rtGetExamProperty;
-    hrp.sCommonStr = "CHECK_ENVIRONMENT,IS_FACE_CHECK,SNAPSHOT_INTERVAL,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,FACE_VERIFY_FORCE_EXIT";
     g_httpBllPtr->get(hrp);
 }
 

+ 2 - 1
client/courseList.h

@@ -82,7 +82,7 @@ private slots:
     void onGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWithoutCache orgProperties);
 
     void onEndExam(CEndExam endExam);
-
+    void onSkipFaceCheckParam(CSkipFaceCheckParam skipFaceCheckParam);
 private:
     void initUI();
     void setCheck(COURSE_MENU_BTN_TYPE cmbt);
@@ -95,6 +95,7 @@ private:
     void doFaceCompare();
     void doLiveness();
     void getExamProperty();
+    void getSkipFaceCheckParam();
 
     Ui::courseList *ui;
 

BIN
client/images/edt-account.png


BIN
client/images/edt-password.png


BIN
client/images/icon-hide-password.png


BIN
client/images/icon-show-password.png


+ 83 - 9
client/login.cpp

@@ -16,6 +16,8 @@
 #include "CKeyBoardHook.h"
 #include "CWindowsFireWall.h"
 #include <process.h>
+#include <QLayout>
+#include <QAction>
 
 login::login(QWidget *parent)
     : QWidget(parent)
@@ -131,11 +133,7 @@ login::login(QWidget *parent)
 
 login::~login()
 {
-    if(g_logPtr)
-    {
-        g_logPtr.reset();
-    }
-
+    hide();
     HWND task = nullptr;
     task=FindWindow(L"Shell_TrayWnd",nullptr);
     if(task)
@@ -144,6 +142,20 @@ login::~login()
     }
 
     awMsgBox::clear();
+
+    if(g_windowsFireWallPtr)
+    {
+        g_windowsFireWallPtr.reset();
+    }
+
+
+    if(g_logPtr)
+    {
+        g_logPtr.reset();
+    }
+
+
+
     delete ui;
 }
 
@@ -355,10 +367,52 @@ void login::initUI()
     ui->edt_account->setGeometry((ui->widget_loginInfo->width() - g_appInfoPtr->m_fRate*280)/2,
                                  g_appInfoPtr->m_fRate*70,
                                  g_appInfoPtr->m_fRate*280, g_appInfoPtr->m_fRate*50);
+    QPushButton *btn_IconAccount = new QPushButton;
+    btn_IconAccount->setCursor(Qt::ArrowCursor);
+    int nBtnWidth = g_appInfoPtr->m_fRate*16;
+    btn_IconAccount->setFixedSize(nBtnWidth, nBtnWidth);
+    btn_IconAccount->setStyleSheet("border-image:url(:/images/edt-account.png);");
+    QHBoxLayout *layout = new QHBoxLayout(ui->edt_account);
+    layout->setContentsMargins(g_appInfoPtr->m_fRate*13, 0, g_appInfoPtr->m_fRate*13, 0);
+    layout->addWidget(btn_IconAccount);
+    layout->addSpacerItem(new QSpacerItem(40, 20, QSizePolicy::Expanding));
+
+    ui->edt_account->setLayout(layout);
+
 
 
     ui->edt_password->setGeometry(ui->edt_account->x(), ui->edt_account->y() + ui->edt_account->height() + g_appInfoPtr->m_fRate*20,
                                   ui->edt_account->width(), ui->edt_account->height());
+
+    QPushButton *btn_showPassword = new QPushButton;
+    btn_showPassword->setCursor(Qt::ArrowCursor);
+    nBtnWidth = g_appInfoPtr->m_fRate*14;
+    btn_showPassword->setFixedSize(nBtnWidth, nBtnWidth);
+    btn_showPassword->setStyleSheet("border-image:url(:/images/icon-show-password.png);");
+
+    connect(btn_showPassword, &QPushButton::clicked, this, [&](){
+        ui->edt_password->setEchoMode(ui->edt_password->echoMode() == QLineEdit::Password ? QLineEdit::Normal : QLineEdit::Password);
+        QPushButton *btn = (QPushButton*)(sender());
+        if(btn)
+        {
+            btn->setStyleSheet(ui->edt_password->echoMode() == QLineEdit::Password ? "border-image:url(:/images/icon-show-password.png);" : "border-image:url(:/images/icon-hide-password.png);");
+        }
+    });
+
+    QPushButton *btn_IconPassword = new QPushButton;
+    btn_IconPassword->setCursor(Qt::ArrowCursor);
+    btn_IconPassword->setFixedSize(nBtnWidth, nBtnWidth);
+    btn_IconPassword->setStyleSheet("border-image:url(:/images/edt-password.png);");
+    layout = new QHBoxLayout(ui->edt_password);
+    layout->setContentsMargins(g_appInfoPtr->m_fRate*15, 0, g_appInfoPtr->m_fRate*15, 0);
+    layout->addWidget(btn_IconPassword);
+    layout->addSpacerItem(new QSpacerItem(40, 20, QSizePolicy::Expanding));
+    layout->addWidget(btn_showPassword);
+
+    ui->edt_password->setLayout(layout);
+
+
+
     ui->btn_login->setGeometry(ui->edt_account->x(), ui->edt_password->y() + ui->edt_password->height() + g_appInfoPtr->m_fRate*40,
                                ui->edt_account->width(), g_appInfoPtr->m_fRate*56);
     ui->label_login_version->adjustSize();
@@ -466,7 +520,14 @@ void login::setBtnStyle()
 
 void login::on_btn_close_clicked()
 {
-    close();
+    /*HWND task = nullptr;
+    task=FindWindow(L"Shell_TrayWnd",nullptr);
+    if(task)
+    {
+        ShowWindow(task,SW_SHOW);//隐藏任务栏
+    }
+    hide()*/;
+    qApp->exit();
 }
 
 void login::onStudentClientConfig(CStudentClientConfig studentClientConfig)
@@ -506,6 +567,7 @@ void login::onStudentClientConfig(CStudentClientConfig studentClientConfig)
         g_appInfoPtr->m_bShowStudentName = studentClientConfig.bShowStudentName;
         g_appInfoPtr->m_bShowStudentCode = studentClientConfig.bShowStudentCode;
         g_appInfoPtr->m_bShowStudentIdentity = studentClientConfig.bShowStudentIdentity;
+        g_appInfoPtr->m_bInprogressCheckRemoteAssistance = studentClientConfig.bExamingBlackListCheck;
 
         if(studentClientConfig.bIsCustomMenuLogo)
         {
@@ -544,7 +606,7 @@ void login::onStudentClientConfig(CStudentClientConfig studentClientConfig)
 		}
 		
 #ifdef _DEBUG
-        g_appInfoPtr->m_bFullScreenTop = false;
+        g_appInfoPtr->m_bFullScreenTop = false; 
 #endif // _DEBUG
 
         if(g_appInfoPtr->m_bFullScreenTop)
@@ -561,7 +623,10 @@ void login::onStudentClientConfig(CStudentClientConfig studentClientConfig)
                 ShowWindow(task,SW_HIDE);//隐藏任务栏
             }
 
-            g_windowsFireWallPtr = std::make_shared<CWindowsFireWall>(_getpid());
+            if(g_windowsFireWallPtr == nullptr)
+            {
+                g_windowsFireWallPtr = std::make_shared<CWindowsFireWall>(_getpid());
+            }
         }
   
         
@@ -574,7 +639,16 @@ void login::onStudentClientConfig(CStudentClientConfig studentClientConfig)
 		{
 			m_pLoading.reset();
 		}
-        QTimer::singleShot(3000, this, [&](){close();});
+        QTimer::singleShot(3000, this, [&](){
+//            HWND task = nullptr;
+//            task=FindWindow(L"Shell_TrayWnd",nullptr);
+//            if(task)
+//            {
+//                ShowWindow(task,SW_SHOW);//隐藏任务栏
+//            }
+//            hide();
+            qApp->exit();
+        });
 	}
 }
 

+ 3 - 0
client/rc.qrc

@@ -70,5 +70,8 @@
         <file>images/icon-aw-minisize.png</file>
         <file>images/btn-etvt-mute.png</file>
         <file>images/img-face-mask.png</file>
+        <file>images/icon-show-password.png</file>
+        <file>images/coe.ico</file>
+        <file>images/icon-hide-password.png</file>
     </qresource>
 </RCC>

+ 4 - 0
common/CAppInfo.cpp

@@ -16,6 +16,7 @@ CAppInfo::CAppInfo()
 	m_sOrgPrefix = "";
 	m_bDisableMutiScreen = false;
 	m_bDisableRemoteAssistance = false;
+    m_bInprogressCheckRemoteAssistance = true;
 	m_bFullScreenTop = false;
 	m_bDisableVirtualCamera = false;
 	m_sRootOrgId = "";
@@ -49,8 +50,11 @@ CAppInfo::CAppInfo()
     m_sUpgradeUrl = "";
 	m_sCacheFileDir = "temp/";
     m_bShowDebugInfo = false;
+    m_bSkipFaceCheck = false;
 
     m_pAnsBgWidget = nullptr;
+
+    m_bInprogressFaceLivenessFailedForceExit = true;
 }
 
 __int64 CAppInfo::serverMTime()

+ 6 - 0
common/CAppInfo.h

@@ -91,6 +91,7 @@ public:
 
 	bool m_bDisableMutiScreen;//禁止全屏
 	bool m_bDisableRemoteAssistance;//远程协助
+    bool m_bInprogressCheckRemoteAssistance;//过程中检测远程协助
 	bool m_bFullScreenTop;//屏幕前置
 	bool m_bDisableVirtualCamera;//虚拟摄像头
 	QString m_sRootOrgId;
@@ -121,6 +122,11 @@ public:
 
     ExamInfo m_oExamInfo;
     QWidget* m_pAnsBgWidget;
+    //过程中活体检测失败是否退出考试
+    bool m_bInprogressFaceLivenessFailedForceExit;
+
+    //检查当前考生是否跳过人脸识别接口
+    bool m_bSkipFaceCheck;
 
 	int m_nVersionId;
 	QString m_sVersionCode;

+ 92 - 56
common/CHttpBll.cpp

@@ -1139,7 +1139,7 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
         }
         break;
 
-    case RequestType::rtExamControlCheckTime:
+        case RequestType::rtExamControlCheckTime:
         {
             CBaseResponsePackage res;
             res.nCode = nCode;
@@ -1150,6 +1150,23 @@ void CHttpBll::requestProc(CHttpRequestPackage requestPkg)
             emit sgnExamControlCheckTime(res);
         }
         break;
+
+        case RequestType::rtSkipFaceCheckParam:
+        {
+            CSkipFaceCheckParam res;
+            res.nCode = nCode;
+            if (sErrorMsg != "" || nCode != 200)
+            {
+                res.sMessage = sErrorMsg;
+            }
+            else
+            {
+                genSkipFaceCheckParam(&res, sResponse);
+            }
+            emit sgnSkipFaceCheckParam(res);
+        }
+        break;
+
         default:
         break;
     }
@@ -1163,7 +1180,7 @@ void CHttpBll::genUpgrade(CUpgrade *pUpgrade, const std::string &sResponse)
         Json::Value jsonRoot = Json::Value::null;
         if(!reader.parse(sResponse, jsonRoot))
         {
-            pUpgrade->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pUpgrade->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pUpgrade->sMessage << sResponse.c_str();
         }
 
@@ -1194,7 +1211,7 @@ void CHttpBll::genAgreement(CAgreement *pAgreement, const std::string &sResponse
         Json::Value jsonRoot = Json::Value::null;
         if(!reader.parse(sRes, jsonRoot))
         {
-            pAgreement->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pAgreement->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pAgreement->sMessage << sResponse.c_str();
         }
 
@@ -1216,7 +1233,7 @@ void CHttpBll::genStudentClientConfig(CStudentClientConfig *pStudentClientConfig
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pStudentClientConfig->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pStudentClientConfig->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pStudentClientConfig->sMessage << sResponse.c_str();
         }
 
@@ -1264,6 +1281,10 @@ void CHttpBll::genStudentClientConfig(CStudentClientConfig *pStudentClientConfig
             {
                 pStudentClientConfig->bDisableVirtualMachine = true;
             }
+            else if(sType == "EXAMING_BLACK_LIST_CHECK")
+            {
+                pStudentClientConfig->bExamingBlackListCheck = true;
+            }
         }
 
         pStudentClientConfig->sRootOrgId = jsonRoot["ROOT_ORG_ID"].asString().c_str();// " : "0",
@@ -1294,7 +1315,7 @@ void CHttpBll::genSysNotice(CSysNotice *pSysNotice, const std::string &sResponse
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pSysNotice->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pSysNotice->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pSysNotice->sMessage << sResponse.c_str();
         }
 
@@ -1328,7 +1349,7 @@ void CHttpBll::genLoginLimit(CLoginLimit *pLoginLimit, const std::string &sRespo
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pLoginLimit->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pLoginLimit->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pLoginLimit->sMessage << sResponse.c_str();
         }
         pLoginLimit->nCount = jsonRoot["count"].asInt64();
@@ -1348,7 +1369,7 @@ void CHttpBll::genLoginInfo(CLoginInfo *pLoginInfo, const std::string &sResponse
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pLoginInfo->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pLoginInfo->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pLoginInfo->sMessage << sResponse.c_str();
         }
     //	pLoginInfo->nCode = jsonRoot["code"].asInt();
@@ -1392,7 +1413,7 @@ void CHttpBll::genGetStudentClientMenu(CGetStudentClientMenu *pGetStudentClientM
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetStudentClientMenu->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetStudentClientMenu->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetStudentClientMenu->sMessage << sResponse.c_str();
         }
 
@@ -1421,7 +1442,7 @@ void CHttpBll::genGetStudentInfoBySession(CGetStudentInfoBySession *pGetStudentI
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetStudentInfoBySession->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetStudentInfoBySession->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetStudentInfoBySession->sMessage << sResponse.c_str();
         }
         pGetStudentInfoBySession->nId = jsonRoot["id"].asInt64();
@@ -1462,7 +1483,7 @@ void CHttpBll::genSpecialtyNameList(CSpecialtyNameList *pSpecialtyNameList, cons
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pSpecialtyNameList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pSpecialtyNameList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pSpecialtyNameList->sMessage << sResponse.c_str();
         }
         QString sSpecialtyName = "";
@@ -1495,7 +1516,7 @@ void CHttpBll::genGetUserNoticeList(CGetUserNoticeList *pGetUserNoticeList, cons
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetUserNoticeList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetUserNoticeList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetUserNoticeList->sMessage << sResponse.c_str();
         }
 
@@ -1545,7 +1566,7 @@ void CHttpBll::genQueryBatchList(CQueryBatchList *pQueryBatchList, const std::st
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryBatchList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryBatchList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryBatchList->sMessage << sResponse.c_str();
         }
         int nSize = jsonRoot.size();
@@ -1573,16 +1594,16 @@ void CHttpBll::genGetExamProperty(CGetExamProperty *pGetExamProperty, const std:
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetExamProperty->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetExamProperty->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetExamProperty->sMessage << sResponse.c_str();
         }
 
-        if (jsonRoot.isMember("BEFORE_EXAM_REMARK"))
+        if (jsonRoot.isMember("BEFORE_EXAM_REMARK") && jsonRoot["BEFORE_EXAM_REMARK"] != Json::Value::null)
         {
             pGetExamProperty->sBeforeExamRemark = jsonRoot["BEFORE_EXAM_REMARK"].asString().c_str();
         }
 
-        if (jsonRoot.isMember("CHECK_ENVIRONMENT"))
+        if (jsonRoot.isMember("CHECK_ENVIRONMENT") && jsonRoot["CHECK_ENVIRONMENT"] != Json::Value::null)
         {
             pGetExamProperty->bCheckEnvironment = QVariant(jsonRoot["CHECK_ENVIRONMENT"].asString().c_str()).toBool();
         }
@@ -1592,62 +1613,62 @@ void CHttpBll::genGetExamProperty(CGetExamProperty *pGetExamProperty, const std:
 //            pGetExamProperty->nFaceThreshold = QVariant(jsonRoot["PC_CLIENT_FACE_THRESHOLD"].asString().c_str()).toInt();
 //        }
 
-        if (jsonRoot.isMember("IS_FACE_CHECK"))
+        if (jsonRoot.isMember("IS_FACE_CHECK") && jsonRoot["IS_FACE_CHECK"]  != Json::Value::null)
         {
             pGetExamProperty->bIsFaceCheck = QVariant(jsonRoot["IS_FACE_CHECK"].asString().c_str()).toBool();
         }
 
-        if (jsonRoot.isMember("SNAPSHOT_INTERVAL"))
+        if (jsonRoot.isMember("SNAPSHOT_INTERVAL") && jsonRoot["SNAPSHOT_INTERVAL"]  != Json::Value::null)
         {
             pGetExamProperty->nSnapshotInterval = QVariant(jsonRoot["SNAPSHOT_INTERVAL"].asString().c_str()).toInt();
         }
 
-        if (jsonRoot.isMember("FACE_VERIFY_START_MINUTE"))
+        if (jsonRoot.isMember("FACE_VERIFY_START_MINUTE") && jsonRoot["FACE_VERIFY_START_MINUTE"] != Json::Value::null)
         {
             pGetExamProperty->nFaceVerifyStartMinute = QVariant(jsonRoot["FACE_VERIFY_START_MINUTE"].asString().c_str()).toInt();
         }
 
-        if (jsonRoot.isMember("FACE_VERIFY_END_MINUTE"))
+        if (jsonRoot.isMember("FACE_VERIFY_END_MINUTE") && jsonRoot["FACE_VERIFY_END_MINUTE"] != Json::Value::null)
         {
             pGetExamProperty->nFaceVerifyEndMinute = QVariant(jsonRoot["FACE_VERIFY_END_MINUTE"].asString().c_str()).toInt();
         }
 
-        if (jsonRoot.isMember("IS_STRANGER_ENABLE"))
+        if (jsonRoot.isMember("IS_STRANGER_ENABLE") && jsonRoot["IS_STRANGER_ENABLE"]  != Json::Value::null)
         {
             pGetExamProperty->bIsStrangerEnable = QVariant(jsonRoot["IS_STRANGER_ENABLE"].asString().c_str()).toBool();
         }
 
-        if (jsonRoot.isMember("PRACTICE_TYPE"))
+        if (jsonRoot.isMember("PRACTICE_TYPE") && jsonRoot["PRACTICE_TYPE"] != Json::Value::null)
         {
             pGetExamProperty->sPracticeType = jsonRoot["PRACTICE_TYPE"].asString().c_str();
         }
 
-        if (jsonRoot.isMember("FREEZE_TIME"))
+        if (jsonRoot.isMember("FREEZE_TIME") && jsonRoot["FREEZE_TIME"] != Json::Value::null)
         {
             pGetExamProperty->nFreezeTime = QVariant(jsonRoot["FREEZE_TIME"].asString().c_str()).toInt();
         }
 
-        if (jsonRoot.isMember("AFTER_EXAM_REMARK"))
+        if (jsonRoot.isMember("AFTER_EXAM_REMARK") && jsonRoot["AFTER_EXAM_REMARK"] != Json::Value::null)
         {
             pGetExamProperty->sAfterExamRemark = jsonRoot["AFTER_EXAM_REMARK"].asString().c_str();
         }
 
-        if (jsonRoot.isMember("IS_OBJ_SCORE_VIEW"))
+        if (jsonRoot.isMember("IS_OBJ_SCORE_VIEW") && jsonRoot["IS_OBJ_SCORE_VIEW"] != Json::Value::null)
         {
             pGetExamProperty->bIsObjScoreView = QVariant(jsonRoot["IS_OBJ_SCORE_VIEW"].asString().c_str()).toBool();
         }
 
-        if (jsonRoot.isMember("SHOW_CHEATING_REMARK"))
+        if (jsonRoot.isMember("SHOW_CHEATING_REMARK") && jsonRoot["SHOW_CHEATING_REMARK"] != Json::Value::null)
         {
             pGetExamProperty->bShowCheatingRemark = QVariant(jsonRoot["SHOW_CHEATING_REMARK"].asString().c_str()).toBool();
         }
 
-        if (jsonRoot.isMember("CHEATING_REMARK"))
+        if (jsonRoot.isMember("CHEATING_REMARK") && jsonRoot["CHEATING_REMARK"] != Json::Value::null)
         {
             pGetExamProperty->sCheatingRemark = jsonRoot["CHEATING_REMARK"].asString().c_str();
         }
 
-        if (jsonRoot.isMember("IS_FACE_VERIFY_BEFORE"))
+        if (jsonRoot.isMember("IS_FACE_VERIFY_BEFORE") && jsonRoot["IS_FACE_VERIFY_BEFORE"] != Json::Value::null)
         {
             pGetExamProperty->bIsLivenessBefore = QVariant(jsonRoot["IS_FACE_VERIFY_BEFORE"].asString().c_str()).toBool();
         }
@@ -1669,9 +1690,12 @@ void CHttpBll::genGetExamProperty(CGetExamProperty *pGetExamProperty, const std:
             }
         }
 
+        if(jsonRoot.isMember("FACE_VERIFY_FORCE_EXIT") && jsonRoot["FACE_VERIFY_FORCE_EXIT"] != Json::Value::null)
+        {
+            pGetExamProperty->bFaceVerifyForceExit = QVariant(jsonRoot["FACE_VERIFY_FORCE_EXIT"].asString().c_str()).toBool();
+        }
 
-
-        if(jsonRoot.isMember("SHOW_MULTIPLE_CHOICE_WARNING"))
+        if(jsonRoot.isMember("SHOW_MULTIPLE_CHOICE_WARNING") && jsonRoot["SHOW_MULTIPLE_CHOICE_WARNING"] != Json::Value::null)
         {
             pGetExamProperty->bMutipleAnserCountTips = QVariant(jsonRoot["SHOW_MULTIPLE_CHOICE_WARNING"].asString().c_str()).toBool();
         }
@@ -1690,7 +1714,7 @@ void CHttpBll::genStartExamLimit(CStartExamLimit *pStartExamLimit, const std::st
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pStartExamLimit->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pStartExamLimit->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pStartExamLimit->sMessage << sResponse.c_str();
         }
 
@@ -1711,7 +1735,7 @@ void CHttpBll::genIpLimit(CIpLimit *pIpLimit, const std::string &sResponse)
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pIpLimit->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pIpLimit->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pIpLimit->sMessage << sResponse.c_str();
         }
 
@@ -1731,7 +1755,7 @@ void CHttpBll::genStartExam(CStartExam *pStartExam, const std::string &sResponse
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pStartExam->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pStartExam->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pStartExam->sMessage << sResponse.c_str();
         }
         pStartExam->sCourseCode = jsonRoot["courseCode"].asString().c_str();
@@ -1791,7 +1815,7 @@ void CHttpBll::genGetExamById(CGetExamById *pGetExamById, const std::string &sRe
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetExamById->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetExamById->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetExamById->sMessage << sResponse.c_str();
         }
 
@@ -1821,7 +1845,7 @@ void CHttpBll::genStartAnswer(CStartAnswer *pStartAnswer, const std::string &sRe
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pStartAnswer->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pStartAnswer->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pStartAnswer->sMessage << sResponse.c_str();
         }
         pStartAnswer->nDuration = jsonRoot["duration"].asInt64();
@@ -1842,7 +1866,7 @@ void CHttpBll::genGetQuestion(CGetQuestion *pGetQuestion, const std::string &sRe
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetQuestion->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetQuestion->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetQuestion->sMessage << sResponse.c_str();
         }
         pGetQuestion->sId = jsonRoot["id"].asString().c_str();
@@ -1888,7 +1912,7 @@ void CHttpBll::genGetQuestionContent(CGetQuestionContent *pGetQuestionContent, c
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetQuestionContent->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetQuestionContent->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetQuestionContent->sMessage << sResponse.c_str();
         }
 
@@ -1999,7 +2023,7 @@ void CHttpBll::genQueryExamList(CQueryExamList *pQueryExamList, const std::strin
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryExamList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryExamList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryExamList->sMessage << sResponse.c_str();
         }
 
@@ -2026,7 +2050,7 @@ void CHttpBll::genQueryExamEndList(CQueryExamEndList *pQueryExamEndList, const s
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryExamEndList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryExamEndList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryExamEndList->sMessage << sResponse.c_str();
         }
 
@@ -2053,7 +2077,7 @@ void CHttpBll::genQueryObjectiveScoreList(CQueryObjectiveScoreList *pQueryObject
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryObjectiveScoreList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryObjectiveScoreList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryObjectiveScoreList->sMessage << sResponse.c_str();
         }
         int nScoreSize = jsonRoot.size();
@@ -2086,7 +2110,7 @@ void CHttpBll::genQueryHomeworkList(CQueryHomeworkList *pQueryHomeworkList, cons
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryHomeworkList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryHomeworkList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryHomeworkList->sMessage << sResponse.c_str();
         }
 
@@ -2113,7 +2137,7 @@ void CHttpBll::genQueryPracticeCourseList(CQueryPracticeCourseList *pQueryPracti
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryPracticeCourseList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryPracticeCourseList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryPracticeCourseList->sMessage << sResponse.c_str();
         }
 
@@ -2176,7 +2200,7 @@ void CHttpBll::genQueryPracticeRecordList(CQueryPracticeRecordList *pQueryPracti
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pQueryPracticeRecordList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pQueryPracticeRecordList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pQueryPracticeRecordList->sMessage << sResponse.c_str();
         }
         int nSize = jsonRoot.size();
@@ -2214,7 +2238,7 @@ void CHttpBll::genGetPracticeDetailInfo(CGetPracticeDetailInfo *pGetPracticeDeta
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetPracticeDetailInfo->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetPracticeDetailInfo->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetPracticeDetailInfo->sMessage << sResponse.c_str();
         }
         pGetPracticeDetailInfo->sCourseCode  = jsonRoot["courseCode"].asString().c_str();
@@ -2253,7 +2277,7 @@ void CHttpBll::genFindExamRecordDataEntity(CFindExamRecordDataEntity *pFindExamR
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pFindExamRecordDataEntity->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pFindExamRecordDataEntity->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pFindExamRecordDataEntity->sMessage << sResponse.c_str();
         }
 
@@ -2274,7 +2298,7 @@ void CHttpBll::genGetExamRecordQuestions(CGetExamRecordQuestions *pGetExamRecord
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetExamRecordQuestions->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetExamRecordQuestions->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetExamRecordQuestions->sMessage << sResponse.c_str();
         }
         int nSize = jsonRoot["examQuestionEntities"].size();
@@ -2319,7 +2343,7 @@ void CHttpBll::genGetOfflineCourse(CGetOfflineCourse *pGetOfflineCourse, const s
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetOfflineCourse->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetOfflineCourse->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetOfflineCourse->sMessage << sResponse.c_str();
         }
         int nSize = jsonRoot.size();
@@ -2390,7 +2414,7 @@ void CHttpBll::genCheckExamInProgress(CCheckExamInProgress *pCheckExamInProgress
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pCheckExamInProgress->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pCheckExamInProgress->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pCheckExamInProgress->sMessage << sResponse.c_str();
         }
         if (jsonRoot["data"].isNull())
@@ -2424,7 +2448,7 @@ void CHttpBll::genGetCourseInfo(CGetCourseInfo *pGetCourseInfo, const std::strin
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetCourseInfo->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetCourseInfo->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetCourseInfo->sMessage << sResponse.c_str();
         }
         pGetCourseInfo->sCourseName = jsonRoot["courseName"].asString().c_str();
@@ -2449,7 +2473,7 @@ void CHttpBll::genFindExamQuestionList(CFindExamQuestionList *pFindExamQuestionL
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pFindExamQuestionList->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pFindExamQuestionList->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pFindExamQuestionList->sMessage << sResponse.c_str();
         }
 
@@ -2495,7 +2519,7 @@ void CHttpBll::genGetExamRecordPaperStruct(CGetExamRecordPaperStruct *pGetExamRe
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetExamRecordPaperStruct->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetExamRecordPaperStruct->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetExamRecordPaperStruct->sMessage << sResponse.c_str();
         }
 
@@ -2572,7 +2596,7 @@ void CHttpBll::genGetEndExamInfo(CGetEndExamInfo *pGetEndExamInfo, const std::st
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pGetEndExamInfo->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pGetEndExamInfo->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pGetEndExamInfo->sMessage << sResponse.c_str();
         }
 
@@ -2601,7 +2625,7 @@ void CHttpBll::genGetWXQrCode(CGetWXQrCode *pGetWXQrCode, const std::string &sRe
 //        Json::Value jsonRoot = Json::Value::null;
 //        if (!reader.parse(sResponse, jsonRoot))
 //        {
-//            pProcessUpload->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+//            pProcessUpload->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
 //            myDebug() << pProcessUpload->sMessage << sResponse.c_str();
 //        }
 //        pProcessUpload->sFileUrl = jsonRoot["fileUrl"].asString().c_str();
@@ -2620,7 +2644,7 @@ void CHttpBll::genGetOrgPropertiesByGroupWithoutCache(CGetOrgPropertiesByGroupWi
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pOrgProperties->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pOrgProperties->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pOrgProperties->sMessage << sResponse.c_str();
         }
         pOrgProperties->nActionNum = QVariant(jsonRoot["ACTION_NUM"].asString().c_str()).toInt();
@@ -2629,7 +2653,7 @@ 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"))
+        if(jsonRoot.isMember("PC_CLIENT_FACE_THRESHOLD") && jsonRoot["PC_CLIENT_FACE_THRESHOLD"] != Json::Value::null)
         {
             pOrgProperties->nFaceThreshold = QVariant(jsonRoot["PC_CLIENT_FACE_THRESHOLD"].asString().c_str()).toInt();
         }
@@ -2649,7 +2673,7 @@ void CHttpBll::genStartFaceLiveVerify(CStartFaceLiveVerify *pStartFaceLiveVerify
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pStartFaceLiveVerify->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pStartFaceLiveVerify->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pStartFaceLiveVerify->sMessage << sResponse.c_str();
         }
 
@@ -2671,7 +2695,7 @@ void CHttpBll::genClientExamProcessUploadSign(CClientExamProcessUploadSign *pCli
         Json::Value jsonRoot = Json::Value::null;
         if (!reader.parse(sResponse, jsonRoot))
         {
-            pClientExamProcessUploadSign->sMessage = QString::fromLocal8Bit("解析后台返回环境信息json异常!");
+            pClientExamProcessUploadSign->sMessage = QString::fromLocal8Bit("数据请求失败,请检查网络是否正常!");
             myDebug() << pClientExamProcessUploadSign->sMessage << sResponse.c_str();
         }
 
@@ -2689,3 +2713,15 @@ void CHttpBll::genClientExamProcessUploadSign(CClientExamProcessUploadSign *pCli
         myServerLog()<<sResponse.c_str()<<",exception error"<<e.what();
     }
 }
+
+void CHttpBll::genSkipFaceCheckParam(CSkipFaceCheckParam *pSkipFaceCheckParam, const std::string &sResponse)
+{
+    try
+    {
+        pSkipFaceCheckParam->bSkipFaceCheck = QVariant(sResponse.c_str()).toBool();
+    }
+    catch (const std::exception &e)
+    {
+        myServerLog()<<sResponse.c_str()<<",exception error"<<e.what();
+    }
+}

+ 2 - 0
common/CHttpBll.h

@@ -74,6 +74,7 @@ signals:
     void sgnClientExamProcessUploadSign(CClientExamProcessUploadSign clientExamProcessUploadSign);
     void sgnUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun);
     void sgnExamControlCheckTime(CBaseResponsePackage res);
+    void sgnSkipFaceCheckParam(CSkipFaceCheckParam skipFaceCheckParam);
 public:
     CHttpBll();
 
@@ -138,6 +139,7 @@ private:
     void genClientExamProcessUploadSign(CClientExamProcessUploadSign *pClientExamProcessUploadSign, const std::string &sResponse);
 
 	void genExamCourseInfo(const Json::Value &jExamItem, CExamCourseInfo &eci);
+    void genSkipFaceCheckParam(CSkipFaceCheckParam *pSkipFaceCheckParam, const std::string &sResponse);
 
 	QString sKey;
     QString sToken;

+ 11 - 0
common/httpDataDef.h

@@ -89,6 +89,7 @@ enum class RequestType
     rtClientExamProcessUploadSign,//文件上传签名信息
     rtUploadFileToAliyun,
     rtExamControlCheckTime, //交卷冻结时间检查
+    rtSkipFaceCheckParam//检查当前考生是否跳过人脸识别接口
 };
 
 class CHttpRequestPackage
@@ -189,6 +190,7 @@ public:
     bool bDisableVirtualMachine;
 	bool bFullScreenTop; 	
 	bool bDisableVirtualCamera;
+    bool bExamingBlackListCheck;//考试中黑名单检测
 	QString sRootOrgId;// " : "0",
 	bool bShowQmthLogo;// " : "false",
 	bool bShowStudentClientAppQrcode;// " : "true",				
@@ -213,6 +215,7 @@ public:
         bDisableVirtualMachine = false;
         bFullScreenTop = false;
         bDisableVirtualCamera = false;
+        bExamingBlackListCheck = false;
 		sRootOrgId = "";// " : "0",
 		bShowQmthLogo = false;// " : "false",
 		bShowStudentClientAppQrcode = false;// " : "true",				
@@ -462,6 +465,7 @@ public:
 	std::vector<QString> vOfflineUploadFileType;
 
     bool bIsLivenessBefore;//考前活体检测
+    bool bFaceVerifyForceExit;//考中活体不通过强制退出
 
     bool bMutipleAnserCountTips;
 
@@ -485,6 +489,8 @@ public:
 		sCheatingRemark = "";
         bIsLivenessBefore = false;
 
+        bFaceVerifyForceExit = true;
+
         bMutipleAnserCountTips = false;
 	}
 };
@@ -1451,4 +1457,9 @@ public:
     QString sFileUrl = "";
 };
 
+class CSkipFaceCheckParam : public CBaseResponsePackage
+{
+public:
+    bool bSkipFaceCheck = false;
+};
 #endif // HTTPDATADEF_H

+ 32 - 1
component/CWebsocketProc.cpp

@@ -14,7 +14,7 @@ CWebsocketProc::CWebsocketProc()
     m_sToken = "";
     m_nTimeOutTimes = 0;
     m_nTimeOutLimit = 4;
-    m_nTimeOutSecord = 30;
+    m_nTimeOutSecord = 10;
     m_bConnected = false;
     m_pWebsocket = new QWebSocket;
     m_isExitClosed = false;
@@ -30,6 +30,11 @@ CWebsocketProc::CWebsocketProc()
     connect(m_pWebsocket, &QWebSocket::disconnected, this, &CWebsocketProc::onDisconnected);
     bool ret = connect(m_pWebsocket, &QWebSocket::textMessageReceived, this, &CWebsocketProc::onTextReceived);
     ret = connect(m_pWebsocket, &QWebSocket::connected, this, &CWebsocketProc::onConnected);
+
+    m_pHeartBeat = new QTimer;
+    connect(m_pHeartBeat, SIGNAL(timeout()), this, SLOT(onHeartBreatTimeout()));
+    m_pHeartBeat->setInterval(m_nTimeOutSecord*1000);
+    m_pHeartBeat->start();
 }
 
 CWebsocketProc::~CWebsocketProc()
@@ -52,6 +57,7 @@ void CWebsocketProc::setUrl(QString sUrl, QString sToken, QString sKey)
 
 void CWebsocketProc::open()
 {    
+    m_lastRecvTime = 0;
     m_isExitClosed = false;
     if(!m_sUrl.isEmpty())
     {      
@@ -93,6 +99,28 @@ bool CWebsocketProc::isConnected()
     return m_bConnected;
 }
 
+void CWebsocketProc::onHeartBreatTimeout()
+{
+    qDebug() << "onHeartBreatTimeout";
+    int nCurTime = g_appInfoPtr->serverMTime();
+    if(m_lastRecvTime != 0 && nCurTime - m_lastRecvTime > m_nTimeOutSecord*3*1000)
+    {
+        close();
+        open();
+        emit networkWeak();
+        return;
+    }
+
+    if(m_bConnected)
+    {
+        qint64 len = sendText("{eventType: \"HEARTBEAT\"}");
+        myDebug()<<len;
+    }
+    else
+    {
+    }
+}
+
 qint64 CWebsocketProc::sendText(QString sText)
 {
     if(m_bConnected)
@@ -140,6 +168,9 @@ void CWebsocketProc::onTextReceived(QString msg)
     try
     {
         qDebug()<<"recv:"<<msg;
+        myServerLog()<<"recv:"<<msg;
+
+        m_lastRecvTime = g_appInfoPtr->serverMTime();
 
         Json::Value jRececvMsg = Json::Value::null;
         Json::Reader reader;

+ 3 - 0
component/CWebsocketProc.h

@@ -33,6 +33,7 @@ private Q_SLOTS:
     void onConnected();
     void onTextReceived(QString msg);
     void reconnect();
+    void onHeartBreatTimeout();
 private:    
     QWebSocket *m_pWebsocket;
 
@@ -40,6 +41,7 @@ private:
     int m_nTimeOutLimit;
     int m_nTimeOutSecord;
     int m_nTimeOutTimes;
+    QTimer *m_pHeartBeat;
 
     QString m_sUrl;
     QString m_sToken;
@@ -48,6 +50,7 @@ private:
     bool m_bConnected;
 
     bool m_isExitClosed;
+    __int64 m_lastRecvTime = 0;
 };
 
 extern std::shared_ptr<CWebsocketProc> g_websocketPtr;

+ 7 - 3
component/CWindowsFireWall.cpp

@@ -909,8 +909,13 @@ bool CWindowsFireWall::getAllAppNameList(std::vector<CProcessData> &vAppList)
         return bRet;
     }
 
+    std::wstring sThisExePath = L"";
+    GetProcessFullPath(m_pid, sThisExePath);
+    QString sThisPath = QString::fromStdWString(sThisExePath).toLower();
+
+
     BOOL bMore = Process32First(hProcessSnap,&pe32);
-    QStringList list;
+    static QStringList list;
     while(bMore)
     {
         std::wstring sExePath = L"";
@@ -919,9 +924,8 @@ bool CWindowsFireWall::getAllAppNameList(std::vector<CProcessData> &vAppList)
 
         if(pe32.th32ProcessID != m_pid &&
                 !sExePath.empty() &&
-//                sPath.indexOf("c:\\windows\\system32") < 0 &&
+                sThisPath != sPath &&
                 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();

+ 37 - 10
face/faceCompare.cpp

@@ -76,8 +76,21 @@ faceCompare::faceCompare(QWidget *parent) :
                 });
 
                 connect(m_pSkipFaceCompare.get(), &skipFaceCompare::confirm, this, [&](){
-                    m_pSkipFaceCompare.reset();
-                    emit faceComparePass();
+                    //比对成功
+                    QString sFileName = QString("temp/photo/%1.png").arg(CCommonTools::getUuid());
+                    QImage imgCompare = CCommonTools::Mat2QImage(m_nCurImage);
+                    imgCompare.save(sFileName, "PNG");
+
+                    CHttpRequestPackage hrp;
+                    hrp.sUri = "/api/ecs_oe_student/client/exam/process/upload/sign";
+                    hrp.nRequestType = RequestType::rtClientExamProcessUploadSign;
+                    hrp.sCommonStr = __FILE__;
+                    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::hptBody;
+                    g_httpBllPtr->post(hrp);
                 });
             }
             m_pSkipFaceCompare->show();
@@ -275,7 +288,7 @@ void faceCompare::threadProc()
 #ifdef _DEBUG
                         g_appInfoPtr->m_oExamInfo.nFaceThreshold = 1;
 #endif // _DEBUG
-                        if(fScore*100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold)
+                        if(fScore*100 > g_appInfoPtr->m_oExamInfo.nFaceThreshold || g_appInfoPtr->m_bSkipFaceCheck)
                         {
 							m_fScore = fScore;
 							m_nFaceCount = nFaceCount;
@@ -354,7 +367,7 @@ void faceCompare::onClientExamProcessUploadSign(CClientExamProcessUploadSign pro
     catch (const std::exception &e)
     {
         ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
-        myServerLog()<<"exception error"<<e.what();
+        myServerLog()<<"onClientExamProcessUploadSign error"<<e.what();
     }
 }
 
@@ -396,7 +409,7 @@ void faceCompare::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyun)
     catch (const std::exception &e)
     {
         ShowMsg(QString::fromLocal8Bit("上传照片失败"), this, MSG_ICON_TYPE::mit_error);
-        myServerLog()<<"exception error"<<e.what();
+        myServerLog()<<"onUploadFileToAliyun error"<<e.what();
     }
 }
 
@@ -407,11 +420,25 @@ void faceCompare::onSaveFaceCompareResult(CBaseResponsePackage res)
     {
         if(res.nCode == 200)
         {
-            ShowMsg(QString::fromLocal8Bit("人脸比对成功"), this, MSG_ICON_TYPE::mit_succeed);
-            QTimer::singleShot(3000, this, [&](){
+            if(g_appInfoPtr->m_bSkipFaceCheck)
+            {
                 emit faceComparePass();
-            });
-
+            }
+            else
+            {
+                if(m_pSkipFaceCompare && m_pSkipFaceCompare->isVisible())
+                {
+                    m_pSkipFaceCompare.reset();
+                    emit faceComparePass();
+                }
+                else
+                {
+                    ShowMsg(QString::fromLocal8Bit("人脸比对成功"), this, MSG_ICON_TYPE::mit_succeed);
+                    QTimer::singleShot(3000, this, [&](){
+                        emit faceComparePass();
+                    });
+                }
+            }
         }
         else
         {
@@ -428,6 +455,6 @@ void faceCompare::onSaveFaceCompareResult(CBaseResponsePackage res)
     catch (const std::exception &e)
     {
         ShowMsg(QString::fromLocal8Bit("保存人脸识别信息失败"), this, MSG_ICON_TYPE::mit_error);
-        myServerLog()<<"exception error"<<e.what();
+        myServerLog()<<"onSaveFaceCompareResult error"<<e.what();
     }
 }

+ 18 - 5
face/faceLiveness.cpp

@@ -33,11 +33,14 @@ faceLiveness::faceLiveness(FACE_LIVENESS_TYPE livenessType, QWidget *parent) :
     {
         ui->label_fl_time->setVisible(true);
         ui->btn_fl_close->setVisible(false);
+        myServerLog()<< "FACE_LIVENESS_TYPE::flt_inprogress";
     }
     else
     {
         ui->label_fl_time->setVisible(false);
         ui->btn_fl_close->setVisible(true);
+
+        myServerLog()<< "FACE_LIVENESS_TYPE::flt_entry_exam";
     }
 
     m_nMaxSeconds = g_appInfoPtr->m_oExamInfo.nAllActionDuration;
@@ -70,7 +73,7 @@ faceLiveness::faceLiveness(FACE_LIVENESS_TYPE livenessType, QWidget *parent) :
         palette.setBrush(QPalette::Window, QBrush(img.scaled(ui->widget_fc_camera->width(), ui->widget_fc_camera->height())));
         ui->widget_fc_camera->setPalette(palette);
 
-        if(m_bStartCompare)
+        if(m_bStartCompare && !frame.empty())
         {
             std::scoped_lock sl(m_imgMutex);
             m_imgList.push_back(frame);
@@ -277,7 +280,7 @@ void faceLiveness::threadProc()
 			{
 				if (m_imgList.begin() != m_imgList.end())
 				{
-					myDebug() << "m_imgList:" << m_imgList.size();
+                    myServerLog() << "m_imgList:" << m_imgList.size();
 
 					cv::Mat matImage;
 					{
@@ -295,7 +298,7 @@ void faceLiveness::threadProc()
 
 					if (matImage.empty())
 					{
-						myDebug() << "matImage.empty";
+                        myServerLog() << "matImage.empty";
 						continue;
 					}
 
@@ -325,7 +328,7 @@ void faceLiveness::verifyAction(cv::Mat matImage)
 		int nFaceCount = 0;
 		float fScore = 0;
 
-		if (m_currentVerifyInfo.bIsVerify)
+        if (m_currentVerifyInfo.bIsVerify || matImage.empty())
 		{
 			return;
 		}
@@ -562,6 +565,16 @@ void faceLiveness:: saveLivenessResult()
 		bool bSubmit = true;
 		for (int i = 0; i < m_livenessList.count(); ++i)
 		{
+            if(m_livenessList[i].matImage.empty())
+            {
+                myServerLog()<<QString("saveLivenessResult index of %1 matImage is empty").arg(i);
+                if(m_livenessType == FACE_LIVENESS_TYPE::flt_entry_exam)
+                {
+                    emit faceLivenessFaild();
+                    return;
+                }
+            }
+
 			if (!m_livenessList[i].matImage.empty() &&
 				m_livenessList[i].sUrl.isEmpty())
 			{
@@ -673,7 +686,7 @@ void faceLiveness::actionTimer()
 {        
 	try
 	{
-		if (m_currentVerifyInfo.bIsVerify)
+        if (m_currentVerifyInfo.bIsVerify && !m_currentVerifyInfo.matImage.empty())
 		{
 			//当前比对完成
 			{

+ 4 - 2
face/inprogressFace.cpp

@@ -63,6 +63,7 @@ void CInprogressFace::addImage(cv::Mat matImage)
 {
     if(m_bStart)
     {
+
         std::scoped_lock lock(m_mImgList);
         m_vImgList.push_back(matImage);        
     }
@@ -70,6 +71,7 @@ void CInprogressFace::addImage(cv::Mat matImage)
 
 void CInprogressFace::addFaceCountImage(cv::Mat matImage)
 {
+    myServerLog()<<"inprogress start"<<m_bStart;
     if(m_bStart)
     {
         std::scoped_lock lock(m_mImgFaceCountList);
@@ -122,7 +124,7 @@ void CInprogressFace::threadProc()
 
                 if(matImage.empty())
                 {
-                    myDebug()<<"matImage.empty";
+                    myServerLog()<<"Inprogress matImage.empty";
                     continue;
                 }
 
@@ -290,7 +292,7 @@ void CInprogressFace::onUploadFileToAliyun(CUploadFileToAliyun uploadFileToAliyu
                 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();
+                myServerLog() << jBody.toStyledString().c_str();
                 g_httpBllPtr->post(hrp);
             }
             else

+ 67 - 67
launcher/envCheck.cpp

@@ -19,71 +19,71 @@ envCheck::envCheck(QWidget *parent) :
 
     initUI();
 
-    m_sCameraList<<"17GuaGua Cam"
-      <<"91KBOX"
-      <<"e2eSoft iVCam"
-      <<"e2eSoft VCam"
-      <<"FaceRig Virtual Camera"
-      <<"MagicCamera Capture"
-      <<"MeiSe"
-      <<"Virtual Cam"
-      << QString::fromLocal8Bit("YY伴侣")
-      <<"WebcamMax Capture"
-      <<"Wecam"
-      <<"Vcam "
-      <<"softcam"
-      <<"Vandate Virtual Camera"
-      <<"video2webcam"
-      <<"VCDCut Pro"
-      << QString::fromLocal8Bit("9158虚拟视频")
-      <<"9158Capture"
-      << "Insta360 Virtual Camera"
-      << QString::fromLocal8Bit("无他直播伴侣PC客户端")
-      << QString::fromLocal8Bit("无他相机电脑版")
-      <<"mobiola webcamera"
-      << QString::fromLocal8Bit("艾米秀宝(ImiShowBox)")
-      <<"video2Webcam"
-      << QString::fromLocal8Bit("飞翔虚拟视频")
-      << QString::fromLocal8Bit("魔力秀")
-      << QString::fromLocal8Bit("YY开播")
-      << QString::fromLocal8Bit("无他伴侣")
-      << QString::fromLocal8Bit("视频连麦")
-      << QString::fromLocal8Bit("酷狗直播伴侣")
-      <<"screen-capture-recorder"
-      <<"OBS Virtual Camera"
-      <<"OBS-Camera"
-      <<"ManyCam Virtual Webcam"
-      << QString::fromLocal8Bit("小葫芦直播助手")
-      <<"yyplayer"
-      << QString::fromLocal8Bit("秀色直播伴侣")
-      << QString::fromLocal8Bit("秀色直播助手")
-      <<"Citrix HDX Web Camera";
-
-    m_sRemoteList
-        <<"teamviewer"
-        <<"lookmypc"
-  //      <<"xt"
-        <<"winaw32"
-        <<"pcaquickconnect"
-        <<"sessioncontroller"
-        <<"sunlogin";
-        //<<"sunloginremote";
-    //		<< "qq"
-//        <<"wechat"
-//        <<"wemeetapp";
-
-    m_sRemoteTipList
-        <<"TeamViewer"
-        <<"LookMyPC"
-  //      << QString::fromLocal8Bit("协通")
-        <<"Symantec PCAnywhere"
-        <<"Symantec PCAnywhere"
-        <<"Symantec PCAnywhere"
-        << QString::fromLocal8Bit("向日葵");
-     //   << QString::fromLocal8Bit("向日葵");
-    //        <<"QQ"
-//        << QString::fromLocal8Bit("微信")
-//        << QString::fromLocal8Bit("腾讯会议");
+//    m_sCameraList<<"17GuaGua Cam"
+//      <<"91KBOX"
+//      <<"e2eSoft iVCam"
+//      <<"e2eSoft VCam"
+//      <<"FaceRig Virtual Camera"
+//      <<"MagicCamera Capture"
+//      <<"MeiSe"
+//      <<"Virtual Cam"
+//      << QString::fromLocal8Bit("YY伴侣")
+//      <<"WebcamMax Capture"
+//      <<"Wecam"
+//      <<"Vcam "
+//      <<"softcam"
+//      <<"Vandate Virtual Camera"
+//      <<"video2webcam"
+//      <<"VCDCut Pro"
+//      << QString::fromLocal8Bit("9158虚拟视频")
+//      <<"9158Capture"
+//      << "Insta360 Virtual Camera"
+//      << QString::fromLocal8Bit("无他直播伴侣PC客户端")
+//      << QString::fromLocal8Bit("无他相机电脑版")
+//      <<"mobiola webcamera"
+//      << QString::fromLocal8Bit("艾米秀宝(ImiShowBox)")
+//      <<"video2Webcam"
+//      << QString::fromLocal8Bit("飞翔虚拟视频")
+//      << QString::fromLocal8Bit("魔力秀")
+//      << QString::fromLocal8Bit("YY开播")
+//      << QString::fromLocal8Bit("无他伴侣")
+//      << QString::fromLocal8Bit("视频连麦")
+//      << QString::fromLocal8Bit("酷狗直播伴侣")
+//      <<"screen-capture-recorder"
+//      <<"OBS Virtual Camera"
+//      <<"OBS-Camera"
+//      <<"ManyCam Virtual Webcam"
+//      << QString::fromLocal8Bit("小葫芦直播助手")
+//      <<"yyplayer"
+//      << QString::fromLocal8Bit("秀色直播伴侣")
+//      << QString::fromLocal8Bit("秀色直播助手")
+//      <<"Citrix HDX Web Camera";
+
+//    m_sRemoteList
+//        <<"teamviewer"
+//        <<"lookmypc"
+//  //      <<"xt"
+//        <<"winaw32"
+//        <<"pcaquickconnect"
+//        <<"sessioncontroller"
+//        <<"sunlogin";
+//        //<<"sunloginremote";
+//    //		<< "qq"
+////        <<"wechat"
+////        <<"wemeetapp";
+
+//    m_sRemoteTipList
+//        <<"TeamViewer"
+//        <<"LookMyPC"
+//  //      << QString::fromLocal8Bit("协通")
+//        <<"Symantec PCAnywhere"
+//        <<"Symantec PCAnywhere"
+//        <<"Symantec PCAnywhere"
+//        << QString::fromLocal8Bit("向日葵");
+//     //   << QString::fromLocal8Bit("向日葵");
+//    //        <<"QQ"
+////        << QString::fromLocal8Bit("微信")
+////        << QString::fromLocal8Bit("腾讯会议");
 
     qRegisterMetaType<CSysNotice>("CSysNotice");
     connect(g_httpBllPtr.get(), &CHttpBll::sgnSysNotice, this, &envCheck::onSysNotice);
@@ -259,13 +259,13 @@ void envCheck::checkProc()
                 {
                     if(sCheckStr.isEmpty())
                     {
-                        sCheckStr = QString::fromLocal8Bit("请检测是否开启虚拟摄像头%1").arg(ci.name);
+                        sCheckStr = QString::fromLocal8Bit("请检测是否存在虚拟摄像头%1").arg(ci.name);
                     }
                     else
                     {
                         sCheckStr += QString::fromLocal8Bit("、%1").arg(ci.name);
                     }
-                    myDebug()<<QString::fromLocal8Bit("虚拟摄像头信息,vid:%1,pid%2:,name:%3")
+                    myDebug()<<QString::fromLocal8Bit("虚拟摄像头信息,vid:%1,pid:%2,name:%3")
                                    .arg(ci.vid).arg(ci.pid).arg(ci.name);
                 }
 

+ 6 - 0
launcher/main.cpp

@@ -7,6 +7,7 @@
 #include <QFileInfo>
 #include <QSettings>
 #include "CLogTrack.h"
+#include <QProcess>
 
 long  __stdcall CrashInfocallback(_EXCEPTION_POINTERS *pexcp)
 {
@@ -82,6 +83,11 @@ int main(int argc, char *argv[])
     qInstallMessageHandler(CustomOutputMessage);
     ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)CrashInfocallback);
 
+    QProcess process;
+    process.start("taskkill /f /im client.exe");
+    process.waitForFinished();
+
+
     launcher w;
     w.show();
 

+ 1 - 1
question/wxAnswer.cpp

@@ -134,7 +134,7 @@ wxAnswer::wxAnswer(QString sAnswerType, int nOrder, QWidget *parent) :
 
 wxAnswer::~wxAnswer()
 {
-	QFileInfo file("coe.cfgi");
+    QFileInfo file("coe.cfgi");
 	QString sFilePath = file.absoluteFilePath();
 	QSettings set(sFilePath, QSettings::IniFormat);