# 08: 监测数据时间字段规格(来自决策票 03) Type: spec Status: ready-for-agent Label: ready-for-agent Blocked by: 03 Category: spec 本规格固化[决策票 03](03-monitoring-created-at-contract.md)的维护者确认结果,作为[同一张 map](../map.md)的子规格单。它是运行监测真实数据「数据时间」契约的实施输入;不覆盖 `.scratch/cockpit-shell-panel-layout/spec.md`。 ## 进度:100% 规格文档已发布为 `ready-for-agent` 并挂到同一决策 map;100% 仅指规格交付,**不表示 `createdAt` 字段、前端时间标签或后端契约已实现**。后端契约改动(三端点加 `createdAt`)需按地图约定在决策收口后进入后端执行票;前端接线边界在本规格内。 ## Problem Statement 运行监测模式的三个面板级聚合端点当前没有统一的“数据时间”表达,导致三处问题: 1. **时间语义不清**:`/monitoring/overview` 只有信封级 `updatedAt`(快照加载时刻)与 `freshness.serverUpdatedAt`(响应生成时刻),没有“这批数据记录写到什么时候”的表达;前端只能以“数据时间”呈现 `updatedAt` 并写明区别(`METRIC_FRESHNESS_GAP`),无法证明它是真实数据记录时间。 2. **采集/上报时刻与记录创建时刻混淆**:设备级已有 `sampledAt`(复合语义:GAS `report_time`、WATER `timestamp_since` 优先,`create_time` 兜底)与 `equipment_status.status_update_time`;若面板直接把 `sampledAt`/`updatedAt` 当“数据时间”,会把采样时刻、状态更新时刻、记录创建时刻混为一谈。 3. **逐对象时间缺失**:台账卡(`/monitoring/distribution` 的 Marker)与异常设备(`/monitoring/situation` 的 AbnormalEquipment)没有逐对象时间字段;`distribution` 甚至把快照里的 `statusTime` 丢弃在响应外,前端无法展示“这台设备/这个点位的记录时间”。 4. **空态不明确**:无 `create_time` 或集合为空时,必须显式返回 null/未知,不得用响应时间冒充。 ## Solution 从值班人员视角:监测概览展示一个“数据时间”(范围内最新一条真实记录创建的 `create_time`,跨类型取 max);台账卡与异常设备各带自己的“数据时间”;前端“数据时间”与设备级“采样时间”两套标签各归其位,互不冒充;无数据时明确显示未知,不编造时间。 核心语义(详见决策票 03 的 Answer): - `createdAt`=**记录创建时间**(`create_time`),不是采样/上报时刻。 - 三端点字段落点: - `/monitoring/overview`:**分区级 `createdAt`**(信封一个读数,跨类型 max create_time)。 - `/monitoring/distribution`:**信封级 `createdAt` + 台账逐对象级 `createdAt`**(点位 marker 用 `monitor_point.create_time`、设备 marker 用 `equipment_base.create_time`)。 - `/monitoring/situation`:**信封级 `createdAt` + 异常设备逐对象级 `createdAt`**(用其来源表 `create_time`)。 - `map-snapshot` 不加 `createdAt`。 - `sampledAt`(采样/上报时刻)与 `createdAt`(记录创建时刻)并存分离;`status_update_time`(状态更新时刻)设备级承载,不与 `createdAt` 混。 - 空态:无 `create_time` 或集合为空 → `createdAt` 显式 `null`/未知,前端“—”或“数据时间未知”;不用响应时间/envelope `updatedAt`/`serverUpdatedAt` 冒充。 - 前端“数据时间”(=createdAt)与“采样时间”(=sampledAt/installTime/status_update_time 按其语义)两套标签。 ## User Stories 1. 作为值班人员,我想在监测概览看到“数据时间”(范围内最新真实数据记录时间),以便知道这批数据写到什么时候。 2. 作为值班人员,我想“数据时间”不是设备采样时刻也不是服务响应时间,以便不会被“看起来像是实时”误导。 3. 作为值班人员,我想台账卡上的每台设备/每个点位带自己的“数据时间”,以便知道该对象的数据到什么时候。 4. 作为值班人员,我想异常设备清单中每台设备带自己的“数据时间”,以便判断异常信息的新旧。 5. 作为值班人员,我想没有 `create_time` 时界面明确显示未知(“—”),而不是把响应时间当数据时间,以便不编造时间。 6. 作为值班人员,我想设备级指标/详情展示“采样时间”(真实采样/上报时刻),以便与面板的“数据时间”区分。 7. 作为值班人员,我想“数据时间”与“采样时间”标签不混用,以便不会把记录创建时刻误当设备采集时刻。 8. 作为部署/维护者,我想三端点的 `createdAt` 字段名与语义统一(都是记录创建时间),以便契约自洽、前端不猜。 9. 作为维护者,我想监测概览的 `createdAt` 按跨类型 max(create_time) 计算,以便异构设备类型统一成单一时间读数。 10. 作为维护者,我想执行票逐表核验 `create_time` 存在性、某表无则如实标缺口,以便不硬凑数据来源。 11. 作为维护者,我想 `map-snapshot` 不加 `createdAt`,以便空间摘要不携带无人消费的时间字段。 12. 作为维护者,我想刷新/重新取数时机不在本规格定义(归 real 生命周期),以便时间语义与刷新调度解耦。 ## Implementation Decisions ### 后端契约(供后端执行票) - `monitoring/overview`:响应新增分区级 `createdAt`(跨类型 max create_time,来自聚合源各表真实 `create_time`)。 - `monitoring/distribution`:响应新增信封级 `createdAt` + Marker 逐对象 `createdAt`(点位 marker=`monitor_point.create_time`、设备 marker=`equipment_base.create_time`;把当前丢弃的 `statusTime` 抛离,只带 `create_time` 语义的 `createdAt`)。 - `monitoring/situation`:响应新增信封级 `createdAt` + 异常设备逐对象 `createdAt`(用其来源表 `create_time`)。 - 三端点 `mapFilter`/信封不新增其它时间字段;`updatedAt`(快照加载时刻)与 `serverUpdatedAt`(响应生成时刻)保留原语义。 - archive 端点不加 `createTime`(现状有 `installTime`/`productionDate`,详情时间按“采样时间/安装时间”展示)。 - `sampledAt` 保持现状(GAS `report_time` 优先、WATER `timestamp_since` 优先、`create_time` 兜底),不改。 ### 前端 - `domain/monitoringPanels.js`:新增 `createdAt` 读取(分区级 + 逐对象级);空态 null → “—”;“数据时间”标签映射;与“采样时间”标签分离。 - `services/monitoringApi.js`:三端点透传 `createdAt`(只读不筛),不新增入参。 - 组件(`PanelBlocks` / 台账卡 / 设备详情):监测概览“数据时间”读数、台账卡时间、异常设备时间;设备级详情显示“采样时间/安装时间”(现有字段)。 - `METRIC_FRESHNESS_GAP` 措辞改为“数据时间=记录创建时间,不是设备采样时刻”。 ## Testing Decisions - **好测试的定义**:只测外部行为与契约语义——`createdAt` 读取/空态、“数据时间/采样时间”标签不混、服务层不新增入参、不把 `updatedAt`/`serverUpdatedAt` 冒充 `createdAt`。 - **主接缝**:领域纯函数(`domain/monitoringPanels.js` 的时间适配)+ 服务层守卫(`services/monitoringApi.js`)。先例:`.scratch/cockpit-shell-panel-layout/verify/t18-monitoring-panels.mjs`、`t05-adapter.mjs`(静态守卫 + 变异测试确认有牙)。 - **浏览器走查**(`-walkthrough.mjs` + `data-*`):监测概览“数据时间”读数、台账卡时间、空态“—”、设备详情“采样时间/安装时间”,断言时间标签不混。 - **后端执行票验收**:三端点响应含 `createdAt`(信封 + 逐对象)、空态 `null`、跨类型 max(create_time) 语义;`map-snapshot` 与 archive 不含 `createdAt`。 ## Out of Scope - `sampledAt` 的语义变更(保持现状复合映射,不改)。 - 刷新/重新取数时机(归决策票 04,real 生命周期);本规格只定字段语义与展示。 - `map-snapshot` 的筛选与命中设备子集(归决策票 02 / 规格 07)。 - 设备级状态词表、异常统计(归决策票 06)。 - 后端实现与真实联调(后端执行票在相关决策收口后创建)。 - 移动端、UE5、Docker、国产化认证及非驾驶舱领域。 ## Further Notes - 本规格依赖决策票 03(已 resolved);后端契约改动需在决策票 04(real 生命周期)、05(联调基线)、06(业务语义)收口后进入后端执行票。 - 领域词汇已同步 `CONTEXT.md`:新增「采样时间」词条并修订「数据时间」。 - 未运行 build/debug 验证(遵循仓库 AGENTS.md 规则);本规格只交付实施输入。