/** * 拓扑图:基于 GET /tenant/device 返回的设备数组,构造 PisellFloorMapLayout 所需的 * `FloorMapViewConfig` + `dataSources`,无连线、按 `type_code` 动态生成 elementKinds、 * 用近似正方形网格自动布局。**不依赖 shop floor-plan**。 */ import type { FloorMapDataSources, FloorMapEdge, FloorMapElementKindCategory, FloorMapElementKindConfig, FloorMapSceneElement, FloorMapViewConfig } from '@pisell/materials'; import { TOPOLOGY_DEVICE_KIND_PREFIX } from './topologyFloorPlanConstants'; /** 接口返回里单台设备(局部字段,仅用本视图实际用到的) */ export interface RawTopologyDevice { id: number | string; type_code?: string | null; type_kind?: string | null; model_code?: string | null; number?: string | null; status?: string | null; link?: string | null; /** 设备上报信息(与 saasDevice devicePlanning 的 `device.data` 结构一致) */ data?: Record | null; name?: Record | string | null; type?: { name?: Record | null; } | null; model?: { name?: Record | null; code?: string | null; } | null; workarea?: { id?: number; name?: Record | null; } | null; workarea_id?: number | null; } export { TOPOLOGY_DEVICE_KIND_PREFIX }; /** * 静态 `type_code` 枚举:拓扑图所有可识别的设备类型。 * 接口返回里若出现未列入的 `type_code`,会落到 `unknown` 兜底 kind。 */ export declare const TOPOLOGY_DEVICE_TYPE_CODES: readonly ["pos", "receipt_printer", "label_printer", "switch", "info_display", "terminal", "chenlei", "test1"]; export declare type TopologyDeviceTypeCode = (typeof TOPOLOGY_DEVICE_TYPE_CODES)[number]; /** 拓扑设备所有 kind value(含 unknown 兜底) */ export declare const TOPOLOGY_DEVICE_KIND_VALUES: string[]; /** 从 HTTP 封装响应中提取 `data` 数组(兼容 `{data: [...]}` / 直接数组) */ export declare function extractRawDeviceList(response: unknown): RawTopologyDevice[]; /** 接口返回里单条连接(局部字段,仅用本视图实际用到的) */ export interface RawTopologyDeviceConnection { id: number | string; source_device_id: number | string; target_device_id: number | string; status?: string | null; config?: { connection_ip?: string | null; connection_type?: string | null; connection_method?: string | null; } | null; } /** 从 HTTP 封装响应中提取设备连接 `data` 数组 */ export declare function extractRawDeviceConnectionList(response: unknown): RawTopologyDeviceConnection[]; /** * 设备 IP:与 devicePlanning 详情「网络 → 本地 IP」同源(`data.network.local_ip`)。 */ export declare function deviceIpAddress(device: RawTopologyDevice): string | undefined; /** 设备数组 → `dataSources.devices`(PisellFloorMapLayout 需要的扁平 record 形式) */ export declare function buildTopologyDeviceDataSources(rawDevices: RawTopologyDevice[]): FloorMapDataSources; /** * 基于固定 `TOPOLOGY_DEVICE_TYPE_CODES` 枚举生成图元种类,**不依赖**接口响应。 * 接口若返回新的 type_code,运行时会落到 `unknown` 兜底 kind(见 `buildTopologyConnectionAwareSceneElements`)。 */ export declare function buildTopologyDeviceElementKinds(): { categories: FloorMapElementKindCategory[]; kinds: FloorMapElementKindConfig[]; /** type_code → kind value(落点时使用) */ typeCodeToKind: Map; }; /** * 连接优先布局: * 1. 用连接关系把设备分成连通分量(多对多关系交由 edges 渲染)。 * 2. 每个有连接的分量按 `type_kind` 分两行:smart / integrated 在上,dumb 在下; * 同层节点用 barycenter 启发重排,减少连线交叉。 * 3. 多个 cluster 横向并排(超出最大行宽换行)。 * 4. 孤立设备最后放在已布局区域**下方**:上一行 smart、下一行 dumb,整体居左对齐。 */ export declare function buildTopologyConnectionAwareSceneElements(rawDevices: RawTopologyDevice[], rawConnections: RawTopologyDeviceConnection[], typeCodeToKind: Map): { sceneElements: FloorMapSceneElement[]; }; export declare function getConnectionTypeStyle(connectionType: string | null | undefined): { color?: string; dashed?: boolean; }; /** * connection 数组 → `FloorMapEdge[]`。 * - 仅保留两端 device 都在当前 device 数组里的连接(避免悬空 edge)。 * - 锚点强制走 top/bottom:source 所在层在 target 上方时 source.bottom→target.top; * 反之 source.top→target.bottom;同层时也用 top↔bottom,避免出现左右锚点连线。 */ export declare function buildTopologyEdgesFromConnections(rawConnections: RawTopologyDeviceConnection[], rawDevices: RawTopologyDevice[]): FloorMapEdge[]; /** * 一站式:原始设备数组 + 连接数组 → 阅读态 `FloorMapViewConfig`。 * `rawConnections` 未传或为空时不渲染连线,仅展示节点。 * * 此函数只做「全量自动布局」,不考虑已保存的 floor-plan 数据。需要做对账请用 * {@link reconcileTopologyView}。 */ export declare function buildTopologyFloorMapConfigFromDevices(rawDevices: RawTopologyDevice[], rawConnections?: RawTopologyDeviceConnection[]): { config: FloorMapViewConfig; dataSources: FloorMapDataSources; }; export interface ReconcileTopologyViewParams { rawDevices: RawTopologyDevice[]; rawConnections: RawTopologyDeviceConnection[]; /** 已保存的 sceneElements;首次进来传 undefined / 空数组 */ savedSceneElements?: FloorMapSceneElement[]; /** 已保存的 edges;用于复用 routing snapshot(其余字段从连接接口刷新) */ savedEdges?: FloorMapEdge[]; } export interface ReconcileTopologyViewResult { config: FloorMapViewConfig; dataSources: FloorMapDataSources; /** 此次 reconcile 新增的设备 id(首次进来 = 全部设备) */ addedDeviceIds: string[]; /** 已保存里 API 已经没有的 instanceId(ghost),渲染时按下线状态展示 */ ghostInstanceIds: string[]; /** 已保存里 API 已经没有的设备 id(ghostInstanceIds 反向解析后) */ ghostDeviceIds: string[]; /** 已存在并被保留位置的设备 id(debug 用) */ keptDeviceIds: string[]; } /** * 接入 floor-plan 的核心:把「已保存布局」「设备列表」「连接列表」对账成最终 view config。 * * 规则: * - 设备同时在 API + 已保存里:保留位置/尺寸,用 API 数据刷新 elementKind / name * - 设备只在 API(新设备):放到「新增区」auto-layout * - 设备只在已保存(接口已下线,ghost):保留 sceneElement,由 UI 侧渲染下线样式 * - 边:按当前 connections 接口重建;保留 savedEdges 的 routing snapshot(按 id 配对) * * 当 `savedSceneElements` 为空时退化为整体 auto-layout,等价于 `buildTopologyFloorMapConfigFromDevices`。 */ export declare function reconcileTopologyView(params: ReconcileTopologyViewParams): ReconcileTopologyViewResult;