标注功能重构方案.md 12 KB

标注功能重构方案(细化版)

状态:设计稿,未改代码。确认后再进入实施。 本版调整:标注改为“段记录 + 15 分钟色块显示”;PKS 单击整小时、连续小时合并;双击弹窗改类型/看算法属性/改起止/删除;不设正常段;时间轴汇总所有子图。

1. 目标与范围

目标

  • 标注对象:wave_file 传感器数据 和 PKS 数据。
  • 显示单位:15 分钟色块。
  • 存储单位:标签段(起止时间对齐 15 分钟;wave 与 PKS 人工标注均按整小时)。
  • 算法标签(振动/油压/温度)进入统一表,页面可看、可改。
  • 人工标签与算法标签共存,人工优先。
  • 后续可导出给训练。

不做

  • 不改模型算法。
  • 不改 tag-manual。
  • 不改 compressor_alarm。
  • 暂不删除 wave_annotation,最后迁移。
  • 不做“正常”段:正常样本由后续训练算法生成。

取消

“预训练记录”整套:前端记录/删除按钮、/api/pretrain-records、pretrain_service.py、backend/预训练之文件头.csv、pretrainCounts。


2. 核心模型

2.1 目标与通道

标注目标 = 目标类型 + 通道 + 标签段(start_time, end_time)
目标类型 通道 channel_key target_key
wave_file `wave:{device_part} {device_point}`
pks pks:{unit}:{device_code}:{metric_key} 同 channel_key
  • wave:15 分钟一个文件,槽与文件一一对应。
  • PKS:每个全场点位(如 YSJ_11)一个独立通道、独立标注行。
  • 不同子图 = 不同通道 = 独立标签记录,单独操作。

2.2 段记录与 15 分钟显示

  • 一条标签记录 = 一个连续时间段 [start_time, end_time)。
  • start_time/end_time 对齐 15 分钟;PKS 人工标注默认整小时。
  • 页面按 15 分钟切成色块显示;一条段记录可覆盖多个色块。
  • 相邻同类型段 合并为一条记录;不同类型重叠时拒绝并提示。

2.3 标签级别

只保留异常级别,与现有算法一致:

轻微 / 异常 / 严重异常

label_subtype 存振动侧、温度部位、方向等;features_json 存算法原始属性。


3. 页面交互

3.1 标注行

每个子图上方一行,高度约一行文本(18–20px):

┌──────────── 子图标题 ────────────┐
│ 异常 │ [异常][异常][ ][轻微][轻微] │  ← 左侧显示当前设置的类
├──────────────────────────────────┤
│            波形子图               │
└──────────────────────────────────┘
  • 每格 = 15 分钟。
  • 有标签:按级别着色,块内显示类型文本,单行、超出隐藏。
  • 无标签:浅灰空块。
  • 无数据(停机/缺文件):空白且不可点。
  • 颜色:轻微=黄,异常=橙,严重异常=红。
  • 标注行左侧标题只显示“当前被设置的类”,不显示复杂信息。

3.2 单击

  • 单击空白 15 分钟块:新增标注,默认类型 异常(可改)。
  • wave 与 PKS 一致:单击任一块 → 自动选中所在整小时(4 个块)。
  • 连续小时再次单击 → 若类型相同,合并成一条记录。
  • 同一通道内,不同类型不允许重叠或相邻;不同通道互不影响。

3.3 双击弹窗

双击任意块打开弹窗,内容:

  1. 类型选择:轻微 / 异常 / 严重异常。
  2. 起止时间:可编辑,按小时设置(wave 与 PKS 都默认整小时)。
  3. 算法原始属性:以只读 JSON 展示,例如:
机组、批次、周期编号、压力阶段、开始小时、结束小时、
持续自然小时数、有效运行小时数、周期基线油压、正常波动带、
阶段开始小时油压、阶段结束小时油压、阶段最低小时油压、
阶段开始/结束相对周期基线变化、阶段最大连续下降有效小时数、
阶段低报警小时数、阶段低低报警小时数、是否形成确认等级、阶段触发依据
  1. 备注(可编辑)。
  2. 删除按钮:删除整条段记录。

保存后:

  • 改类型 → 更新段记录。
  • 改起止 → 重新计算合并/拆分。
  • 人工修改后 origin=manual,算法重复导入不覆盖。

3.4 展示

  • 波形半透明色块保持现状,覆盖整个标签段。
  • 时间轴“标注”行:汇总所有子图;任一道有标签即着色,颜色取最高级别。
  • 时间轴 tooltip 只简单表达“有标注”,不列通道明细。
  • 增加颜色图例。

4. 数据表

CREATE TABLE IF NOT EXISTS compressor_label (
    id                 BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    source_type        VARCHAR(32)  NOT NULL COMMENT 'vibration/oil_pressure/temperature/pressure_wave/pks_manual',
    origin             VARCHAR(16)  NOT NULL DEFAULT 'manual' COMMENT 'algorithm/manual/imported',
    target_type        VARCHAR(16)  NOT NULL COMMENT 'wave_file/pks',
    target_id          BIGINT UNSIGNED NULL COMMENT 'wave_file.id',
    target_key         VARCHAR(200) NOT NULL COMMENT 'wave:{id} / pks:{unit}:{code}:{metric}',
    channel_key        VARCHAR(200) NOT NULL COMMENT '子图通道键',
    segment_key        VARCHAR(128) NULL COMMENT '算法原始段分组键',
    unit               VARCHAR(16)  NOT NULL,
    device_code        VARCHAR(64)  NULL,
    device_part        VARCHAR(200) NULL,
    device_point       VARCHAR(200) NULL COMMENT 'wave 点位',
    metric_key         VARCHAR(64)  NULL COMMENT 'PKS: YSJ_11',
    metric_label       VARCHAR(200) NULL COMMENT 'PKS: 链轮端振动',
    start_time         DATETIME     NOT NULL COMMENT '标签段起点,15min/小时对齐',
    end_time           DATETIME     NOT NULL COMMENT '标签段终点(不含)',
    algorithm_start    DATETIME     NULL COMMENT '算法原始段起点',
    algorithm_end      DATETIME     NULL COMMENT '算法原始段终点',
    label_type         VARCHAR(32)  NOT NULL COMMENT '轻微/异常/严重异常',
    label_subtype      VARCHAR(64)  NULL,
    severity           TINYINT      NULL,
    confirm_status     VARCHAR(16)  NOT NULL DEFAULT '未确认',
    usable_for_train   TINYINT(1)   NOT NULL DEFAULT 1,
    source_file        VARCHAR(500) NULL,
    source_row         VARCHAR(64)  NULL,
    algorithm_version  VARCHAR(64)  NULL,
    features_json      MEDIUMTEXT   NULL COMMENT '算法原始属性',
    note               VARCHAR(1000) NULL,
    created_by         VARCHAR(64)  NULL,
    updated_by         VARCHAR(64)  NULL,
    created_at         DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at         DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at         DATETIME     NULL,
    PRIMARY KEY (id),
    KEY idx_target_time (target_key, start_time, end_time),
    KEY idx_channel_time (channel_key, start_time),
    KEY idx_segment (segment_key),
    KEY idx_unit_time (unit, start_time),
    KEY idx_source (source_type, origin)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '统一训练标签表';

说明:

  • 不做 (target_key, slot_start) 唯一键,因为要支持跨多槽的段和合并。
  • 段重叠/相邻的合并与冲突在服务层处理。
  • 同通道同时间段只保留一条有效记录。
  • 算法段导入时也按段存,显示时展开为 15 分钟块。

合并/冲突规则

新增或修改时,取同 target_key(同一子图通道)下与 [start,end) 重叠或相邻的记录:
- 类型相同(重叠或相邻) -> 合并为一条,start=min, end=max
- 类型不同(重叠或相邻) -> 拒绝,提示先修改/删除相邻记录
- 不同 target_key/通道互不影响,各自独立

算法导入覆盖

不存在            -> 插入
origin=manual     -> 跳过
origin=algorithm  -> 更新

5. 算法标签接入

算法不动,新增转存程序:

读取 CSV -> 生成段记录 -> UPSERT compressor_label
来源 source_type metric_key label_type 时间
振动异常段.csv vibration 链轮端→YSJ_11,联轴器端→YSJ_10 振动阶段 开始/结束小时
润滑油压力小时阶段段.csv oil_pressure 7/8/9 号机→YSJ_5 压力阶段 开始/结束小时
温度异常段.csv temperature 阶段点位 YSJ_n → YSJ{unit}_n 温度阶段 开始/结束小时

字段映射:

  • label_subtype:振动侧 / 温度部位 / 方向 / 特征类型。
  • confirm_status:由“是否形成确认等级”映射。
  • source_row:周期编号。
  • features_json:整行原样 JSON。
  • segment_key:来源 + 周期编号 + 起止时间。

正常样本不导入、不生成。


6. 接口

GET    /api/labels?target_type=&unit=&device_code=&metric_key=&start=&end=
GET    /api/labels?wave_file_ids=...
POST   /api/labels              新增(自动合并)
PUT    /api/labels/{id}         改类型/起止/备注(自动合并或拆分)
DELETE /api/labels/{id}         删除段

返回:

{
  "id": 12,
  "targetType": "pks",
  "targetKey": "pks:7:7#:YSJ_11",
  "startTime": "2026-02-10T10:00:00",
  "endTime": "2026-02-10T12:00:00",
  "labelType": "异常",
  "labelSubtype": "链轮端",
  "origin": "algorithm",
  "confirmStatus": "已确认",
  "features": { "...": "算法原始属性" }
}

7. 时间轴

  • 汇总所有子图/通道。
  • 每个时间槽:任一道有标签 → 标记。
  • 颜色取该槽内最高级别(严重异常 > 异常 > 轻微)。
  • tooltip 只显示“有标注”,不列通道明细。
  • 语义不变,只改数据来源和着色逻辑。

8. 分期

Phase 0:确认本设计

Phase 1:清理预训练记录

前端按钮/状态、后端接口/service/CSV/pretrainCounts。不动 wave_annotation。

Phase 2:新表 + 算法标签只读

建表、转存三张 CSV、查询接口、标注行只读展示。

Phase 3:人工标注

单击新增/整小时选择/连续合并;双击弹窗改类型、起止、看算法 JSON、删除;先 wave 后 PKS。

Phase 4:训练导出与迁移(暂缓,用户指示先不做)

导出 usable_for_train=1;迁移 wave_annotation;下线老逻辑。


8.1 测试记录(2026-11-08)

使用 Playwright + Chrome 对 Phase 1–3 做了界面回归:

  • Phase 1:窗口文件表只剩“定位”,无“记录/删除”;页面无“预训练”;/api/pretrain-records 返回 404。
  • Phase 2:算法标签在子图标注行按 15 分钟块显示;时间轴“标注”行汇总着色。
  • Phase 3:
    • 单击空白整点块 → POST 创建 异常,成功。
    • 双击已有标签 → 弹窗,类型、起止、点位、备注正常回显。
    • 改类型保存 → PUT,弹窗关闭,重开类型正确。
    • 改起止时间 + 备注保存 → PUT,重开值正确。
    • 删除 → 二次确认 → DELETE,弹窗关闭。
    • 同类型相邻单击 → 合并为一条段记录。
    • 不同类型相邻保存 → 400,界面提示“同一子图内不同类型不能重叠或相邻”。
    • 双击算法标签 → 显示只读算法属性 JSON(机组、周期编号、压力阶段、基线油压、触发依据等)。
  • 测试产生的临时人工标签已清理,库内保留 182 条算法标签。

9. 已确认

  1. wave 单击也选中整小时。
  2. 同一通道内,不同类型不允许重叠或相邻并存;不同通道各自独立。
  3. 时间轴 tooltip 只表达“有标注”,不显示通道明细。

10. 注意

  • 段记录跨多槽,显示时展开;不要按槽存重复行。
  • 人工修改与算法导入要隔离,避免覆盖。
  • 新旧标注并存期只显示一套,避免重复。
  • ECharts 标注行需随缩放重绘,事件绑定在 graphic 上。