#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 "private/qhttpmultipart_p.h" #include #include "basemainTr.h" #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://ver.stem993.cn"); // static const QLatin1String scCode("code"); // static const QLatin1String scMessage("message"); // static const QLatin1String scData("data"); void critical(const QString &text, const QString &title = Tr::tr("Error")) { const QWidgetList widgetList = QApplication::topLevelWidgets(); QWidget *parentWidget = nullptr; if (!widgetList.isEmpty()) { parentWidget = widgetList.first(); } Q_UNUSED(parentWidget) qDebug() << parentWidget << text; // 获取当前活动窗口 // QMessageBox::critical(parentWidget, title, text); } void information(const QString &text, const QString &title = Tr::tr("information")) { const QWidgetList widgetList = QApplication::topLevelWidgets(); QWidget *parentWidget = nullptr; if (!widgetList.isEmpty()) { parentWidget = widgetList.first(); } Q_UNUSED(parentWidget) qDebug() << parentWidget << text << title; // 获取当前活动窗口 // QMessageBox::information(parentWidget, title, text); } // 响应拦截 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() << "error:" << data << jsonError.errorString(); return false; } #ifdef QT_DEBUG //qDebug() << QString::fromUtf8(jsonDoc.toJson()); #endif data = jsonDoc.object(); // if (jsonDoc.isObject()) { // const QJsonObject &object = jsonDoc.object(); // if (object.contains(scCode)) { // int code = object.value(scCode).toInt(); // if (code != 200) { // // 获取当前活动窗口 // critical(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) { //权限错误 critical(reply->errorString(), Tr::tr("Server Error")); return false; } else { //其他错误 AppEvent::instance()->setJwtToken(QString()); critical(reply->errorString(), Tr::tr("Server Error")); 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) { setAutoDeleteReplies(true); // 自动清理 QNetworkReply *reply } 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()); req.setRawHeader("Machine_code", AppEvent::instance()->machineCode().toUtf8()); 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; } 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 QVector files; 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); files.append(file); } QNetworkAccessManager *manager = NetworkAccessManager::instance(); QUrl fullUrl(QString(base_url).append(url)); QNetworkReply *reply = manager->post(QNetworkRequest(fullUrl), multiPart); if (!reply) { qDebug() << "sendRequest Operation error"; delete multiPart; qDeleteAll(files); return std::nullopt; } QObject::connect(reply, &QNetworkReply::finished, [multiPart, files]() { multiPart->deleteLater(); qDeleteAll(files); }); //等待请求结束 QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); QJsonValue data; if (!InterceptorsResponse(reply, data)) { reply->deleteLater(); return std::nullopt; } reply->deleteLater(); return data; } } // namespace TC