logplus/logPlus/ApiClient.cpp

191 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ApiClient.h"
#include <QJsonDocument>
#include <QDebug>
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();
}