feat(nav): ds数据/文件页签创建时间显示 + 加载更多分页(loadTmRows分页+total)
This commit is contained in:
parent
7cdc7b8077
commit
ee8342f4bf
|
|
@ -502,7 +502,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
|
|
||||||
// ── 单击左下数据列表的采集批次(DS) → 占位(真实剖面/反演渲染下一阶段接 dd 接口)──
|
// ── 单击左下数据列表的采集批次(DS) → 占位(真实剖面/反演渲染下一阶段接 dd 接口)──
|
||||||
QObject::connect(datasetList, &QListWidget::itemClicked, datasetList,
|
QObject::connect(datasetList, &QListWidget::itemClicked, datasetList,
|
||||||
[propLabel, detailRendererPtr, detailRenderWindowPtr](QListWidgetItem* item) {
|
[propLabel, detailRendererPtr, detailRenderWindowPtr, &nav](QListWidgetItem* item) {
|
||||||
|
if (item->data(geopro::app::kDsLoadMoreRole).toBool()) {
|
||||||
|
nav.loadMoreData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const QString name =
|
const QString name =
|
||||||
item->data(Qt::DisplayRole).toString().section('\n', 0, 0);
|
item->data(Qt::DisplayRole).toString().section('\n', 0, 0);
|
||||||
detailRendererPtr->RemoveAllViewProps();
|
detailRendererPtr->RemoveAllViewProps();
|
||||||
|
|
@ -617,6 +621,23 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 控制器 ↔ UI 信号接线(导航壳)──────────────────────────────────────
|
// ── 控制器 ↔ UI 信号接线(导航壳)──────────────────────────────────────
|
||||||
|
// "加载更多"行:列表末尾若已加载数 < 总数,放一行可点击的"加载更多(已/共)"。
|
||||||
|
auto removeLoadMore = [](QListWidget* lw) {
|
||||||
|
if (lw->count() > 0 &&
|
||||||
|
lw->item(lw->count() - 1)->data(geopro::app::kDsLoadMoreRole).toBool())
|
||||||
|
delete lw->takeItem(lw->count() - 1);
|
||||||
|
};
|
||||||
|
auto addLoadMore = [](QListWidget* lw, int total) {
|
||||||
|
const int loaded = lw->count();
|
||||||
|
if (loaded < total) {
|
||||||
|
auto* m = new QListWidgetItem(
|
||||||
|
QStringLiteral("加载更多(%1/%2)").arg(loaded).arg(total), lw);
|
||||||
|
m->setData(geopro::app::kDsLoadMoreRole, true);
|
||||||
|
m->setTextAlignment(Qt::AlignCenter);
|
||||||
|
m->setForeground(QColor("#2D6CB5"));
|
||||||
|
}
|
||||||
|
return loaded;
|
||||||
|
};
|
||||||
QObject::connect(topBar, &geopro::app::TopBar::workspaceSwitchRequested, &nav,
|
QObject::connect(topBar, &geopro::app::TopBar::workspaceSwitchRequested, &nav,
|
||||||
&geopro::controller::WorkbenchNavController::switchWorkspace);
|
&geopro::controller::WorkbenchNavController::switchWorkspace);
|
||||||
QObject::connect(topBar, &geopro::app::TopBar::projectSwitchRequested, &nav,
|
QObject::connect(topBar, &geopro::app::TopBar::projectSwitchRequested, &nav,
|
||||||
|
|
@ -643,19 +664,31 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
datasetTabs->setTabText(1, QStringLiteral("文件"));
|
datasetTabs->setTabText(1, QStringLiteral("文件"));
|
||||||
});
|
});
|
||||||
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::datasetsLoaded, datasetList,
|
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::datasetsLoaded, datasetList,
|
||||||
[datasetList, datasetTitle, datasetTabs](
|
[removeLoadMore, addLoadMore, datasetList, datasetTitle, datasetTabs](
|
||||||
const QString&, const std::vector<geopro::data::DsRow>& list) {
|
const QString&, const std::vector<geopro::data::DsRow>& rows, int total,
|
||||||
geopro::app::populateDatasetList(datasetList, list);
|
bool append) {
|
||||||
|
removeLoadMore(datasetList);
|
||||||
|
geopro::app::populateDatasetList(datasetList, rows, append);
|
||||||
|
const int loaded = addLoadMore(datasetList, total);
|
||||||
if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集显示栏"));
|
if (datasetTitle) datasetTitle->setText(QStringLiteral("数据集显示栏"));
|
||||||
datasetTabs->setTabText(
|
datasetTabs->setTabText(
|
||||||
0, QStringLiteral("数据 (%1)").arg(static_cast<int>(list.size())));
|
0, total > 0 ? QStringLiteral("数据 (%1/%2)").arg(loaded).arg(total)
|
||||||
|
: QStringLiteral("数据"));
|
||||||
});
|
});
|
||||||
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::filesLoaded, fileList,
|
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::filesLoaded, fileList,
|
||||||
[fileList, datasetTabs](const QString&,
|
[removeLoadMore, addLoadMore, fileList, datasetTabs](
|
||||||
const std::vector<geopro::data::DsRow>& list) {
|
const QString&, const std::vector<geopro::data::DsRow>& rows, int total,
|
||||||
geopro::app::populateFileList(fileList, list);
|
bool append) {
|
||||||
|
removeLoadMore(fileList);
|
||||||
|
geopro::app::populateFileList(fileList, rows, append);
|
||||||
|
const int loaded = addLoadMore(fileList, total);
|
||||||
datasetTabs->setTabText(
|
datasetTabs->setTabText(
|
||||||
1, QStringLiteral("文件 (%1)").arg(static_cast<int>(list.size())));
|
1, total > 0 ? QStringLiteral("文件 (%1/%2)").arg(loaded).arg(total)
|
||||||
|
: QStringLiteral("文件"));
|
||||||
|
});
|
||||||
|
QObject::connect(fileList, &QListWidget::itemClicked, fileList,
|
||||||
|
[&nav](QListWidgetItem* item) {
|
||||||
|
if (item->data(geopro::app::kDsLoadMoreRole).toBool()) nav.loadMoreFiles();
|
||||||
});
|
});
|
||||||
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::loadFailed, objectTree,
|
QObject::connect(&nav, &geopro::controller::WorkbenchNavController::loadFailed, objectTree,
|
||||||
[objectTree, &window](const QString& stage, const QString& msg) {
|
[objectTree, &window](const QString& stage, const QString& msg) {
|
||||||
|
|
|
||||||
|
|
@ -16,22 +16,25 @@ QString humanSize(long long b) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows) {
|
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append) {
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
list->clear();
|
if (!append) list->clear();
|
||||||
for (const auto& d : rows) {
|
for (const auto& d : rows) {
|
||||||
QString text = QString::fromStdString(d.dsName);
|
QString text = QString::fromStdString(d.dsName);
|
||||||
if (!d.typeName.empty()) text += QStringLiteral("\n%1").arg(QString::fromStdString(d.typeName));
|
QString sub = QString::fromStdString(d.createTime); // 名称下先创建时间
|
||||||
|
if (!d.typeName.empty())
|
||||||
|
sub += QStringLiteral(" · %1").arg(QString::fromStdString(d.typeName)); // 再跟类型
|
||||||
|
if (!sub.isEmpty()) text += QStringLiteral("\n%1").arg(sub);
|
||||||
auto* item = new QListWidgetItem(text, list);
|
auto* item = new QListWidgetItem(text, list);
|
||||||
item->setData(kDsIdRole, QString::fromStdString(d.id));
|
item->setData(kDsIdRole, QString::fromStdString(d.id));
|
||||||
item->setData(kDsDdTypeRole, QString::fromStdString(d.ddCode));
|
item->setData(kDsDdTypeRole, QString::fromStdString(d.ddCode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows) {
|
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append) {
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
list->clear();
|
if (!append) list->clear();
|
||||||
if (rows.empty()) {
|
if (!append && rows.empty()) {
|
||||||
auto* hint = new QListWidgetItem(QStringLiteral("(暂无文件)"), list);
|
auto* hint = new QListWidgetItem(QStringLiteral("(暂无文件)"), list);
|
||||||
hint->setFlags(Qt::NoItemFlags);
|
hint->setFlags(Qt::NoItemFlags);
|
||||||
hint->setForeground(QColor("#9AA6B6"));
|
hint->setForeground(QColor("#9AA6B6"));
|
||||||
|
|
@ -41,7 +44,9 @@ void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>&
|
||||||
for (const auto& d : rows) {
|
for (const auto& d : rows) {
|
||||||
const QString fname =
|
const QString fname =
|
||||||
d.fileName.empty() ? QString::fromStdString(d.dsName) : QString::fromStdString(d.fileName);
|
d.fileName.empty() ? QString::fromStdString(d.dsName) : QString::fromStdString(d.fileName);
|
||||||
const QString text = fname + QStringLiteral("\n%1").arg(humanSize(d.fileSize));
|
QString sub = QString::fromStdString(d.createTime); // 名称下先创建时间
|
||||||
|
sub += QStringLiteral(" · %1").arg(humanSize(d.fileSize)); // 再跟大小
|
||||||
|
const QString text = fname + QStringLiteral("\n%1").arg(sub);
|
||||||
auto* item = new QListWidgetItem(text, list);
|
auto* item = new QListWidgetItem(text, list);
|
||||||
item->setData(kDsIdRole, QString::fromStdString(d.id));
|
item->setData(kDsIdRole, QString::fromStdString(d.id));
|
||||||
item->setData(kDsFileUrlRole, QString::fromStdString(d.fileUrl));
|
item->setData(kDsFileUrlRole, QString::fromStdString(d.fileUrl));
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ namespace geopro::app {
|
||||||
constexpr int kDsIdRole = 0x0100; // Qt::UserRole
|
constexpr int kDsIdRole = 0x0100; // Qt::UserRole
|
||||||
constexpr int kDsDdTypeRole = 0x0101; // Qt::UserRole + 1
|
constexpr int kDsDdTypeRole = 0x0101; // Qt::UserRole + 1
|
||||||
constexpr int kDsFileUrlRole = 0x0102; // Qt::UserRole + 2(文件下载 url,备用)
|
constexpr int kDsFileUrlRole = 0x0102; // Qt::UserRole + 2(文件下载 url,备用)
|
||||||
|
constexpr int kDsLoadMoreRole = 0x0103; // 标记"加载更多"行
|
||||||
|
|
||||||
// 数据页签:每条 = dsName +(类型名);UserRole 存 dsId、+1 存 ddCode。
|
// 数据页签:每条 = dsName +(类型名);UserRole 存 dsId、+1 存 ddCode。
|
||||||
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows);
|
void populateDatasetList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append);
|
||||||
// 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。
|
// 文件页签:每条 = 文件名 +(可读大小);UserRole 存 dsId、+2 存文件 url。空时显示占位。
|
||||||
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows);
|
void populateFileList(QListWidget* list, const std::vector<geopro::data::DsRow>& rows, bool append);
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -106,20 +106,48 @@ void WorkbenchNavController::switchProject(const QString& projectId) {
|
||||||
void WorkbenchNavController::selectTm(const QString& tmObjectId) {
|
void WorkbenchNavController::selectTm(const QString& tmObjectId) {
|
||||||
if (tmObjectId.isEmpty() || busy_) return;
|
if (tmObjectId.isEmpty() || busy_) return;
|
||||||
BusyGuard guard(this, &busy_);
|
BusyGuard guard(this, &busy_);
|
||||||
|
currentTmId_ = tmObjectId.toStdString();
|
||||||
const std::string pid = currentProjectId_;
|
const std::string pid = currentProjectId_;
|
||||||
const std::string tm = tmObjectId.toStdString();
|
dataPageNo_ = 1;
|
||||||
const auto data = repo_.loadTmRows(pid, tm, 3); // 数据
|
filePageNo_ = 1;
|
||||||
if (!data.ok) {
|
const auto d = repo_.loadTmRows(pid, currentTmId_, 3, dataPageNo_);
|
||||||
emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(data.error));
|
if (!d.ok) {
|
||||||
|
emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit datasetsLoaded(tmObjectId, data.value);
|
dataTotal_ = d.value.total;
|
||||||
const auto files = repo_.loadTmRows(pid, tm, 1); // 文件
|
emit datasetsLoaded(tmObjectId, d.value.rows, d.value.total, false);
|
||||||
if (!files.ok) {
|
const auto f = repo_.loadTmRows(pid, currentTmId_, 1, filePageNo_);
|
||||||
emit loadFailed(QStringLiteral("files"), QString::fromStdString(files.error));
|
if (!f.ok) {
|
||||||
|
emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit filesLoaded(tmObjectId, files.value);
|
fileTotal_ = f.value.total;
|
||||||
|
emit filesLoaded(tmObjectId, f.value.rows, f.value.total, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkbenchNavController::loadMoreData() {
|
||||||
|
if (currentTmId_.empty() || busy_) return;
|
||||||
|
BusyGuard guard(this, &busy_);
|
||||||
|
const auto d = repo_.loadTmRows(currentProjectId_, currentTmId_, 3, ++dataPageNo_);
|
||||||
|
if (!d.ok) {
|
||||||
|
emit loadFailed(QStringLiteral("datasets"), QString::fromStdString(d.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dataTotal_ = d.value.total;
|
||||||
|
emit datasetsLoaded(QString::fromStdString(currentTmId_), d.value.rows, d.value.total, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkbenchNavController::loadMoreFiles() {
|
||||||
|
if (currentTmId_.empty() || busy_) return;
|
||||||
|
BusyGuard guard(this, &busy_);
|
||||||
|
const auto f = repo_.loadTmRows(currentProjectId_, currentTmId_, 1, ++filePageNo_);
|
||||||
|
if (!f.ok) {
|
||||||
|
emit loadFailed(QStringLiteral("files"), QString::fromStdString(f.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fileTotal_ = f.value.total;
|
||||||
|
emit filesLoaded(QString::fromStdString(currentTmId_), f.value.rows, f.value.total, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace geopro::controller
|
} // namespace geopro::controller
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,18 @@ 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 selectTm(const QString& tmObjectId);
|
||||||
|
void loadMoreData();
|
||||||
|
void loadMoreFiles();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void busyChanged(bool busy);
|
void busyChanged(bool busy);
|
||||||
void workspacesLoaded(const std::vector<geopro::data::Workspace>& list, const QString& currentId);
|
void workspacesLoaded(const std::vector<geopro::data::Workspace>& list, const QString& currentId);
|
||||||
void projectsLoaded(const std::vector<geopro::data::ProjectSummary>& list, const QString& currentId);
|
void projectsLoaded(const std::vector<geopro::data::ProjectSummary>& list, const QString& currentId);
|
||||||
void structureLoaded(const QString& projectName, const std::vector<geopro::data::StructNode>& nodes);
|
void structureLoaded(const QString& projectName, const std::vector<geopro::data::StructNode>& nodes);
|
||||||
void datasetsLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& list);
|
void datasetsLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows,
|
||||||
void filesLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& list);
|
int total, bool append);
|
||||||
|
void filesLoaded(const QString& tmObjectId, const std::vector<geopro::data::DsRow>& rows,
|
||||||
|
int total, bool append);
|
||||||
void loadFailed(const QString& stage, const QString& message);
|
void loadFailed(const QString& stage, const QString& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -39,6 +43,11 @@ 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_;
|
||||||
|
int dataPageNo_ = 0;
|
||||||
|
int filePageNo_ = 0;
|
||||||
|
int dataTotal_ = 0;
|
||||||
|
int fileTotal_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace geopro::controller
|
} // namespace geopro::controller
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,9 @@ RepoResult<std::vector<StructNode>> ApiProjectRepository::loadStructure(const st
|
||||||
return {true, dto::parseStructNodes(r.data.value(QStringLiteral("value")).toArray()), {}};
|
return {true, dto::parseStructNodes(r.data.value(QStringLiteral("value")).toArray()), {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
RepoResult<std::vector<DsRow>> ApiProjectRepository::loadTmRows(const std::string& projectId,
|
RepoResult<DsPage> ApiProjectRepository::loadTmRows(const std::string& projectId,
|
||||||
const std::string& tmObjectId,
|
const std::string& tmObjectId, int classifyType,
|
||||||
int classifyType) {
|
int pageNo) {
|
||||||
const QString path = (classifyType == 1) ? QStringLiteral("/business/dsObject/file/page")
|
const QString path = (classifyType == 1) ? QStringLiteral("/business/dsObject/file/page")
|
||||||
: QStringLiteral("/business/dsObject/data/page");
|
: QStringLiteral("/business/dsObject/data/page");
|
||||||
const QJsonObject body{
|
const QJsonObject body{
|
||||||
|
|
@ -73,11 +73,11 @@ RepoResult<std::vector<DsRow>> ApiProjectRepository::loadTmRows(const std::strin
|
||||||
{QStringLiteral("structParentId"), QString::fromStdString(tmObjectId)},
|
{QStringLiteral("structParentId"), QString::fromStdString(tmObjectId)},
|
||||||
{QStringLiteral("structParentConfType"), 2},
|
{QStringLiteral("structParentConfType"), 2},
|
||||||
{QStringLiteral("classifyTypeList"), QJsonArray{classifyType}},
|
{QStringLiteral("classifyTypeList"), QJsonArray{classifyType}},
|
||||||
{QStringLiteral("pageNo"), 1},
|
{QStringLiteral("pageNo"), pageNo},
|
||||||
{QStringLiteral("pageSize"), 100}};
|
{QStringLiteral("pageSize"), 100}};
|
||||||
const net::ApiResponse r = api_.postJson(path, body);
|
const net::ApiResponse r = api_.postJson(path, body);
|
||||||
if (!ok(r)) return {false, {}, errorOf(r, "loadTmRows failed")};
|
if (!ok(r)) return {false, {}, errorOf(r, "loadTmRows failed")};
|
||||||
return {true, dto::parseDsRows(r.data.value(QStringLiteral("list")).toArray()), {}};
|
return {true, dto::parseDsPage(r.data), {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace geopro::data
|
} // namespace geopro::data
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,8 @@ public:
|
||||||
RepoResult<bool> switchWorkspace(const std::string& tenantId) override;
|
RepoResult<bool> switchWorkspace(const std::string& tenantId) override;
|
||||||
RepoResult<std::vector<ProjectSummary>> listProjects(const std::string& lastProjectId) override;
|
RepoResult<std::vector<ProjectSummary>> listProjects(const std::string& lastProjectId) override;
|
||||||
RepoResult<std::vector<StructNode>> loadStructure(const std::string& projectId) override;
|
RepoResult<std::vector<StructNode>> loadStructure(const std::string& projectId) override;
|
||||||
RepoResult<std::vector<DsRow>> loadTmRows(const std::string& projectId,
|
RepoResult<DsPage> loadTmRows(const std::string& projectId, const std::string& tmObjectId,
|
||||||
const std::string& tmObjectId,
|
int classifyType, int pageNo) override;
|
||||||
int classifyType) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
net::ApiClient& api_;
|
net::ApiClient& api_;
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ std::vector<DsRow> parseDsRows(const QJsonArray& arr) {
|
||||||
d.dsName = str(o, "dsName");
|
d.dsName = str(o, "dsName");
|
||||||
d.typeName = str(o, "name"); // 注意:name 字段=ds类型名
|
d.typeName = str(o, "name"); // 注意:name 字段=ds类型名
|
||||||
d.ddCode = str(o, "ddCode");
|
d.ddCode = str(o, "ddCode");
|
||||||
|
d.createTime = str(o, "createTime");
|
||||||
const QJsonObject f = o.value(QStringLiteral("file")).toObject();
|
const QJsonObject f = o.value(QStringLiteral("file")).toObject();
|
||||||
d.fileName = str(f, "name");
|
d.fileName = str(f, "name");
|
||||||
d.fileUrl = str(f, "url");
|
d.fileUrl = str(f, "url");
|
||||||
|
|
@ -91,6 +92,13 @@ std::vector<DsRow> parseDsRows(const QJsonArray& arr) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DsPage parseDsPage(const QJsonObject& data) {
|
||||||
|
DsPage p;
|
||||||
|
p.rows = parseDsRows(data.value(QStringLiteral("list")).toArray());
|
||||||
|
p.total = data.value(QStringLiteral("total")).toInt();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<StructTreeNode> buildStructTree(const std::vector<StructNode>& flat) {
|
std::vector<StructTreeNode> buildStructTree(const std::vector<StructNode>& flat) {
|
||||||
// 过滤 DS(type==3):DS 不进对象树(按 TM 单独拉取到数据列表)。
|
// 过滤 DS(type==3):DS 不进对象树(按 TM 单独拉取到数据列表)。
|
||||||
std::vector<StructNode> nodes;
|
std::vector<StructNode> nodes;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ std::vector<StructNode> parseStructNodes(const QJsonArray& arr);
|
||||||
// data/page / file/page 的 data["list"] 数组 → DsRow(数据行无 file;文件行含 file{name,size,url})。
|
// data/page / file/page 的 data["list"] 数组 → DsRow(数据行无 file;文件行含 file{name,size,url})。
|
||||||
std::vector<DsRow> parseDsRows(const QJsonArray& arr);
|
std::vector<DsRow> parseDsRows(const QJsonArray& arr);
|
||||||
|
|
||||||
|
// data/page 或 file/page 的整个 data 对象 → DsPage(rows + total)。
|
||||||
|
DsPage parseDsPage(const QJsonObject& data);
|
||||||
|
|
||||||
// 扁平 StructNode 按 parentId 建树。叶子(无子节点)=TM。处理:项目直挂 TM、孤儿 parentId、空表。
|
// 扁平 StructNode 按 parentId 建树。叶子(无子节点)=TM。处理:项目直挂 TM、孤儿 parentId、空表。
|
||||||
struct StructTreeNode {
|
struct StructTreeNode {
|
||||||
StructNode node;
|
StructNode node;
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ public:
|
||||||
virtual RepoResult<bool> switchWorkspace(const std::string& tenantId) = 0;
|
virtual RepoResult<bool> switchWorkspace(const std::string& tenantId) = 0;
|
||||||
virtual RepoResult<std::vector<ProjectSummary>> listProjects(const std::string& lastProjectId) = 0;
|
virtual RepoResult<std::vector<ProjectSummary>> listProjects(const std::string& lastProjectId) = 0;
|
||||||
virtual RepoResult<std::vector<StructNode>> loadStructure(const std::string& projectId) = 0;
|
virtual RepoResult<std::vector<StructNode>> loadStructure(const std::string& projectId) = 0;
|
||||||
// 按 TM 拉数据集/文件行:classifyType 3=数据(data/page) 1=文件(file/page)。
|
// 按 TM 分页拉数据/文件行:classifyType 3=数据 1=文件;pageNo 从 1 起,pageSize 固定 100。
|
||||||
virtual RepoResult<std::vector<DsRow>> loadTmRows(const std::string& projectId,
|
virtual RepoResult<DsPage> loadTmRows(const std::string& projectId,
|
||||||
const std::string& tmObjectId,
|
const std::string& tmObjectId, int classifyType,
|
||||||
int classifyType) = 0;
|
int pageNo) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace geopro::data
|
} // namespace geopro::data
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,11 @@ struct DsNode { std::string id, name, ddType; };
|
||||||
|
|
||||||
// data/page 或 file/page 的一条 ds。数据行只用 dsName/typeName/ddCode;文件行另含 file*。
|
// data/page 或 file/page 的一条 ds。数据行只用 dsName/typeName/ddCode;文件行另含 file*。
|
||||||
struct DsRow {
|
struct DsRow {
|
||||||
std::string id, dsName, typeName, ddCode;
|
std::string id, dsName, typeName, ddCode, createTime;
|
||||||
std::string fileName, fileUrl;
|
std::string fileName, fileUrl;
|
||||||
long long fileSize = 0;
|
long long fileSize = 0;
|
||||||
};
|
};
|
||||||
|
struct DsPage { std::vector<DsRow> rows; int total = 0; };
|
||||||
struct TmNode { std::string id, name, confCode; std::vector<DsNode> dss; };
|
struct TmNode { std::string id, name, confCode; std::vector<DsNode> dss; };
|
||||||
struct GsNode { std::string id, name; std::vector<TmNode> tms; };
|
struct GsNode { std::string id, name; std::vector<TmNode> tms; };
|
||||||
struct Project { std::string id, name; std::vector<GsNode> gss; };
|
struct Project { std::string id, name; std::vector<GsNode> gss; };
|
||||||
|
|
|
||||||
|
|
@ -147,12 +147,13 @@ TEST(NavDto, BuildStructTreeDropsDsAndTmStaysLeaf) {
|
||||||
|
|
||||||
TEST(NavDto, ParseDsRowsDataAndFile) {
|
TEST(NavDto, ParseDsRowsDataAndFile) {
|
||||||
const auto d = dto::parseDsRows(arrOf(R"([
|
const auto d = dto::parseDsRows(arrOf(R"([
|
||||||
{"id":"d1","dsName":"ERT1-WS","name":"电阻率数据","ddCode":"dd_inversion_data"}
|
{"id":"d1","dsName":"ERT1-WS","name":"电阻率数据","ddCode":"dd_inversion_data","createTime":"2026-03-25 16:48:57"}
|
||||||
])"));
|
])"));
|
||||||
ASSERT_EQ(d.size(), 1u);
|
ASSERT_EQ(d.size(), 1u);
|
||||||
EXPECT_EQ(d[0].id, "d1");
|
EXPECT_EQ(d[0].id, "d1");
|
||||||
EXPECT_EQ(d[0].dsName, "ERT1-WS");
|
EXPECT_EQ(d[0].dsName, "ERT1-WS");
|
||||||
EXPECT_EQ(d[0].typeName, "电阻率数据");
|
EXPECT_EQ(d[0].typeName, "电阻率数据");
|
||||||
|
EXPECT_EQ(d[0].createTime, "2026-03-25 16:48:57");
|
||||||
EXPECT_TRUE(d[0].fileName.empty());
|
EXPECT_TRUE(d[0].fileName.empty());
|
||||||
|
|
||||||
const auto f = dto::parseDsRows(arrOf(R"([
|
const auto f = dto::parseDsRows(arrOf(R"([
|
||||||
|
|
@ -163,4 +164,12 @@ TEST(NavDto, ParseDsRowsDataAndFile) {
|
||||||
EXPECT_EQ(f[0].fileName, "ERT1-WS.xlsx");
|
EXPECT_EQ(f[0].fileName, "ERT1-WS.xlsx");
|
||||||
EXPECT_EQ(f[0].fileSize, 62760);
|
EXPECT_EQ(f[0].fileSize, 62760);
|
||||||
EXPECT_EQ(f[0].fileUrl, "/common/file/x.xlsx");
|
EXPECT_EQ(f[0].fileUrl, "/common/file/x.xlsx");
|
||||||
|
|
||||||
|
const auto page = dto::parseDsPage(objOf(R"({
|
||||||
|
"total": 18,
|
||||||
|
"list": [{"id":"x","dsName":"a","name":"t","ddCode":"dd","createTime":"2026-01-01 00:00:00"}]
|
||||||
|
})"));
|
||||||
|
EXPECT_EQ(page.total, 18);
|
||||||
|
ASSERT_EQ(page.rows.size(), 1u);
|
||||||
|
EXPECT_EQ(page.rows[0].dsName, "a");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue