#include "ApiClient.h" #include #include static QString joinUrl(const QString &base, const QString &path) { if (path.startsWith("http://") || path.startsWith("https://")) return path; QString b = base; QString p = path; if (b.endsWith('/')) b.chop(1); if (p.startsWith('/')) p.remove(0, 1); if (b.isEmpty()) return p; return b + '/' + p; } ApiClient* ApiClient::m_instance = nullptr; ApiClient::ApiClient(QObject *parent) : QObject(parent) , m_httpClient(new AeaQt::HttpClient(this)) { } ApiClient::~ApiClient() { } ApiClient* ApiClient::getInstance() { if (m_instance == nullptr) { if (m_instance == nullptr) { m_instance = new ApiClient(); } } return m_instance; } AeaQt::HttpClient* ApiClient::httpClient() const { return m_httpClient; } void ApiClient::setBaseUrl(const QString &baseUrl) { m_baseUrl = baseUrl; } QString ApiClient::baseUrl() const { return m_baseUrl; } void ApiClient::setToken(const QString &token) { // 保存时确保前缀存在:如果调用方传入原始 token(不带 Bearer)也能工作 if (token.startsWith("Bearer ")) m_token = token; else if (token.isEmpty()) m_token.clear(); else m_token = "Bearer " + token; } QString ApiClient::token() const { return m_token; } void ApiClient::handleResponse(const QJsonObject &resp, SuccessCB onSuccess, FailedCB onFailed) { // 统一处理服务端返回格式:{ code, message, data } int code = resp.value("code").toInt(-1); QString message = resp.value("message").toString(); if (code != 0) { if (onFailed) onFailed(message); return; } // 成功,优先返回 data 字段(如果存在且为 object),否则返回整个 resp if (resp.contains("data") && resp.value("data").isObject()) { if (onSuccess) onSuccess(resp.value("data").toObject()); return; } if (onSuccess) onSuccess(resp); } void ApiClient::login(const QString &username, const QString &password, SuccessCB onSuccess, FailedCB onFailed) { QJsonObject body; body["login_mode"] = "local"; body["login_type"] = "username"; body["identifier"] = username; body["password"] = password; QString url = joinUrl(m_baseUrl, "/auth/api/v1/auth/login"); m_httpClient->post(url) .bodyWithJson(body) .onSuccess([this, onSuccess, onFailed](const QJsonObject &resp) { // 先统一处理返回结构 this->handleResponse(resp, // onSuccess -> 特殊处理 login 的 token 保存 [this, onSuccess](const QJsonObject &data) { QString rawToken = data.value("token").toString(); if (!rawToken.isEmpty()) { this->setToken(rawToken); } if (onSuccess) onSuccess(data); }, // onFailed [onFailed](const QString &err) { if (onFailed) onFailed(err); } ); }) .onFailed([onFailed](const QString &err) { if (onFailed) onFailed(err); }) .exec(); } void ApiClient::get(const QString &path, SuccessCB onSuccess, FailedCB onFailed) { qDebug() << "ApiClient::get " << path; QString url = joinUrl(m_baseUrl, path); auto req = m_httpClient->get(url); if (!m_token.isEmpty()) req.header("Authorization", m_token); req.onSuccess([this, onSuccess, onFailed](const QJsonObject &resp) { this->handleResponse(resp, onSuccess, onFailed); }) .onFailed([onFailed](const QString &err) { if (onFailed) onFailed(err); }) .exec(); } void ApiClient::post(const QString &path, const QJsonObject &body, SuccessCB onSuccess, FailedCB onFailed) { qDebug() << "ApiClient::post " << path; QString url = joinUrl(m_baseUrl, path); auto req = m_httpClient->post(url).bodyWithJson(body); if (!m_token.isEmpty()) req.header("Authorization", m_token); req.onSuccess([this, onSuccess, onFailed](const QJsonObject &resp) { this->handleResponse(resp, onSuccess, onFailed); }) .onFailed([onFailed](const QString &err) { if (onFailed) onFailed(err); }) .exec(); } void ApiClient::put(const QString &path, const QJsonObject &body, SuccessCB onSuccess, FailedCB onFailed) { QString url = joinUrl(m_baseUrl, path); auto req = m_httpClient->put(url).bodyWithJson(body); if (!m_token.isEmpty()) req.header("Authorization", m_token); req.onSuccess([this, onSuccess, onFailed](const QJsonObject &resp) { this->handleResponse(resp, onSuccess, onFailed); }) .onFailed([onFailed](const QString &err) { if (onFailed) onFailed(err); }) .exec(); } void ApiClient::del(const QString &path, SuccessCB onSuccess, FailedCB onFailed) { QString url = joinUrl(m_baseUrl, path); auto req = m_httpClient->del(url); if (!m_token.isEmpty()) req.header("Authorization", m_token); req.onSuccess([this, onSuccess, onFailed](const QJsonObject &resp) { this->handleResponse(resp, onSuccess, onFailed); }) .onFailed([onFailed](const QString &err) { if (onFailed) onFailed(err); }) .exec(); } void ApiClient::getBinary(const QString &path, BinarySuccessCB onSuccess, FailedCB onFailed) { qDebug() << "ApiClient::getBinary " << path; QString url = joinUrl(m_baseUrl, path); auto req = m_httpClient->get(url); if (!m_token.isEmpty()) req.header("Authorization", m_token); // 直接使用 QByteArray 回调,跳过 JSON 解析 req.onSuccess([onSuccess, onFailed](const QByteArray &data) { if (onSuccess) onSuccess(data); }) .onFailed([onFailed](const QString &err) { if (onFailed) onFailed(err); }) .exec(); }