105 lines
5.8 KiB
C++
105 lines
5.8 KiB
C++
#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_; // selectObject:data 行
|
||
QPointer<data::NavRequest> selFileReq_; // selectObject:file 行
|
||
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
|