|
@@ -0,0 +1,314 @@
|
|
|
|
|
+#include "tapi.h"
|
|
|
|
|
+#include "appevent.h"
|
|
|
|
|
+#include "qcoreapplication.h"
|
|
|
|
|
+#include "qglobal.h"
|
|
|
|
|
+#include "qjsonobject.h"
|
|
|
|
|
+#include "qobject.h"
|
|
|
|
|
+
|
|
|
|
|
+#include <functional>
|
|
|
|
|
+#include <optional>
|
|
|
|
|
+
|
|
|
|
|
+#include <QApplication>
|
|
|
|
|
+#include <QFile>
|
|
|
|
|
+#include <QFileInfo>
|
|
|
|
|
+#include <QHttpMultiPart>
|
|
|
|
|
+#include <QJsonArray>
|
|
|
|
|
+#include <QJsonDocument>
|
|
|
|
|
+#include <QJsonObject>
|
|
|
|
|
+#include <QNetworkReply>
|
|
|
|
|
+#include <QUrlQuery>
|
|
|
|
|
+
|
|
|
|
|
+#include <QMessageBox>
|
|
|
|
|
+
|
|
|
|
|
+#include <QCoreApplication>
|
|
|
|
|
+
|
|
|
|
|
+struct Tr
|
|
|
|
|
+{
|
|
|
|
|
+ Q_DECLARE_TR_FUNCTIONS(TeacherServer)
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+#include "api/tloginapi.h"
|
|
|
|
|
+namespace TC {
|
|
|
|
|
+// 创建一个映射来存储错误码和对应的信息
|
|
|
|
|
+static QMap<RequestCode, QString> 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://127.0.0.1:8080");
|
|
|
|
|
+
|
|
|
|
|
+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<RequestCode>(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;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+}; // 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<QHttpMultiPartIODevice *>(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<QJsonValue> 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<bool(QNetworkReply *)> 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<QJsonValue> 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
|