geopro/src/controller/WorkbenchNavController.hpp

105 lines
5.8 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.

#pragma once
#include <QObject>
#include <QPointer>
#include <QString>
#include <QStringList>
#include <map>
#include <string>
#include <vector>
#include "repo/RepoTypes.hpp"
namespace geopro::data {
class IAsyncProjectRepository;
class NavRequest;
} // namespace geopro::data
namespace geopro::controller {
// 导航状态机:编排 IAsyncProjectRepository异步句柄持有当前 空间/项目 状态,经信号驱动 UI。
// 不持有 widget。abort-and-replace + 句柄身份比对保证迟到信号被丢弃spec §5.0)。
// busyChanged 语义:「是否存在任一在飞句柄」(去抖:值变才发)。
class WorkbenchNavController : public QObject {
Q_OBJECT
public:
explicit WorkbenchNavController(data::IAsyncProjectRepository& repo, QObject* parent = nullptr);
~WorkbenchNavController() override; // 退出契约abort 所有在飞句柄
void start(); // 启动:拉空间 → 项目 → 结构(依赖链)
QString currentCrsCode() const { return QString::fromStdString(currentCrsCode_); }
QString currentProjectId() const { return QString::fromStdString(currentProjectId_); }
public slots:
void switchWorkspace(const QString& tenantId);
void switchProject(const QString& projectId);
void selectObject(const QString& objectId, int confType); // 单击对象→DS列表+对象详情(并发)
void setCheckedTms(const QStringList& tmObjectIds); // 勾选叶子集→异常树(并发,带缓存)
void selectDataset(const QString& dsObjectId); // 单击DS→数据集动态表单
void loadMoreData();
void loadMoreFiles();
void deleteObject(const QString& objectId, int confType); // 删除GS/TM→成功后刷新结构
void deleteDataset(const QString& dsObjectId); // 删除DS→成功后刷新当前TM数据集列表
// 右键「异常详情」GS→收集其下全部 TM 子孙TM→自身复用 setCheckedTms 拉取并发射异常树。
void showObjectExceptions(const QString& objectId, int confType);
signals:
void busyChanged(bool busy);
void workspacesLoaded(const std::vector<geopro::data::Workspace>& list, const QString& currentId);
void projectsLoaded(const std::vector<geopro::data::ProjectSummary>& list,
const QString& currentId, int total);
void structureLoaded(const QString& projectName, const std::vector<geopro::data::StructNode>& nodes);
void datasetsLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows,
int total, bool append);
void filesLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows,
int total, bool append);
void objectDetailLoaded(const QString& title, const geopro::data::DynamicForm& form);
void exceptionTreeLoaded(const std::vector<geopro::data::ObjectExceptionGroup>& groups, int exceptionCount);
void datasetDetailLoaded(const geopro::data::DynamicForm& form);
void loadFailed(const QString& stage, const QString& message);
// 增删改结果(用于状态栏/toast 反馈;成功后控制器已自行触发相应刷新)。
void mutationSucceeded(const QString& message);
void mutationFailed(const QString& message);
private:
// start / switchWorkspace 依赖链:拉项目 → 拉结构(续延,复用)。
void runProjectsAndStructure();
void abortAll(); // 退出/重置时 abort 所有在飞句柄
void resetSelectionState(); // 切项目/工作空间重置选中态spec §6
void emitBusyIfChanged(); // 据「是否存在任一在飞句柄」去抖发 busyChanged
bool anyInflight() const; // OR 所有在飞 QPointer / 集合
void assembleAndEmitExceptionTree(const QStringList& tmObjectIds); // 缓存命中后组装异常树
// 数据页树形分页:从 allDataRows_一次取全的整棵按「第一层节点(根)」切下一页,
// 每页 kDataRootPageSize 个根 + 各自整棵子树total=根总数。append=false 首页、true 加载更多。
void emitNextDataRootPage(bool append);
data::IAsyncProjectRepository& repo_;
bool lastBusy_ = false;
// 在飞句柄QPointer 防悬垂;身份比对用):
QPointer<data::NavRequest> startStepReq_; // start / switchWorkspace 依赖链当前在飞级
QPointer<data::NavRequest> structReq_; // switchProject
QPointer<data::NavRequest> selDataReq_; // selectObjectdata 行
QPointer<data::NavRequest> selFileReq_; // selectObjectfile 行
QPointer<data::NavRequest> selDetailReq_; // selectObject对象详情
QPointer<data::NavRequest> moreFilesReq_; // loadMoreFiles数据页改客户端按根分页无在飞句柄
QPointer<data::NavRequest> datasetReq_;
QPointer<data::NavRequest> mutateReq_; // 删除/增改abort-and-replace 单路)
std::vector<QPointer<data::NavRequest>> checkedInflight_; // setCheckedTms未命中缓存的并发批
std::vector<data::ProjectSummary> lastProjects_;
std::string currentWorkspaceId_, currentProjectId_, currentProjectName_, currentCrsCode_;
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 filePageNo_ = 0;
int dataTotal_ = 0; // 数据页:根节点总数(树形分页单位)
int fileTotal_ = 0;
std::vector<data::DsRow> allDataRows_; // 当前 TM 一次取全的所有数据行(树形按根客户端分页用)
int dataRootsShown_ = 0; // 已 emit 的根节点数loadMoreData 续切)
};
} // namespace geopro::controller