# OPS 首期数据模型与状态机

## 1. 文档目标

本文用于固定第 1 阶段编码前的核心后端规格，覆盖资源监控、采集、时序指标、原始事件、告警、事件、通知、工单、审计和 3D 机房后端接口所需的最小数据模型与状态机。

本文不替代数据库迁移脚本。后续实现时，应以本文作为 `server/internal/models/`、`server/internal/logic/` 和接口设计的依据。

## 2. 范围边界

第 1 阶段必须覆盖：

- 主机、H3C/华三网络设备、数据库、虚拟化、URL/API 至少各一类样例资源。
- 指标采集、Syslog、SNMP Trap、URL/API 探测、采集失败事件。
- 告警去重、压缩或归并、屏蔽、抑制、确认、忽略、恢复、派单。
- 平台站内消息、短信、邮件三类通知。
- 工单创建、接单、转交、撤回、挂起、重启、关闭。
- 报表、大屏、审计能追踪完整故障闭环。
- 外包 3D 机房前端所需的数据中心、机房、机柜、U 位、设备和告警状态接口模型。

第 1 阶段不覆盖：

- 所有厂商全量适配。
- 老运维平台迁移或集成。
- 3D 机房前端实现。
- 完整 IPAM、复杂拓扑编辑、全量资产审核流程。

## 3. 存储分工

| 存储 | 数据范围 | 说明 |
| --- | --- | --- |
| PostgreSQL | 资源、业务系统、资产、采集任务、规则、告警、事件、工单、通知、权限、审计、报表配置 | 事务数据主库，保证一致性和审计。 |
| TDengine 开源版 | 指标样本、探测样本、接口流量、采集健康度、容量和性能趋势 | 第 1 阶段选定的时序数据库。后端通过适配层访问，避免业务逻辑直接依赖 TDengine SQL 方言。 |
| 文件或对象存储 | 报表导出、附件、截图、录像、大屏快照 | 第 1 阶段可先使用本地文件存储，接口保留替换能力。 |

设计原则：

- PostgreSQL 保存资源和指标定义，时序数据库保存样本值。
- 所有时序数据必须能通过 `resource_id`、`metric_code`、时间范围回查到资源上下文。
- 告警、事件、工单状态变化必须写审计日志。
- 真实凭据不落业务表明文，只保存凭据引用和脱敏描述。

## 4. 通用字段

核心业务表建议统一包含：

| 字段 | 类型建议 | 说明 |
| --- | --- | --- |
| `id` | UUID 或雪花 ID | 主键。 |
| `tenant_id` | string | 单院区可固定，保留多租户或多院区扩展。 |
| `created_at` | timestamp | 创建时间。 |
| `updated_at` | timestamp | 更新时间。 |
| `created_by` | string | 创建人。 |
| `updated_by` | string | 更新人。 |
| `deleted_at` | timestamp nullable | 软删除时间，需要保留审计的表不做物理删除。 |
| `version` | integer | 乐观锁版本，用于工单、规则等并发修改。 |

审计相关表必须额外保留：

| 字段 | 说明 |
| --- | --- |
| `trace_id` | 请求链路 ID。 |
| `operator_id` | 操作人。 |
| `operator_name` | 操作人快照。 |
| `source_ip` | 操作来源 IP。 |
| `before_json` | 变更前快照，敏感字段脱敏。 |
| `after_json` | 变更后快照，敏感字段脱敏。 |

## 5. 资源与资产模型

### 5.1 核心表

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `business_systems` | 业务系统，如 HIS、LIS、PACS、EMR | `name`、`code`、`level`、`network_zone`、`owner_org_id`、`owner_user_id`、`description` |
| `resource_types` | 资源类型和默认模板 | `code`、`name`、`category`、`vendor`、`default_metric_template_id`、`icon` |
| `resources` | 统一监控资源 | `name`、`resource_type_id`、`vendor`、`model`、`ip`、`hostname`、`business_system_id`、`owner_org_id`、`owner_user_id`、`asset_id`、`status`、`collect_status` |
| `resource_relations` | 资源依赖关系 | `source_resource_id`、`target_resource_id`、`relation_type`、`description` |
| `metric_definitions` | 指标定义 | `resource_type_id`、`metric_code`、`metric_name`、`unit`、`value_type`、`default_interval_seconds`、`threshold_hint` |
| `metric_series` | 时序指标序列映射 | `resource_id`、`metric_definition_id`、`metric_code`、`tsdb_name`、`series_key`、`labels_json`、`retention_policy` |
| `credentials` | 凭据引用 | `name`、`type`、`secret_ref`、`masked_summary`、`owner_org_id`、`status` |

### 5.2 资产与 3D 机房接口模型

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `data_centers` | 数据中心 | `name`、`province`、`city`、`address`、`status` |
| `rooms` | 机房 | `data_center_id`、`name`、`floor`、`status` |
| `racks` | 机柜 | `room_id`、`name`、`code`、`total_u`、`row_no`、`column_no`、`x`、`y`、`z`、`status` |
| `rack_units` | U 位占用 | `rack_id`、`u_no`、`resource_id`、`asset_id`、`occupy_height`、`status` |
| `assets` | 资产台账 | `asset_no`、`name`、`vendor`、`model`、`serial_no`、`resource_id`、`rack_id`、`status` |

3D 机房前端接口至少需要返回：

- 数据中心、机房、机柜层级。
- 机柜坐标、容量、已占用 U 位、剩余 U 位。
- 设备与资源绑定关系。
- 设备健康状态、最高告警级别、未恢复告警数量。
- 数据更新时间和权限过滤结果。

### 5.3 资源状态

| 状态码 | 中文名 | 说明 |
| --- | --- | --- |
| `draft` | 草稿 | 已录入但未启用采集。 |
| `active` | 运行中 | 正常纳管，可采集、可触发告警。 |
| `disabled` | 已停用 | 暂停采集，不产生新告警。 |
| `maintenance` | 维护中 | 可采集，但默认抑制或降级告警。 |
| `decommissioned` | 已退役 | 不再采集，仅保留历史和审计。 |

合法流转：

```text
草稿 -> 运行中
运行中 -> 维护中 -> 运行中
运行中 -> 已停用 -> 运行中
运行中 -> 已退役
已停用 -> 已退役
```

非法流转：

- 已退役资源不能直接恢复为运行中，必须重新建档或走恢复审批。
- 已停用资源不能生成新的业务告警，但可以生成配置或审计事件。

## 6. 采集与时序模型

### 6.1 采集任务表

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `collector_tasks` | 采集任务定义 | `resource_id`、`collector_type`、`protocol`、`credential_id`、`schedule_cron`、`interval_seconds`、`timeout_seconds`、`retry_limit`、`status` |
| `collector_runs` | 采集执行记录 | `task_id`、`started_at`、`finished_at`、`run_status`、`success_count`、`failed_count`、`error_code`、`error_message` |
| `discovery_tasks` | 自动发现任务 | `name`、`scan_range`、`protocols`、`credential_id`、`schedule_cron`、`status` |
| `probe_targets` | URL/API/端口探测目标 | `resource_id`、`target_url`、`method`、`expected_status`、`timeout_seconds`、`status` |

### 6.2 时序样本逻辑结构

时序库中的指标样本必须至少包含：

| 字段 | 说明 |
| --- | --- |
| `ts` | 样本时间。 |
| `resource_id` | 资源 ID。 |
| `resource_type` | 资源类型编码。 |
| `metric_code` | 指标编码。 |
| `value` | 指标值。 |
| `unit` | 单位。 |
| `labels` | 标签，如接口名、磁盘分区、数据库实例名。 |
| `quality` | 样本质量：正常、缺失、估算、异常。 |
| `collector_task_id` | 采集任务 ID。 |

### 6.3 采集任务状态

任务配置状态：

```text
草稿 -> 已启用 -> 已停用
已启用 -> 已停用 -> 已启用
已启用 -> 已删除
已停用 -> 已删除
```

单次执行状态：

```text
待执行 -> 执行中 -> 成功
待执行 -> 执行中 -> 部分成功
待执行 -> 执行中 -> 失败
执行中 -> 超时
```

规则：

- 连续失败达到阈值时，必须生成平台内部原始事件。
- 部分成功必须记录缺失指标，不允许只显示成功。
- 凭据错误、设备不可达、协议超时需要区分错误码。

## 7. 事件与告警模型

### 7.1 核心表

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `raw_events` | 原始事件 | `source_type`、`source_id`、`resource_id`、`event_key`、`occurred_at`、`severity`、`title`、`message`、`payload_json`、`parse_status` |
| `alert_rules` | 告警规则 | `name`、`scope_type`、`scope_id`、`metric_code`、`condition_expr`、`duration_seconds`、`recover_expr`、`severity`、`status` |
| `alerts` | 告警实例 | `alert_key`、`resource_id`、`rule_id`、`first_seen_at`、`last_seen_at`、`recovered_at`、`severity`、`status`、`summary` |
| `incidents` | 归并事件 | `incident_no`、`title`、`severity`、`status`、`owner_user_id`、`business_system_id`、`opened_at`、`closed_at` |
| `incident_alerts` | 事件与告警关联 | `incident_id`、`alert_id`、`relation_type` |
| `silence_policies` | 屏蔽策略 | `name`、`scope_type`、`scope_id`、`start_at`、`end_at`、`reason`、`status` |
| `dedup_rules` | 去重规则 | `name`、`match_expr`、`dedup_window_seconds`、`status` |
| `correlation_rules` | 关联/压缩/抑制规则 | `name`、`match_expr`、`action`、`priority`、`status` |
| `escalation_policies` | 升级策略 | `name`、`severity`、`timeout_minutes`、`next_target_type`、`next_target_id`、`status` |

### 7.2 原始事件状态

| 状态码 | 中文名 | 说明 |
| --- | --- | --- |
| `received` | 已接收 | 原始数据已入库。 |
| `parsed` | 已解析 | 已识别资源、级别、事件键。 |
| `unparsed` | 未解析 | 字典或规则不匹配。 |
| `suppressed` | 已抑制 | 命中屏蔽、依赖或抑制规则。 |
| `converted` | 已转告警 | 已生成或更新告警。 |
| `archived` | 已归档 | 不再参与处理。 |

合法流转：

```text
已接收 -> 已解析 -> 已转告警
已接收 -> 未解析 -> 已解析 -> 已转告警
已解析 -> 已抑制 -> 已归档
已转告警 -> 已归档
未解析 -> 已归档
```

规则：

- 未解析 Trap/Syslog 不能直接丢弃，必须可查询、可补规则重放。
- 已抑制事件必须记录命中的策略 ID。

### 7.3 告警状态机

| 状态码 | 中文名 | 说明 |
| --- | --- | --- |
| `firing` | 触发中 | 当前异常仍存在。 |
| `acknowledged` | 已确认 | 值班人员已接手，但异常未恢复。 |
| `ignored` | 已忽略 | 经人工判断无需处理。 |
| `recovered` | 已恢复 | 恢复条件满足或收到恢复事件。 |
| `expired` | 已失效 | 长时间未刷新且无法确认恢复。 |

合法流转：

```text
触发中 -> 已确认 -> 已恢复
触发中 -> 已忽略
触发中 -> 已恢复
触发中 -> 已失效
已确认 -> 已恢复
已确认 -> 已忽略
已确认 -> 已失效
```

非法流转：

- 已恢复告警不能重新变为触发中；同一资源同一规则再次异常时，应创建或激活新的告警周期。
- 已忽略告警不能自动派单。
- 已失效告警不能再确认，只能作为历史查看。

### 7.4 事件状态机

| 状态码 | 中文名 | 说明 |
| --- | --- | --- |
| `open` | 待处理 | 已创建事件，尚未分派。 |
| `assigned` | 已分派 | 已指定处理人或处理组。 |
| `in_progress` | 处理中 | 处理人已开始处理。 |
| `suspended` | 已挂起 | 等待外部条件或人工决策。 |
| `resolved` | 已解决 | 技术处理完成，等待关闭确认。 |
| `closed` | 已关闭 | 闭环完成。 |

合法流转：

```text
待处理 -> 已分派 -> 处理中 -> 已解决 -> 已关闭
处理中 -> 已挂起 -> 处理中
已分派 -> 待处理
已解决 -> 处理中
```

非法流转：

- 已关闭事件不能回到处理中。
- 未关联告警或资源的事件不能进入已关闭。
- 已解决事件若关联告警再次触发，应退回处理中或新建事件，不能静默覆盖。

## 8. 通知模型

### 8.1 核心表

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `notification_policies` | 通知策略 | `name`、`scope_type`、`severity`、`channels`、`receiver_expr`、`status` |
| `notification_templates` | 通知模板 | `channel`、`title_template`、`content_template`、`variables_json`、`status` |
| `notification_records` | 通知发送记录 | `channel`、`alert_id`、`incident_id`、`receiver`、`send_status`、`retry_count`、`error_message`、`sent_at` |

第 1 阶段通知渠道：

- 平台站内消息。
- 短信。
- 邮件。

### 8.2 通知状态机

```text
待发送 -> 发送中 -> 已发送
待发送 -> 发送中 -> 失败 -> 待重试 -> 发送中
失败 -> 已取消
待重试 -> 已取消
```

规则：

- 任何通知失败都不能阻断告警和工单状态流转。
- 通知失败必须可见、可重试、可审计。
- 短信和邮件必须记录第三方返回码或失败原因。

## 9. 工单模型

### 9.1 核心表

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `tickets` | 工单 | `ticket_no`、`title`、`source_type`、`source_id`、`alert_id`、`incident_id`、`resource_id`、`assignee_id`、`status`、`priority`、`closed_at` |
| `ticket_transitions` | 工单流转记录 | `ticket_id`、`from_status`、`to_status`、`operator_id`、`reason`、`created_at` |
| `ticket_comments` | 工单处理记录 | `ticket_id`、`comment_type`、`content`、`attachments_json`、`created_by` |
| `ticket_sla_records` | 工单时效记录 | `ticket_id`、`accepted_at`、`first_response_at`、`resolved_at`、`closed_at`、`overdue_flag` |

### 9.2 工单状态机

| 状态码 | 中文名 | 说明 |
| --- | --- | --- |
| `created` | 已创建 | 工单已生成，等待接单。 |
| `accepted` | 已接单 | 处理人已接收。 |
| `in_progress` | 处理中 | 正在处理。 |
| `transferred` | 已转交 | 转给其他处理人或处理组。 |
| `suspended` | 已挂起 | 暂停处理，等待外部条件。 |
| `restarted` | 已重启 | 从挂起恢复。 |
| `withdrawn` | 已撤回 | 创建方撤回或确认无需处理。 |
| `closed` | 已关闭 | 处理完成并关闭。 |

合法流转：

```text
已创建 -> 已接单 -> 处理中 -> 已关闭
已创建 -> 已撤回
已接单 -> 已转交 -> 已接单
处理中 -> 已转交 -> 已接单
处理中 -> 已挂起 -> 已重启 -> 处理中
已接单 -> 已关闭
```

非法流转：

- 已关闭工单不能转交、撤回或挂起。
- 已撤回工单不能重新接单，只能新建工单。
- 同一告警不能重复自动创建多个未关闭工单。
- 无权限用户不能关闭、转交或撤回工单。

## 10. 权限与审计模型

| 表名 | 职责 | 关键字段 |
| --- | --- | --- |
| `organizations` | 组织部门 | `name`、`parent_id`、`status` |
| `users` | 用户 | `username`、`display_name`、`org_id`、`status` |
| `roles` | 角色 | `name`、`code`、`status` |
| `user_roles` | 用户角色 | `user_id`、`role_id` |
| `role_permissions` | 功能权限 | `role_id`、`permission_code` |
| `data_scopes` | 数据权限 | `subject_type`、`subject_id`、`scope_type`、`scope_expr` |
| `audit_logs` | 审计日志 | `action`、`object_type`、`object_id`、`operator_id`、`trace_id`、`before_json`、`after_json` |

必须审计的动作：

- 资源新增、修改、停用、退役。
- 凭据引用变更。
- 告警确认、忽略、派单、恢复、失效。
- 屏蔽、抑制、升级、通知策略变更。
- 工单接单、转交、撤回、挂起、重启、关闭。
- 权限、角色、数据权限变更。
- 报表导出和敏感数据查看。

## 11. 核心关系

```mermaid
erDiagram
    BUSINESS_SYSTEMS ||--o{ RESOURCES : contains
    RESOURCE_TYPES ||--o{ RESOURCES : classifies
    RESOURCES ||--o{ METRIC_SERIES : emits
    METRIC_DEFINITIONS ||--o{ METRIC_SERIES : defines
    RESOURCES ||--o{ COLLECTOR_TASKS : collected_by
    COLLECTOR_TASKS ||--o{ COLLECTOR_RUNS : runs
    RESOURCES ||--o{ RAW_EVENTS : produces
    RAW_EVENTS ||--o{ ALERTS : converts_to
    ALERT_RULES ||--o{ ALERTS : triggers
    INCIDENTS ||--o{ INCIDENT_ALERTS : groups
    ALERTS ||--o{ INCIDENT_ALERTS : grouped_by
    INCIDENTS ||--o{ TICKETS : handled_by
    ALERTS ||--o{ TICKETS : may_create
    ALERTS ||--o{ NOTIFICATION_RECORDS : notifies
    INCIDENTS ||--o{ NOTIFICATION_RECORDS : notifies
    DATA_CENTERS ||--o{ ROOMS : contains
    ROOMS ||--o{ RACKS : contains
    RACKS ||--o{ RACK_UNITS : contains
    RESOURCES ||--o| ASSETS : binds
    ASSETS ||--o{ RACK_UNITS : occupies
```

## 12. 编码前检查清单

- [ ] PostgreSQL 表结构与本文核心表一一对应。
- [ ] 时序数据库选型完成，并定义 `resource_id + metric_code + ts` 查询方式。
- [ ] 告警、事件、工单状态机在后端集中定义，不在前端自行拼状态。
- [ ] 所有状态变化写入 `audit_logs` 或对应流转记录。
- [ ] 采集失败、通知失败、自动派单失败均能产生可见错误和审计记录。
- [ ] 3D 机房接口不依赖真实现场台账即可返回样例数据。
- [ ] API 响应统一包含 `code`、`message`、`traceId`，错误场景包含可操作建议。
