#include "tapi.h" #include "appevent.h" #include "qcoreapplication.h" #include "qglobal.h" #include "qjsonobject.h" #include "qobject.h" #include #include #include #include #include #include #include #include #include #include #include #include #include struct Tr { Q_DECLARE_TR_FUNCTIONS(TeacherServer) }; #include "api/tloginapi.h" namespace TC { // 创建一个映射来存储错误码和对应的信息 static QMap errorMessages = {{RequestCode::OK, Tr::tr("OK")}, {RequestCode::GeneralServerError, Tr::tr("General Server Error")}, {RequestCode::InvalidRequest, Tr::tr("Invalid Request")}, {RequestCode::TokenExpired, Tr::tr("Token Expired")}, {RequestCode::DatabaseError, Tr::tr("Database Error")}, {RequestCode::UsernameError, Tr::tr("Username Error")}, {RequestCode::InvalidPhoneFormat, Tr::tr("Invalid Phone Format")}, {RequestCode::PasswordRequirementsNotMet, Tr::tr("Password Requirements Not Met")}, {RequestCode::PhoneAlreadyRegistered, Tr::tr("Phone Already Registered")}, {RequestCode::IncorrectCredentials, Tr::tr("Incorrect Credentials")}, {RequestCode::GetPhoneCodeError, Tr::tr("Get Phone Code Error")}, {RequestCode::PhoneCodeExists, Tr::tr("Phone Code Exists")}, {RequestCode::PhoneCodeNotFound, Tr::tr("Phone Code Not Found")}, {RequestCode::CorrectVerificationCode, Tr::tr("Correct Verification Code")}, {RequestCode::UpdateLoginPasswordFailed, Tr::tr("Update Login Password Failed")}, {RequestCode::RealNameVerificationFailed, Tr::tr("Real Name Verification Failed")}, {RequestCode::VIPExpirationTimeFailed, Tr::tr("VIP Expiration Time Failed")}}; static QString base_url("http://exam.stem993.cn"); static const QLatin1String scCode("code"); static const QLatin1String scMessage("message"); static const QLatin1String scData("data"); // 响应拦截 static bool InterceptorsResponse(QNetworkReply *reply, QJsonValue &data) { if (reply->error() == QNetworkReply::NoError) { const QByteArray allData = reply->readAll(); QJsonParseError jsonError; QJsonDocument jsonDoc = QJsonDocument::fromJson(allData, &jsonError); if (jsonError.error != QJsonParseError::NoError) { qDebug() << data; return false; } #ifdef QT_DEBUG qDebug() << QString::fromUtf8(jsonDoc.toJson()); #endif if (jsonDoc.isObject()) { const QJsonObject &object = jsonDoc.object(); if (object.contains(scCode)) { int code = object.value(scCode).toInt(); if (code != 0) { // RequestCode requestCode = static_cast(code); const QWidgetList widgetList = QApplication::topLevelWidgets(); QWidget *parentWidget = nullptr; if (!widgetList.isEmpty()) { parentWidget = widgetList.first(); } // 获取当前活动窗口 QMessageBox::critical(parentWidget, Tr::tr("Error"), object[scMessage].toString()); // if (errorMessages.contains(requestCode)) { // //Core::MessageManager::writeFlashing(errorMessages[requestCode]); // } else { // //Core::MessageManager::writeFlashing(Tr::tr("unknown error")); // } return false; } } if (object.contains(scMessage)) { const QString &message = object.value(scMessage).toString(); // Core::MessageManager::writeFlashing(message); } if (object.contains(scData)) { data = object.value(scData); } } return true; } else if (reply->error() == QNetworkReply::InternalServerError) { //权限错误 qDebug() << "0" << reply->error(); AppEvent::instance()->setJwtToken(QString()); QWidget *parentWidget = QApplication::topLevelWidgets().first(); QMessageBox::critical(parentWidget, Tr::tr("Server Error"), reply->errorString()); return false; } else { //其他错误 AppEvent::instance()->setJwtToken(QString()); qDebug() << "1" << reply->error(); QWidget *parentWidget = QApplication::topLevelWidgets().first(); // 获取当前活动窗口 QMessageBox::critical(parentWidget, Tr::tr("Server Error"), reply->errorString()); // Core::MessageManager::writeFlashing(reply->errorString()); return false; } return false; } static bool InterceptorsResponse2(QNetworkReply *reply, QJsonValue &data) { if (reply->error() == QNetworkReply::NoError) { const QByteArray allData = reply->readAll(); QJsonParseError jsonError; QJsonDocument jsonDoc = QJsonDocument::fromJson(allData, &jsonError); if (jsonError.error != QJsonParseError::NoError) { qDebug() << data; return false; } #ifdef QT_DEBUG qDebug() << QString::fromUtf8(jsonDoc.toJson()); #endif if (jsonDoc.isObject()) { const QJsonObject &object = jsonDoc.object(); data = object; // if (object.contains(scCode)) { // int code = object.value(scCode).toInt(); // if (code != 0) { // return false; // } // } // if (object.contains(scMessage)) { // const QString &message = object.value(scMessage).toString(); // // Core::MessageManager::writeFlashing(message); // } // if (object.contains(scData)) { // data = object.value(scData); // } } return true; } else if (reply->error() == QNetworkReply::InternalServerError) { //权限错误 qDebug() << "0" << reply->error(); AppEvent::instance()->setJwtToken(QString()); return false; } else { //其他错误 qDebug() << reply->error() << reply->errorString(); AppEvent::instance()->setJwtToken(QString()); return false; } return false; } }; // namespace TC namespace TC { static NetworkAccessManager *namInstance = nullptr; void cleanupNetworkAccessManager() { delete namInstance; namInstance = nullptr; } NetworkAccessManager *NetworkAccessManager::instance() { if (!namInstance) { namInstance = new NetworkAccessManager; qAddPostRoutine(cleanupNetworkAccessManager); } return namInstance; } NetworkAccessManager::NetworkAccessManager(QObject *parent) : QNetworkAccessManager(parent) { // const QString ip = AppEvent::instance()->configValue("serverIP").toString(); // const QString port = AppEvent::instance()->configValue("serverPort").toString(); // base_url = QString("http://%1:%2").arg(ip).arg(port); } QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) { QString agentStr = QString::fromLatin1("%1/%2 (QNetworkAccessManager %3; %4; %5; %6 bit)") .arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion(), QLatin1String(qVersion()), QSysInfo::prettyProductName(), QLocale::system().name()) .arg(QSysInfo::WordSize); QNetworkRequest req(request); req.setRawHeader("User-Agent", agentStr.toLatin1()); // QHttpMultiPartIODevice *multiPart = dynamic_cast(outgoingData); // if (multiPart) { // // req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart"); // } else { req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); } const QUrl &url = request.url(); const QString urlPath = url.path(); qDebug() << url; //设置白名单 if (urlPath.indexOf(RefreshToken().url) >= 0 || urlPath.indexOf(Login().url) >= 0) { } else { //需要刷新token // qDebug() << "RefreshToken" << urlPath; if (AppEvent::instance()->isRefreshToken()) { RefreshToken().get(); } } //这里考虑处理 JWT 数据 const QString &token = AppEvent::instance()->jwtToken(); // 加个事件校验 防止token 失效导致异常 if (!token.isEmpty()) { req.setRawHeader("Authorization", "Bearer " + token.toUtf8()); } return QNetworkAccessManager::createRequest(op, req, outgoingData); } // std::optional sendRequest(QNetworkAccessManager::Operation op, const QString &url, const QByteArray &postData = QByteArray()) { QNetworkAccessManager *manager = NetworkAccessManager::instance(); manager->setTransferTimeout(3000); QNetworkReply *reply = nullptr; QUrl fullUrl(QString(base_url).append(url)); switch (op) { case QNetworkAccessManager::HeadOperation: reply = manager->head(QNetworkRequest(fullUrl)); break; case QNetworkAccessManager::GetOperation: reply = manager->get(QNetworkRequest(fullUrl)); break; case QNetworkAccessManager::PutOperation: reply = manager->put(QNetworkRequest(fullUrl), postData); break; case QNetworkAccessManager::PostOperation: reply = manager->post(QNetworkRequest(fullUrl), postData); break; case QNetworkAccessManager::DeleteOperation: reply = manager->deleteResource(QNetworkRequest(fullUrl)); break; case QNetworkAccessManager::CustomOperation: break; default: break; } if (!reply) { qDebug() << "sendRequest Operation error"; } //等待请求结束 QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); QJsonValue data; if (!InterceptorsResponse(reply, data)) { return std::nullopt; } return data; } std::optional sendRawRequest(QNetworkAccessManager::Operation op, const QString &url, const QByteArray &postData = QByteArray()) { QNetworkAccessManager *manager = NetworkAccessManager::instance(); manager->setTransferTimeout(3000); QNetworkReply *reply = nullptr; QUrl fullUrl(QString(base_url).append(url)); switch (op) { case QNetworkAccessManager::HeadOperation: reply = manager->head(QNetworkRequest(fullUrl)); break; case QNetworkAccessManager::GetOperation: reply = manager->get(QNetworkRequest(fullUrl)); break; case QNetworkAccessManager::PutOperation: reply = manager->put(QNetworkRequest(fullUrl), postData); break; case QNetworkAccessManager::PostOperation: reply = manager->post(QNetworkRequest(fullUrl), postData); break; case QNetworkAccessManager::DeleteOperation: reply = manager->deleteResource(QNetworkRequest(fullUrl)); break; case QNetworkAccessManager::CustomOperation: break; default: break; } if (!reply) { qDebug() << "sendRequest Operation error"; } //等待请求结束 QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); QJsonValue data; if (!InterceptorsResponse2(reply, data)) { return std::nullopt; } return data; } bool downRequest(const QString &url, const QByteArray &fileName, std::function callback) { QNetworkAccessManager *manager = NetworkAccessManager::instance(); manager->setTransferTimeout(30000); QUrl fullUrl(QString(base_url).append(url)); QUrlQuery query; query.addQueryItem("file", fileName); fullUrl.setQuery(query); QNetworkReply *reply = manager->get(QNetworkRequest(fullUrl)); if (!reply) { qDebug() << "sendRequest Operation error"; } //等待请求结束 QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); return callback(reply); } std::optional uploaderRequest(const QString &url, const QStringList &fileList) { QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); // Create a file part for (const QString &filePath : fileList) { QFile *file = new QFile(filePath); if (!file->open(QIODevice::ReadOnly)) { qWarning() << "Cannot open file:" << file->errorString(); return false; } QHttpPart filePart; filePart.setBodyDevice(file); filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream")); filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"file\"; filename=\"%1\"") .arg(QFileInfo(filePath).fileName())); file->setParent(multiPart); // Ensure file is deleted with multiPart multiPart->append(filePart); } QNetworkAccessManager *manager = NetworkAccessManager::instance(); QUrl fullUrl(QString(base_url).append(url)); QNetworkReply *reply = manager->post(QNetworkRequest(fullUrl), multiPart); if (!reply) { qDebug() << "sendRequest Operation error"; } //等待请求结束 QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); QJsonValue data; if (!InterceptorsResponse(reply, data)) { return std::nullopt; } return data; } } // namespace TC