feat(data): ApiProjectRepository 实现 IAsyncProjectRepository(9方法,Async后缀,薄封装,新旧并存)

This commit is contained in:
gaozheng 2026-06-12 07:42:00 +08:00
parent 2ee1ccdb0f
commit 05f0bf3d4f
2 changed files with 121 additions and 2 deletions

View File

@ -6,6 +6,8 @@
#include <QUrl>
#include "ApiClient.hpp"
#include "api/NavLoads.hpp"
#include "api/NavRequest.hpp"
#include "dto/NavDto.hpp"
namespace geopro::data {
@ -15,6 +17,9 @@ constexpr int kCodeSuccess = 200;
bool ok(const net::ApiResponse& r) { return r.code == kCodeSuccess; }
// 异步失败谓词(与同步 ok() 同口径:业务码非 200 或网络错误)。
bool isFailureA(const net::ApiResponse& r) { return r.code != kCodeSuccess || !r.rawError.isEmpty(); }
std::string errorOf(const net::ApiResponse& r, const char* fallback) {
if (!r.msg.isEmpty()) return r.msg.toStdString();
if (!r.rawError.isEmpty()) return r.rawError.toStdString();
@ -119,4 +124,100 @@ RepoResult<std::vector<ExceptionRow>> ApiProjectRepository::loadExceptionsByTm(
return {true, dto::parseExceptions(r.data.value(QStringLiteral("value")).toArray()), {}};
}
// ── 异步实现薄封装endpoint/body/parse 与同步版逐一对齐;解析器在 try 内见 ApiNavRequest──
NavRequest* ApiProjectRepository::listWorkspacesAsync() {
auto* call = api_.getAsync(QStringLiteral("/business/system/tenant/enterprise/joined/list"));
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseWorkspaces(r.data.value(QStringLiteral("value")).toArray()));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::switchWorkspaceAsync(const std::string& tenantId) {
const QString path =
QStringLiteral("/business/system/tenant/enterprise/switch/%1").arg(enc(tenantId));
auto* call = api_.postJsonAsync(path, QJsonObject{});
// 切换空间返回新 accessToken必须重新注入与同步版一致后续请求才落到新空间。
return new ApiNavRequest(call, [this](const net::ApiResponse& r) {
const QString token = r.data.value(QStringLiteral("accessToken")).toString();
if (!token.isEmpty()) api_.setToken(token);
return QVariant::fromValue(true);
}, &isFailureA);
}
NavRequest* ApiProjectRepository::pageProjectsAsync(const std::string& nameFilter,
const std::string& typeId, int pageNo,
int pageSize) {
QJsonObject body{{QStringLiteral("projectName"), QString::fromStdString(nameFilter)},
{QStringLiteral("pageNo"), pageNo},
{QStringLiteral("pageSize"), pageSize}};
if (!typeId.empty()) body[QStringLiteral("projectTypeId")] = QString::fromStdString(typeId);
auto* call = api_.postJsonAsync(QStringLiteral("/business/my/profile/project/page"), body);
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseProjectPage(r.data));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::listProjectTypesAsync() {
auto* call = api_.getAsync(QStringLiteral("/business/project/type/list"));
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseProjectTypes(r.data.value(QStringLiteral("value")).toArray()));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::loadStructureAsync(const std::string& projectId) {
const QString path =
QStringLiteral("/business/projectStruct/queryProjectStruct/%1").arg(enc(projectId));
auto* call = api_.getAsync(path);
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseStructNodes(r.data.value(QStringLiteral("value")).toArray()));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::loadRowsAsync(const std::string& projectId,
const std::string& parentId, int parentConfType,
int classifyType, int pageNo) {
const QString path = (classifyType == 1) ? QStringLiteral("/business/dsObject/file/page")
: QStringLiteral("/business/dsObject/data/page");
const QJsonObject body{
{QStringLiteral("projectId"), QString::fromStdString(projectId)},
{QStringLiteral("structParentId"), QString::fromStdString(parentId)},
{QStringLiteral("structParentConfType"), parentConfType},
{QStringLiteral("classifyTypeList"), QJsonArray{classifyType}},
{QStringLiteral("pageNo"), pageNo},
{QStringLiteral("pageSize"), 5}};
auto* call = api_.postJsonAsync(path, body);
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseDsPage(r.data));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::loadObjectDetailAsync(const std::string& objectId, int confType) {
const QString path =
(confType == 1)
? QStringLiteral("/business/gsObject/getGsObjectDetail/%1").arg(enc(objectId))
: QStringLiteral("/business/tmObject/getDetail/%1").arg(enc(objectId));
auto* call = api_.getAsync(path);
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseDynamicForm(r.data));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::loadDatasetFormAsync(const std::string& dsObjectId) {
const QString path = QStringLiteral("/business/dsObject/dynamicForm/%1").arg(enc(dsObjectId));
auto* call = api_.getAsync(path);
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseDynamicForm(r.data));
}, &isFailureA);
}
NavRequest* ApiProjectRepository::loadExceptionsByTmAsync(const std::string& tmObjectId) {
const QString path =
QStringLiteral("/business/exception/queryExceptionByTmObjectId/%1").arg(enc(tmObjectId));
auto* call = api_.getAsync(path);
return new ApiNavRequest(call, [](const net::ApiResponse& r) {
return QVariant::fromValue(dto::parseExceptions(r.data.value(QStringLiteral("value")).toArray()));
}, &isFailureA);
}
} // namespace geopro::data

View File

@ -1,15 +1,20 @@
#pragma once
#include "repo/IProjectRepository.hpp"
#include "repo/IAsyncProjectRepository.hpp"
namespace geopro::net { class ApiClient; }
namespace geopro::data {
// 用共享会话 ApiClient 实现导航仓储同步阻塞。token 由调用方注入 ApiClient。
class ApiProjectRepository : public IProjectRepository {
class NavRequest;
// 用共享会话 ApiClient 实现导航仓储。过渡期同时实现同步(旧)+异步(新)两接口。
// token 由调用方注入 ApiClient。
class ApiProjectRepository : public IProjectRepository, public IAsyncProjectRepository {
public:
explicit ApiProjectRepository(net::ApiClient& api);
// ── 同步(旧A6 删除) ──
RepoResult<std::vector<Workspace>> listWorkspaces() override;
RepoResult<bool> switchWorkspace(const std::string& tenantId) override;
RepoResult<ProjectListPage> pageProjects(const std::string& nameFilter, const std::string& typeId,
@ -22,6 +27,19 @@ public:
RepoResult<DynamicForm> loadDatasetForm(const std::string& dsObjectId) override;
RepoResult<std::vector<ExceptionRow>> loadExceptionsByTm(const std::string& tmObjectId) override;
// ── 异步(新) ── 返回 NavRequest*(薄封装,一方法一请求)。
NavRequest* listWorkspacesAsync() override;
NavRequest* switchWorkspaceAsync(const std::string& tenantId) override;
NavRequest* pageProjectsAsync(const std::string& nameFilter, const std::string& typeId,
int pageNo, int pageSize) override;
NavRequest* listProjectTypesAsync() override;
NavRequest* loadStructureAsync(const std::string& projectId) override;
NavRequest* loadRowsAsync(const std::string& projectId, const std::string& parentId,
int parentConfType, int classifyType, int pageNo) override;
NavRequest* loadObjectDetailAsync(const std::string& objectId, int confType) override;
NavRequest* loadDatasetFormAsync(const std::string& dsObjectId) override;
NavRequest* loadExceptionsByTmAsync(const std::string& tmObjectId) override;
private:
net::ApiClient& api_;
};