fix(data): 装置筛选空-parseDsRows 兼容对象形态 properties+顶层装置字段 + CLAUDE规则
诊断(自读日志[arrayfilter]):enum=15(枚举正常)但 row0[](行 properties 空)→装置值没进 row.properties。 DsObjectDataVO.properties 是泛型 JSON(可能对象而非数组),旧 parseDsRows 只 toArray()→对象形态丢空。 修:properties 数组/对象两种形态都解析;顶层 arrayType/arrayTypeName 也收为属性兜底。 另加 [dsrow-raw] 一次性打印首行原始 JSON,若仍空可据此精准定位装置字段实际位置。 生成位置下拉:combo 自身按内容加宽(对话框随之变宽)→ popup 宽=combo 宽,不再外溢出对话框。 CLAUDE.md:新增「能自己做的绝不让用户做」绑定规则——日志/数据/构建/诊断都自己来,只在 LNK1104 需关 app、或真正产品决策时才找用户。
This commit is contained in:
parent
98bbc9f947
commit
1742b7508b
|
|
@ -49,6 +49,15 @@ as a reason to leave it. Surface it, then handle it. (User directive, 2026-06-25
|
|||
This overrides the "don't fix what isn't broken" bias above *for genuine defects* — it does
|
||||
not license cosmetic refactors or unrequested rewrites.
|
||||
|
||||
**Do it yourself — never offload work you can do (User directive, 2026-06-25, binding):**
|
||||
If you have the tools to do something, DO IT — never tell the user to do it for you.
|
||||
Read the logs yourself (`%LOCALAPPDATA%/Geomative/Geopro3/logs/geopro_*.log` via Bash/grep),
|
||||
inspect data/fixtures yourself, build and link yourself (`build.bat app` via PowerShell),
|
||||
diagnose by adding logging and then reading that log yourself. The ONLY things to ask the
|
||||
user for are: (a) closing a running app so the exe can relink (LNK1104 — a lock only they can
|
||||
release), and (b) genuine product decisions. Do not ask the user to read logs, inspect data,
|
||||
run diagnostics, or interpret output — that is your job.
|
||||
|
||||
## 4. Goal-Driven Execution
|
||||
|
||||
**Define success criteria. Loop until verified.**
|
||||
|
|
|
|||
|
|
@ -143,13 +143,16 @@ VolumeParamsDialog::VolumeParamsDialog(const QVector<VolumeSourceItem>& sources,
|
|||
mount_->setModel(model);
|
||||
mount_->setView(view);
|
||||
view->expandAll();
|
||||
// 下拉面板加宽:默认只取 combo 宽度+缩进 → 长名被截。按最长节点名的文本宽 + 缩进/箭头/滚动条余量
|
||||
// 定最小宽,保证 GS/TM 全名可见(用户反馈被遮住)。
|
||||
// 关键:让 combo **自身**按内容加宽(对话框随布局一起变宽)→ popup 宽 = combo 宽,落在对话框内
|
||||
// 不外溢;只加宽 popup 而不加宽 combo 会让浮窗比对话框还宽、超出右缘(用户反馈)。
|
||||
// 宽度 = 最长节点名文本宽 + 余量(树缩进/展开箭头/滚动条/combo 下拉箭头/内距)。
|
||||
int maxTextW = 0;
|
||||
const QFontMetrics fm = view->fontMetrics();
|
||||
for (const auto& n : structure)
|
||||
maxTextW = std::max(maxTextW, fm.horizontalAdvance(QString::fromStdString(n.name)));
|
||||
view->setMinimumWidth(std::max(geopro::app::scaledPx(260), maxTextW + geopro::app::scaledPx(120)));
|
||||
const int contentW = std::max(geopro::app::scaledPx(200), maxTextW + geopro::app::scaledPx(80));
|
||||
mount_->setMinimumWidth(contentW); // combo 加宽 → 对话框变宽
|
||||
view->setMinimumWidth(contentW); // popup 与 combo 同宽 → 不外溢
|
||||
// 默认选中:指定的 defaultMountId,否则首个节点。view 当前项决定 mountTargetId;combo 显示尽力。
|
||||
QStandardItem* def = mItems.value(defaultMountId, nullptr);
|
||||
if (!def && model->rowCount() > 0) def = model->item(0);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "dto/NavDto.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonValue>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
|
@ -116,6 +118,13 @@ std::vector<StructNode> parseStructNodes(const QJsonArray& arr) {
|
|||
std::vector<DsRow> parseDsRows(const QJsonArray& arr) {
|
||||
std::vector<DsRow> out;
|
||||
out.reserve(static_cast<size_t>(arr.size()));
|
||||
// 诊断(一次):打印首行原始 JSON,定位装置/采集时间等字段实际所在(properties 形态/attachedParameters)。
|
||||
static bool s_loggedRaw = false;
|
||||
if (!s_loggedRaw && !arr.isEmpty()) {
|
||||
s_loggedRaw = true;
|
||||
qInfo().noquote() << "[dsrow-raw]"
|
||||
<< QJsonDocument(arr.first().toObject()).toJson(QJsonDocument::Compact);
|
||||
}
|
||||
for (const QJsonValue& v : arr) {
|
||||
const QJsonObject o = v.toObject();
|
||||
DsRow d;
|
||||
|
|
@ -130,15 +139,31 @@ std::vector<DsRow> parseDsRows(const QJsonArray& arr) {
|
|||
d.dsTypeCode = str(o, "dsTypeCode");
|
||||
d.structParentId = str(o, "structParentId");
|
||||
d.structParentConfType = o.value(QStringLiteral("structParentConfType")).toInt();
|
||||
// properties[] = [{confFieldId,value}](value 用 toVariant().toString() 兼容字符串/数值/时间,
|
||||
// 与 parseDynamicForm 同口径);非数组形态(文件型 ds)安全返回空。
|
||||
const QJsonArray props = o.value(QStringLiteral("properties")).toArray();
|
||||
d.properties.reserve(static_cast<size_t>(props.size()));
|
||||
for (const QJsonValue& pv : props) {
|
||||
const QJsonObject po = pv.toObject();
|
||||
d.properties.push_back(
|
||||
{str(po, "confFieldId"), po.value(QStringLiteral("value")).toVariant().toString().toStdString()});
|
||||
// properties 后端是泛型 JSON:可能是数组 [{confFieldId,value}] 或对象 {confFieldId:value}。两种都解析
|
||||
// (历史只 toArray()→对象形态时丢空,导致装置/采集时间取不到,装置下拉空,用户实测)。
|
||||
const QJsonValue propsV = o.value(QStringLiteral("properties"));
|
||||
if (propsV.isArray()) {
|
||||
const QJsonArray props = propsV.toArray();
|
||||
d.properties.reserve(static_cast<size_t>(props.size()));
|
||||
for (const QJsonValue& pv : props) {
|
||||
const QJsonObject po = pv.toObject();
|
||||
d.properties.push_back({str(po, "confFieldId"),
|
||||
po.value(QStringLiteral("value")).toVariant().toString().toStdString()});
|
||||
}
|
||||
} else if (propsV.isObject()) {
|
||||
const QJsonObject po = propsV.toObject();
|
||||
for (auto it = po.begin(); it != po.end(); ++it)
|
||||
d.properties.push_back(
|
||||
{it.key().toStdString(), it.value().toVariant().toString().toStdString()});
|
||||
}
|
||||
// 装置类型也可能是顶层字段(arrayType 代码 / arrayTypeName 中文名)→ 同时收为属性,兜底供筛选匹配。
|
||||
if (o.contains(QStringLiteral("arrayType")))
|
||||
d.properties.push_back(
|
||||
{"arrayType", o.value(QStringLiteral("arrayType")).toVariant().toString().toStdString()});
|
||||
if (o.contains(QStringLiteral("arrayTypeName")))
|
||||
d.properties.push_back(
|
||||
{"arrayTypeName",
|
||||
o.value(QStringLiteral("arrayTypeName")).toVariant().toString().toStdString()});
|
||||
const QJsonObject f = o.value(QStringLiteral("file")).toObject();
|
||||
d.fileName = str(f, "name");
|
||||
d.fileUrl = str(f, "url");
|
||||
|
|
|
|||
Loading…
Reference in New Issue