feat/object-selection-panels #4

Merged
gaozheng merged 18 commits from feat/object-selection-panels into main 2026-06-10 21:33:30 +08:00
2 changed files with 84 additions and 15 deletions
Showing only changes of commit 8cab498f81 - Show all commits

View File

@ -1,5 +1,7 @@
#include "WorkbenchNavController.hpp" #include "WorkbenchNavController.hpp"
#include "dto/NavDto.hpp"
namespace geopro::controller { namespace geopro::controller {
using data::ProjectSummary; using data::ProjectSummary;
@ -63,6 +65,8 @@ void WorkbenchNavController::loadProjectsAndStructure() {
emit projectsLoaded(ps.value.rows, curP, ps.value.total); emit projectsLoaded(ps.value.rows, curP, ps.value.total);
if (curP.isEmpty()) { if (curP.isEmpty()) {
lastStructNodes_.clear();
tmExceptionCache_.clear();
emit structureLoaded(QString(), {}); // 暂无项目 → 空树 emit structureLoaded(QString(), {}); // 暂无项目 → 空树
return; return;
} }
@ -71,6 +75,7 @@ void WorkbenchNavController::loadProjectsAndStructure() {
emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error)); emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error));
return; return;
} }
lastStructNodes_ = st.value;
emit structureLoaded(QString::fromStdString(currentProjectName_), st.value); emit structureLoaded(QString::fromStdString(currentProjectName_), st.value);
} }
@ -100,54 +105,108 @@ void WorkbenchNavController::switchProject(const QString& projectId) {
emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error)); emit loadFailed(QStringLiteral("structure"), QString::fromStdString(st.error));
return; return;
} }
lastStructNodes_ = st.value;
tmExceptionCache_.clear();
emit structureLoaded(QString::fromStdString(currentProjectName_), st.value); emit structureLoaded(QString::fromStdString(currentProjectName_), st.value);
} }
void WorkbenchNavController::selectTm(const QString& tmObjectId) { void WorkbenchNavController::selectObject(const QString& objectId, int confType) {
if (tmObjectId.isEmpty() || busy_) return; if (objectId.isEmpty() || busy_) return;
BusyGuard guard(this, &busy_); BusyGuard guard(this, &busy_);
currentTmId_ = tmObjectId.toStdString(); currentParentId_ = objectId.toStdString();
currentParentConfType_ = confType;
const std::string pid = currentProjectId_; const std::string pid = currentProjectId_;
dataPageNo_ = 1; dataPageNo_ = 1;
filePageNo_ = 1; filePageNo_ = 1;
const auto d = repo_.loadTmRows(pid, currentTmId_, 3, dataPageNo_); const auto d = repo_.loadRows(pid, currentParentId_, confType, 3, dataPageNo_);
if (!d.ok) { if (!d.ok) {
emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error)); emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error));
return; return;
} }
dataTotal_ = d.value.total; dataTotal_ = d.value.total;
emit datasetsLoaded(tmObjectId, d.value.rows, d.value.total, false); emit datasetsLoaded(objectId, d.value.rows, d.value.total, false);
const auto f = repo_.loadTmRows(pid, currentTmId_, 1, filePageNo_); const auto f = repo_.loadRows(pid, currentParentId_, confType, 1, filePageNo_);
if (!f.ok) { if (!f.ok) {
emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error)); emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error));
return; return;
} }
fileTotal_ = f.value.total; fileTotal_ = f.value.total;
emit filesLoaded(tmObjectId, f.value.rows, f.value.total, false); emit filesLoaded(objectId, f.value.rows, f.value.total, false);
const auto detail = repo_.loadObjectDetail(currentParentId_, confType);
if (!detail.ok) {
emit loadFailed(QStringLiteral("objectDetail"), QString::fromStdString(detail.error));
return;
}
emit objectDetailLoaded(objectId, detail.value);
} }
void WorkbenchNavController::loadMoreData() { void WorkbenchNavController::loadMoreData() {
if (currentTmId_.empty() || busy_) return; if (currentParentId_.empty() || busy_) return;
BusyGuard guard(this, &busy_); BusyGuard guard(this, &busy_);
const auto d = repo_.loadTmRows(currentProjectId_, currentTmId_, 3, ++dataPageNo_); const auto d = repo_.loadRows(currentProjectId_, currentParentId_, currentParentConfType_, 3, ++dataPageNo_);
if (!d.ok) { if (!d.ok) {
emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error)); emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error));
return; return;
} }
dataTotal_ = d.value.total; dataTotal_ = d.value.total;
emit datasetsLoaded(QString::fromStdString(currentTmId_), d.value.rows, d.value.total, true); emit datasetsLoaded(QString::fromStdString(currentParentId_), d.value.rows, d.value.total, true);
} }
void WorkbenchNavController::loadMoreFiles() { void WorkbenchNavController::loadMoreFiles() {
if (currentTmId_.empty() || busy_) return; if (currentParentId_.empty() || busy_) return;
BusyGuard guard(this, &busy_); BusyGuard guard(this, &busy_);
const auto f = repo_.loadTmRows(currentProjectId_, currentTmId_, 1, ++filePageNo_); const auto f = repo_.loadRows(currentProjectId_, currentParentId_, currentParentConfType_, 1, ++filePageNo_);
if (!f.ok) { if (!f.ok) {
emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error)); emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error));
return; return;
} }
fileTotal_ = f.value.total; fileTotal_ = f.value.total;
emit filesLoaded(QString::fromStdString(currentTmId_), f.value.rows, f.value.total, true); emit filesLoaded(QString::fromStdString(currentParentId_), f.value.rows, f.value.total, true);
}
void WorkbenchNavController::setCheckedTms(const QStringList& tmObjectIds) {
if (busy_) return;
BusyGuard guard(this, &busy_);
auto nameOf = [this](const std::string& id) -> std::string {
for (const auto& n : lastStructNodes_)
if (n.id == id) return n.name;
return id;
};
std::vector<data::ObjectExceptionGroup> groups;
int total = 0;
for (const QString& tmQ : tmObjectIds) {
const std::string tm = tmQ.toStdString();
auto it = tmExceptionCache_.find(tm);
if (it == tmExceptionCache_.end()) {
const auto ex = repo_.loadExceptionsByTm(tm);
if (!ex.ok) {
emit loadFailed(QStringLiteral("exceptions"), QString::fromStdString(ex.error));
return;
}
it = tmExceptionCache_.emplace(tm, ex.value).first;
}
const auto grouped = data::dto::groupExceptionsByConsortium(it->second);
data::ObjectExceptionGroup g;
g.objectId = tm;
g.objectName = nameOf(tm);
g.consortia = grouped.consortia;
g.looseExceptions = grouped.loose;
total += static_cast<int>(it->second.size());
groups.push_back(std::move(g));
}
emit exceptionTreeLoaded(groups, total);
}
void WorkbenchNavController::selectDataset(const QString& dsObjectId) {
if (dsObjectId.isEmpty() || busy_) return;
BusyGuard guard(this, &busy_);
const auto form = repo_.loadDatasetForm(dsObjectId.toStdString());
if (!form.ok) {
emit loadFailed(QStringLiteral("datasetDetail"), QString::fromStdString(form.error));
return;
}
emit datasetDetailLoaded(form.value);
} }
} // namespace geopro::controller } // namespace geopro::controller

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QStringList>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -21,7 +23,9 @@ public:
public slots: public slots:
void switchWorkspace(const QString& tenantId); void switchWorkspace(const QString& tenantId);
void switchProject(const QString& projectId); void switchProject(const QString& projectId);
void selectTm(const QString& tmObjectId); void selectObject(const QString& objectId, int confType); // 单击对象→DS列表+对象详情
void setCheckedTms(const QStringList& tmObjectIds); // 勾选叶子集→异常树
void selectDataset(const QString& dsObjectId); // 单击DS→数据集动态表单
void loadMoreData(); void loadMoreData();
void loadMoreFiles(); void loadMoreFiles();
@ -35,6 +39,9 @@ signals:
int total, bool append); int total, bool append);
void filesLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows, void filesLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows,
int total, bool append); int total, bool append);
void objectDetailLoaded(const QString& title, const geopro::data::DynamicForm& form);
void exceptionTreeLoaded(const std::vector<geopro::data::ObjectExceptionGroup>& groups, int tmCount);
void datasetDetailLoaded(const geopro::data::DynamicForm& form);
void loadFailed(const QString& stage, const QString& message); void loadFailed(const QString& stage, const QString& message);
private: private:
@ -44,7 +51,10 @@ private:
bool busy_ = false; bool busy_ = false;
std::vector<data::ProjectSummary> lastProjects_; std::vector<data::ProjectSummary> lastProjects_;
std::string currentWorkspaceId_, currentProjectId_, currentProjectName_, currentCrsCode_; std::string currentWorkspaceId_, currentProjectId_, currentProjectName_, currentCrsCode_;
std::string currentTmId_; std::string currentParentId_;
int currentParentConfType_ = 0;
std::vector<data::StructNode> lastStructNodes_; // tmId→name 解析
std::map<std::string, std::vector<data::ExceptionRow>> tmExceptionCache_;
int dataPageNo_ = 0; int dataPageNo_ = 0;
int filePageNo_ = 0; int filePageNo_ = 0;
int dataTotal_ = 0; int dataTotal_ = 0;