26 KiB
交接文档:数据集详情图表 + 全 App 网络层异步化
给下一个会话:读完本文件即可无缝接手。最后更新 2026-06-12。 分支
feat/dataset-detail-chart,领先 main 68 commits。测试 122/122 全绿。 ⚠️ 工作区脏:sessions 0.1–0.5 的代码(散点 hover/日志崩溃捕获/colormap/数据集树/按根分页/暗色主题)全部未提交(用户多次选「保持现状」不提交不合并)。git status一大堆 M/??,别假设干净树;接手前先git status看清。新增未跟踪文件:src/app/Logging.*、src/app/panels/chart/{ScatterHoverTip,ChartTheme}.*、tests/app/test_scatter_hover.cpp,以及若干*.jpeg/*.yml临时抓图/抓取产物(非源码,可忽略/清理)。
0. 一句话现状
geopro(Qt6/C++ 离线桌面客户端,1:1 复刻赛盈地空 web)已完成两大块:
- 数据集详情图表(仅 ERT 反演
dd_inversion_data,QwtPlot 落地,用户已验收)。 - 全 App 网络层 100% 异步化(详情/导航/登录/项目列表全异步,同步
QEventLoop阻塞路径已彻底删除,无技术债)。
均未合并入 main,分支挂起等收尾。
0.1 2026-06-12 渲染保真修复(本次会话)
用户报客户端散点/网格颜色与原版差异大(大量点透明发白、图例只有 6 色 + 白缝)、散点缺 hover。经 Playwright 抓原版真实 API + 读源码定位为通用根因:
- colorBar alpha 标度 bug(核心):
lvl/colorGradation/getDetail返回的 colorBar 是混合格式——hex#00008B与 CSSrgba(0, 0, 170, 1)(alpha 是 0–1 浮点),共 18 段。DatasetChartDto.cpp用AlphaScale::Bit255解析 → rgba 的a=1被当字节 → alpha≈1/255 近透明(12 个 rgba 段全成白缝;6 个 hex 段因 hex 分支强制 255 才可见)。修复:Bit255→Unit(一行)。散点连续插值ColorMapService的归一化位置val/maxVal已证精确等于原版 Plotly colorscale 位置,无需改。 - 散点 hover:新增
ScatterHoverTip(canvas 事件过滤器,与 LivePanner 共存),最近点命中显示X/Y/值(各 3 位小数,对齐原版 Plotly hovertemplate<b>X:</b> %{x:.3f}…)。 - 文件:改
src/data/dto/DatasetChartDto.cpp;新增src/app/panels/chart/ScatterHoverTip.{hpp,cpp}+ 接线RawDataChartView.{hpp,cpp};测试tests/data/test_dataset_chart_dto.cpp(改用真实混合格式 + 断言 alpha=255 回归)、新增tests/app/test_scatter_hover.cpp。测试 116→118 全绿,cpp-reviewer APPROVE。 - ⚠️ 像素级视觉 1:1 待用户在运行的 app 内登录核对(原生 Qt 窗口无法用 Playwright 驱动;以下各层已机器验证:抓包/源码/RED-GREEN/插值位置匹配)。
- 观察(未改,待定):图例
ColorBarWidget画stops-1=17段,丢弃最后一段最深色;原版疑为 18 段。非本次报障,留待用户决定是否补齐。
0.2 2026-06-12 第二轮修复(散点 cauto 归一化 + hover mouseTracking + 页签名)
第一轮 alpha 修复后颜色不再透明,但散点仍与原版不一致(挤在暖色中段、无蓝无紫)。复查 Plotly _fullData:散点 cmin/cmax 未设 → cauto 自动取 vlist 实际 min/max(本例 45.93–197.79),把整段色阶铺满数据范围;而客户端 ColorMapService 错用 colorBar 全程 0–1323 归一化数据 → 压进色阶 0.03–0.15 段。
- 修复 A(散点 cauto):
ColorMapService.setDataRange(dataMin,dataMax)解耦「色阶形状位置(按断点值)」与「数据值归一化(按数据 min/max)」;RawDataChartView::setData按d.scatter.v有限值 min/max 调用。数值验证 1:1:手算修复后客户端对样本值的 RGB 与原版 Plotly 实测逐字节相同(如中位 92.01→[168,0,35]、62.34→[255,119,0])。网格仍用绝对阈值(colorAtDiscrete),不变。 - 修复 B(hover 仍无效):根因
QwtPlotCanvas默认不开 mouseTracking → 无按键时收不到 MouseMove。ScatterHoverTip构造里加canvas->setMouseTracking(true)。 - 修复 C(页签用数据名):
ChartData加dsName;openDataset加可选第 3 参dsName(默认空,向后兼容测试);kDsNameRole存 dsName,main.cpp双击传入,DatasetDetailPaneladdTab用dsName(空回退 dsId)+ tooltip。 - 文件:
ColorMapService.{hpp,cpp}、RawDataChartView.cpp、ScatterHoverTip.cpp、DatasetDetailController.{hpp,cpp}、DatasetListPanel.{hpp,cpp}、DatasetDetailPanel.cpp、main.cpp;测试test_colormap_service.cpp(+DataRangeDecouples)。119/119 全绿。 - ⚠️ hover/页签名/视觉仍待用户运行核对(GUI 无法自动驱动)。
0.3 2026-06-12 桌面端日志 + 崩溃捕获(新基础设施)
用户反馈:双击 ds 后状态栏报「内部系统错误」然后客户端崩溃;后端错误可接受,但客户端不该崩。复测发现 scatter/color 接口当时其实 200/干净数据 → 无日志根本无从定位。遂加生产级日志 + 崩溃捕获(已实测打通)。
src/app/Logging.{hpp,cpp}:initLogging()(main.cpp 在 setApplicationName 后调用)。qInstallMessageHandler接管全 AppqDebug/qInfo/qWarning/qCritical/qFatal→ 写带时间戳/级别的滚动日志:%LOCALAPPDATA%/Geomative/Geopro3/logs/geopro_YYYYMMDD.log(按天,UTF-8+BOM,启动清理 14 天前旧文件)。- 崩溃捕获:
SetUnhandledExceptionFilter(SEH,含未捕获 C++ 异常 0xE06D7363)+std::set_terminate;崩溃时MiniDumpWriteDump写crash_*.dmp(链Dbghelp)+ 记一行[FATAL] 崩溃 code=… addr=… dump=…。SetErrorMode抑制系统弹窗。已用临时 env 自检实测:空指针崩溃 → 生成 6MB dmp + 日志记录 code=0xc0000005(自检块已删)。 - dmp 可 VS/WinDbg 加载看完整调用栈。
- 埋点:
ApiCall::onFinished记录每个 API 响应(URL/http/code/err,成功 INFO/失败 WARN);DatasetDetailControlleropenDataset + 各 loadFailed;App 启动版本/路径。net 层qWarning自动收录。 - 顺带堵崩溃根因(评审 H-2 + 防脏数据):
ColorMapService::colorAtContinuous对 NaN/Inf 的 t 回退首断点色(原会upper_bound返回 end() 后解引用越界崩溃);RawDataChartViewvlist min/max 用isfinite跳过 NaN/±Inf。+ 单测ColorAtContinuousNaNSafe。 - 测试 119→120 全绿。
0.4 2026-06-12 崩溃定位 + 顶层异常护栏
用户提供 dump + log。日志序列:openDataset(ERT2-WS_result.dat) → dynamicForm 后端返回 code=500 sys.internalServerError(即"内部系统错误")→ scatter 200 → color 200 → Qt has caught an exception thrown from an event handler → 崩溃。
dump 分析(winget 装 Microsoft.WinDbg,!analyze -v):异常 e06d7363(C++ EH),栈 VCRUNTIME140!CxxThrowException ← msvcp140!std::_Xlength_error ← geopro_desktop+0x9ad0 ← +0xa94ee ← +0x24b71 ← +0x235c0。即 std::length_error(STL 容器/字符串用非法 size resize/reserve/构造)。栈帧都在 geopro_desktop(含静态链接的 Qwt),但该 dump 是旧构建、当前 PDB 已不匹配 → 符号化不出函数名。静态排查 dynamicForm 解析 / DynamicFormView / selectDataset 失败路径 / 散点解析(已 try/catch) / 渲染 / ColorMapService 均未见明显抛点 → 确切行待运行期护栏日志点名。
修复(主,根治"不该崩"):main.cpp 加 GuardedApplication : QApplication,override notify() try/catch:任何 slot/事件处理器抛出的异常被拦截 + qCritical 记录 [guard] 拦截... what | type | receiver=<对象类名> | event=<事件类型>,然后吞掉(不终止)。后端故障等异常不再使整个客户端退出。
附带:修 appendCrashLine 文件共享 bug(崩溃行原写不进日志——g_logFile 独占,第二句柄 open 失败;改为复用已打开句柄);colorAtContinuous NaN/Inf 守卫。
护栏实测:用户复现,护栏拦到 → 日志 [guard] 拦截未捕获异常: vector too long | type=std::length_error | receiver=QNetworkReplyHttpImpl | event=43(MetaCall)。即异常在网络响应 finished 同步链里(最后一个 chart 请求 color 返回 → chartReady→openOrUpdate→渲染)抛出 std::length_error("vector too long" = std::vector 用了非法尺寸,典型负数转 size_t)。进程未崩(护栏吞掉),但图表没渲染出来。
诊断基础设施(关键补强):
- Release 构建之前不生成 PDB → dump/崩溃栈对自家代码全部符号化失败(只有系统 DLL 导出表能解析)。已在根
CMakeLists.txtMSVC 块加/Zi(编译) +/DEBUG /OPT:REF /OPT:ICF(链接):Release 保持优化的同时产出匹配 PDB。生产桌面端排障必需。 - VEH 抛点堆栈符号化(
Logging.cpp):AddVectoredExceptionHandler在 C++ 异常(0xE06D7363)抛出瞬间(栈未展开、PDB 匹配)用 DbgHelp(SymInitialize+SymLoadModuleExW+SymFromAddrW+SymGetLineFromAddrW64,宽字符——UNICODE 下必须)打印模块+RVA 函数名+偏移 (文件:行)。自测验证:reserve(-1)→ 正确打印geopro::app::initLogging (Logging.cpp:245)。即使异常被护栏吞掉也留下抛点栈。
下一步定位 length_error 确切行:用当前构建复现一次 → 日志 [THROW] 段直接给出 geopro::app::<类>::<方法> (文件:行)。测试 120/120 全绿。
0.5 2026-06-12 数据集列表树化 + 按根分页 + 暗色主题保真(本次会话)
用户三组报障,均已修复、构建链接通过、应用真实流程跑通无崩溃、测试 120→122 全绿:
(1) 数据集列表应是树(原为平铺)
- 实地确认(铁律 Playwright):原版「数据管理」选 TM 后的数据列表是 el-table tree-data(有展开箭头)。脚本直连 API 验证 TM E3(项目 1458977804960256 垃圾掩埋場):10 个 DS → 4 个根(默认折叠)= 3×源「ERT原始数据」+ 1×「ERT电极坐标」;派生「反演/接地电阻」按
parentId(==sourceShowParentId)挂源「原始数据」下。根 = parentId 为空或指向不在本批的「源文件节点」。 - 改:
DsRow加parentId;NavDto::parseDsRows解析sourceShowParentId(回退parentId);DatasetListPanel::populateDatasetList由QListWidget改建QTreeWidget(两遍法按 parentId 嵌套,卡片委托applyDatasetCardDelegate泛化到QAbstractItemView);main.cppdatasetList改QTreeWidget(setExpandsOnDoubleClick(false):双击=开详情、展开靠箭头),点击/双击/反向高亮/加载更多 4 处改QTreeWidgetAPI。文件页签仍平铺QListWidget。默认折叠(对齐原版)。 - 测试:
test_nav_dto.cpp::ParseDsRowsParentIdForTree。
(2) 分页应按「第一层节点(根)」算(原按扁平 DS)
- 根因:后端
dsObject/data/page按扁平 DS 分页(脚本验证:total=10、pageSize=5 返回 5 条扁平行)——子节点的父常落在下一页 → 按页建树出孤儿根、首层数错乱。 - 改:
IAsyncProjectRepository::loadRowsAsync加int pageSize=5参数(接口/ApiProjectRepository/测试 stub 同步);WorkbenchNavController::selectObject数据页改用大 pageSize(kFetchAllPageSize=1000)一次取全整棵,缓存allDataRows_;新私有emitNextDataRootPage(bool append)客户端按根切页(每页kDataRootPageSize=5个根 + 各自整棵子树,DFS 收集后按原序输出,total=根总数);loadMoreData改同步切下一页(无请求);dataRootsShown_游标,resetSelectionState清空。删因此空置的moreDataReq_。main.cppaddTreeLoadMore计数改按顶层根。若listCount<total(pageSize 不足取全)qWarning告警。 - 测试:
test_workbench_nav_controller.cpp::DataPaginatesByRootNodeNotFlatCount(6 根→首页 5 根+子=7 行/total=6,续页第 6 根;用qRegisterMetaType<std::vector<DsRow>>读 spy 行参)。
(3) 暗色主题图表样式未跟随
- 原详情图
QwtPlot、ColorBarWidget、LoadingOverlay全硬编码白底/浅色 → 暗色主题下刺眼白底/白蒙板。原版 web 无暗色,故暗色为客户端自定:浅色分支保持原硬编码值=与原版 1:1 不动,仅暗色改 token。 - 新增
src/app/panels/chart/ChartTheme.{hpp,cpp}applyChartPlotTheme(QwtPlot*):按isDarkTheme()设画布底色(bg/panel)/轴字(text/secondary)/网格(border/default)/零线(border/strong),遍历 itemList 重着色 grid/marker。Raw/GridDataChartView删硬编码白块、ctor 末尾调用 + 连ThemeManager::changed热切换。 ColorBarWidget::paintEvent底色/边框/刻度字按isDarkTheme()(暗色bg/panel/border/strong/text/secondary;色带格=数据色不变)+ ctor 连 changed→update。LoadingOverlay遮罩纱色由rgba(255,255,255,160)改按主题(暗色bg/app深纱)+ label 文字text/primary,连 changed 热切换。- token 表见
src/app/Theme.cpp(bg/panel白/#161A20、text/secondary、border/*)。
新文件:src/app/panels/chart/ChartTheme.{hpp,cpp}(已加 src/app/CMakeLists.txt)。
改动文件:RepoTypes.hpp、NavDto.cpp、IAsyncProjectRepository.hpp、ApiProjectRepository.{hpp,cpp}、WorkbenchNavController.{hpp,cpp}、DatasetListPanel.{hpp,cpp}、main.cpp、RawDataChartView.cpp、GridDataChartView.cpp、ColorBarWidget.cpp、LoadingOverlay.cpp、src/app/CMakeLists.txt、tests/{data/test_nav_dto,controller/test_workbench_nav_controller}.cpp。
记忆新增:dataset-list-is-tree(树结构 + 扁平分页坑 + 按根分页解法 + 暗色图表方案)。
- ⚠️ 待用户运行核对(GUI 无法自动驱动):① 暗色下网格详情的「加载中…」蒙板是深纱、色阶条深底浅字;② 数据列表按 5 根分页(根多的 TM 才出「加载更多」)+ 树嵌套正确。机器侧已验证:脚本抓原版结构 + 构建 + 122 测试 + 真实登录流程日志跑通(项目 1458977804960256→E3→data/page→getDetail→dynamicForm,无崩溃)。
1. 背景
- geopro = Qt6 / C++ 离线桌面客户端,目标像素级 1:1 复刻 web 系统
http://tenant.geomative.cn/#/projectSpace/datasetMange/datasetInfo(赛盈地空)。 - 硬约束:禁 QWebEngine/Chromium(离线)。图表用本地 QwtPlot(轴/交互/图例)+ VTK 算法层(等值线几何)+ 连续/离散色阶。验收 = 视觉等价 + 交互一致(非字节级 diff)。
- 标准测试 ds:
id=1458990939709440(ddCode=dd_inversion_data)。 - 站点 baseUrl:
http://tenant.geomative.cn/pop-api。Auth header:geomativeauthorization: Geomative <token>。
2. 技术栈与构建/测试
- Qt6 Widgets + Qwt 6.2(源码
external/qwt-src/,用cmake/qwt.cmake以 CMake 构建静态库,不要用 qmake——本机 VS2026 缺 vswhere)。 - VTK 9.6 仅算法层(
vtkBandedPolyDataContourFilter/vtkStripper/vtkSplineFilter/vtkDataSetSurfaceFilter),不做 VTK 渲染。 - CMake(VS 自带)+ Ninja + MSVC 14.51;GoogleTest/CTest;vcpkg(仅非 Qt 依赖)。
- 构建:
powershell.exe -ExecutionPolicy Bypass -File scripts/dev-build.ps1- ⚠️
LNK1104 无法打开 geopro_desktop.exe= exe 在运行:先Get-Process geopro_desktop -ErrorAction SilentlyContinue | Stop-Process -Force再构建。 - ⚠️ 改头文件后偶发 ninja 增量陈旧导致链接报「符号在 main.cpp.obj 重复定义」:删
build/release/src/app/CMakeFiles/geopro_desktop.dir/main.cpp.obj后重建。
- ⚠️
- 测试:
powershell.exe -ExecutionPolicy Bypass -File scripts/dev-test.ps1(只跑 ctest 不构建——必须先 dev-build)。当前 116/116 绿。- 单测过滤:
build/release/tests/geopro_tests.exe --gtest_filter=ApiBatch.* - ⚠️ 直接跑 exe 时 4 个
CrsTransform/VoxelRegister/Terrain失败是缺PROJ_DATA环境项;ctest(dev-test)会注入环境、全绿——以 dev-test 的 "X/X passed" 为准。
- 单测过滤:
- 网络/署名:AuthLiveTest 联网真打站点;提交信息全局禁用署名(勿加 Co-Authored-By)。
3. 第一块:数据集详情图表(已完成,仅 dd_inversion_data)
详情含两页签,均经用户逐项验收:
- 原数据:Plotly scattergl 风格散点(方形点/白描边/连续色阶/x 轴顶部)。
- 网格数据:填充等值面(栅格 QImage)+ 黑色等值线(vtkStripper+vtkSplineFilter 样条平滑,每条线只标一个数值)+ NaN 白边裁剪 + 底部异常表/描述。
数据 API(均经 Playwright 实测):
| 页 | 接口 |
|---|---|
| 原数据 | lvl/colorGradation/getDetail(type1) + dd/ert/inversion/getErtRawDataScatterGraph/{id} |
| 网格 | dd/ert/inversion/rows/{id}(服务端网格化,波动 1–4s) + colorGradation/getDetail(type2) + exception/queryException/{id} |
⚠️ 架构偏离:原 spec 定 QGraphicsView,实际落地用 QwtPlot(见
plans/2026-06-11-dataset-detail-chart-v2-qwt.md,权威)。
策略分派已打通(本次会话):控制器从硬编码 dd_inversion_data 改为走 ChartStrategyRegistry(在 controller 层 src/controller/IDatasetChartStrategy.hpp,含 hasGridPhase()),未注册类型优雅降级「暂不支持」。ErtInversionStrategy(app 层)已注册。这是接其余 dd 类型的地基。
4. 第二块:全 App 网络层异步化(本次会话完成,无技术债)
动机:原 ApiClient 用 QEventLoop 死等每个请求 → 全 App 冻 UI(网格 rows 1–4s 最痛)。
核心安全不变量(spec §5.0,务必遵守):「abort 后绝不回灌」靠三件套——
- 每层
aborted_入口守卫(disconnect只是尽力而为,挡不住已入队的迟到信号); - 控制器句柄身份比对(
if (load != current_) return;丢弃迟到信号); - 一律
deleteLater,禁止同步 delete。 错误判定口径:业务code != 200 || !rawError.isEmpty()(HTTP 200 也可能 code=500)。
net 层原语(src/net/,AUTOMOC 已 ON):
IApiCall/ApiCall:单请求句柄(包 QNetworkReply),finished(ApiResponse)+abort(),自管理 deleteLater。ApiBatch:并发汇聚 N 个 IApiCall,全成功succeeded(QList)/ 任一失败 fail-fastfailed(i,resp)+abort 其余。ApiChain:串行依赖链(上步结果喂下步工厂,工厂可抛转 failed)。契约:首个 step 工厂不得同步抛/同步 fire(否则信号在调用方连接前丢失;生产路径都发异步请求,满足)。ApiResponseParse::buildResponse:sync/async 共用解析(已无 sync 调用方,仅 ApiCall 用)。ApiClient:仅getAsync/postJsonAsync(同步get/postJson/await/QEventLoop 已删除)。
data 层:
- 详情:
ChartLoad/GridLoad(抽象基 +ApiChartLoad/ApiGridLoad实现,包 ApiBatch + 注入 parse)、IAsyncDatasetRepository、ApiDatasetRepository.loadChartAsync/loadGridAsync、DatasetLoads.hpp(ChartParts/GridParts)。 - 导航:
NavRequest(单非模板句柄,done(QVariant)/failed(QString);ApiNavRequest包 IApiCall + 解析器)、NavLoads.hpp(各类型Q_DECLARE_METATYPE)、IAsyncProjectRepository(9 方法...Async后缀,返回NavRequest*,薄封装;汇聚/链编排放控制器)、ApiProjectRepository仅实现异步接口。
controller 层:
DatasetDetailController:abort-and-replace + 句柄身份比对 +loadStarted(dsId,Phase)+ 析构 abort;走ChartStrategyRegistry分派。WorkbenchNavController:全异步(NavRequest 续延依赖链 + 控制器内并发计数 + abort-and-replace + 身份比对);删除busy_/BusyGuard/drainPendingCheckedTms;busyChanged(bool)语义改为「有在飞句柄」(去抖);setCheckedTms入口去重 + 「最后一次为准」由 abort-and-replace 承接 +tmExceptionCache_缓存命中不发请求。对外信号面零改动(main.cpp 接线没动)。
app 层:
AuthService(net 层):fetchCaptchaAsync()→CaptchaLoad、loginAsync()→LoginLoad(内用 ApiChain:verifyCodeCheck→RSA(step2 工厂内)→login2)。LoginWindow:不冻 + 可取消(析构 abort),删repaint()hack。ProjectListDialog:改用IAsyncProjectRepository(NavRequest + abort-and-replace + 身份比对 + 析构 abort),过滤/分页/选项目行为等价。LoadingOverlay:网格懒加载「加载中」遮罩,接loadStarted、就绪/失败隐藏。main.cpp:qRegisterMetaType<ApiResponse>();装配注入 registry/异步 repo(引用绑定,接线信号面不变)。
执行方式:全程 subagent-driven(每块 implementer + spec 符合度评审 + 代码质量评审 opus + follow-up 加固)。测试 75 → 116(+41,含 abort 回灌防护回归用例)。
5. 关键文件地图
- net:
src/net/{IApiCall.hpp,ApiCall.*,ApiBatch.*,ApiChain.*,ApiResponseParse.*,ApiClient.*,AuthService.*,AuthLoads.*} - data:
src/data/api/{DatasetLoads.hpp,DatasetLoadHandles.*,ApiDatasetRepository.*,NavRequest.*,NavLoads.hpp,ApiProjectRepository.*,DatasetChartDto.*}、src/data/repo/{IAsyncDatasetRepository.hpp,IAsyncProjectRepository.hpp,IDatasetRepository.hpp(本地样例同步,保留),RepoTypes.hpp} - controller:
src/controller/{DatasetDetailController.*,WorkbenchNavController.*,IDatasetChartStrategy.hpp} - app:
src/app/main.cpp、src/app/panels/{DatasetDetailPanel.*,DatasetDetailPage.*,LoadingOverlay.*,chart/*}、src/app/login/LoginWindow.*、src/app/ProjectListDialog.*、src/app/panels/chart/ErtInversionStrategy.hpp - 测试:
tests/net/{FakeApiCall.hpp,test_api_batch.cpp,test_api_chain.cpp,test_auth.cpp(live),test_auth_loads.cpp}、tests/data/{test_nav_request.cpp,test_dataset_load_handles.cpp}、tests/controller/{test_dataset_detail_controller.cpp,test_workbench_nav_controller.cpp}、tests/app/test_chart_strategy_registry.cpp
6. 尚未完成 / 下一步(按优先级)
A. 收尾本分支(最先)
分支领先 main 68 commits、122/122 绿,但工作区脏(sessions 0.1–0.5 代码全未提交,见顶部 ⚠️)。用户多次选「保持现状」未提交未合并。先决:本次会话两组改动(数据集树/按根分页、暗色主题)待用户在运行的 app 内目视核对(见 0.5 末尾清单)——核对通过再谈提交。下一步可问用户:①目视核对本次改动 ②提交这批未提交工作(建议按主题分多个 commit:详情图保真 / 日志崩溃捕获 / 数据集树+分页 / 暗色主题)③合并回 main(本地) ④推送建 PR(origin=gitea https://gitea.geomative.cn/gaozheng/geopro.git) ⑤保持现状。用 superpowers:finishing-a-development-branch。
B. 其余 dd 类型详情图(计划已写,多数 BLOCKED)
计划:plans/2026-06-11-dataset-detail-other-dd-types.md。
- Phase 1(策略分派打通):✅ 已完成(本次会话)。
- Phase 0(样本探查):需做——用 Playwright 登录原版 web,对每类 dd 找有数据对象、抓真实响应存 fixtures + 渲染规格。这是后续所有类型的前置。
- Phase 2(ERT 测量散点)/ Phase 3(TEM 折线,新 LineChartView):仅当 Phase 0 确认有样本才解锁。
- Phase 4:BLOCKED——dd_grid/轨迹/测井/GPR,当前租户无活数据样本(GPR 对象无数据、无测井数据),按 1:1 复刻铁律不能凭空实现。
- 矩阵详见计划文件。
C. 工具条编辑类功能(网格页占位按钮,未做,单独立项)
白化 / 滤波处理 / 色阶配置 / 异常框注 / 自动标注 / 网格化 / 另存为 / 导出 / 描述富文本 / 大视图(Esc)全屏。当前是占位按钮。交互较重,建议先 brainstorm 拆解。spec §2.3 列为范围外。
D. 纯整洁 follow-up(非债、非阻断)
- 删
DatasetDetailController::ChartData.grid/gridScale死字段(从未填充,预存)。 - 若未来引入 cross-thread/QueuedConnection,再补
qRegisterMetaType<QList<ApiResponse>>()。
7. 相关文档
- spec:
docs/superpowers/specs/2026-06-11-apiclient-async-design.md(异步设计 + §5.0 安全不变量 + §7 错误判定/退出契约 + 顶部「状态更新」=已完成)、docs/superpowers/specs/2026-06-11-dataset-detail-view-design.md(详情视图,顶部状态=仅 ERT 反演完成 + QwtPlot 偏离)。 - plan:
docs/superpowers/plans/2026-06-11-apiclient-async-datasetdetail.md(详情试点)、2026-06-11-apiclient-async-rollout.md(导航 Part A + 登录 Part B,均落地)、2026-06-11-dataset-detail-other-dd-types.md(其余 dd 类型,Phase 1 done)、2026-06-11-dataset-detail-chart-v2-qwt.md(QwtPlot 返工,权威)。 - API 文档:
docs/apis(business_OpenAPI.json)。 - 外部方案:
docs/Geopro3.0_二维图表返工技术方案.md。
8. 记忆(务必遵守,~/.claude/projects/D--Git-lanbingtech-geopro/memory/)
reply-in-chinese— 全程中文回复。study-original-via-playwright— 任何不确定必须用 Playwright 实地看原版,禁止臆测(尤其做新 dd 类型详情图前抓样本/规格)。no-embellishment-replicate-exactly— 严格 1:1,不加原版没有的特性(曾因等值线「周期重复标注」被纠正)。
9. 工作方式备注(本次会话沿用,效果好)
- 用户偏好 subagent-driven 执行 + 实现后 code review + spec 符合度 双评审(opus 评审);「非必要不停,一口气做完」。
- 真并行构建在本项目不安全(dev-build 硬编码单一 build 目录 + 多任务共改 main.cpp/CMakeLists)→ 用顺序执行;worktree 隔离不了构建(硬编码路径 + 冷配置开销)。
- 破坏性接口改形需原子落地(同批提交)保持构建绿(详情试点 Task5+6 合并、Part A A4+A5、本次清债 都是此教训)。
- 评审 follow-up 多为小加固,直接在新代码上补;「不为不可能的场景写错误处理」(CLAUDE.md §2)——评审若建议为构造保证不会发生的情况加防御,可不采纳。