import { defineStore } from 'pinia' import { ref } from 'vue' import { fetchFaultPartMap } from '../api/faultMap' import { getViewer } from '../three/instance' import type { FaultMapRow } from '../types' import { levelColor } from '../utils/level' import { useAlarmsStore } from './alarms' import { useModelStore } from './model' import { usePartsStore } from './parts' export const useFaultPartsStore = defineStore('faultParts', () => { const rows = ref([]) const loaded = ref(false) async function ensureLoaded(): Promise { if (loaded.value) return await reload() } async function reload(): Promise { rows.value = await fetchFaultPartMap() loaded.value = true } function splitPoints(value: string): string[] { return String(value || '') .split(/[|,]/) .map((item) => item.trim()) .filter(Boolean) } function clear(): void { getViewer()?.clearFaultColors() } /** 依据当前选中告警与当前模型,给命中的 3D 部件上故障等级色(临时、不持久化)。 */ function apply(): void { const alarms = useAlarmsStore() const partsStore = usePartsStore() const modelStore = useModelStore() const alarm = alarms.selected if (!alarm || !loaded.value) { clear() return } const model = modelStore.current const alarmPoints = splitPoints(alarm.device_point) const byLabel = new Map(partsStore.parts.map((part) => [part.label, part.id])) const hex = levelColor(alarm.alarm_level) const entries: Record = {} let sceneCamera: [number, number, number] | null = null let sceneTarget: [number, number, number] | null = null rows.value.forEach((row) => { if (row.model !== model || row.alarm_type !== alarm.alarm_type) return const rowPoints = splitPoints(row.device_point) if (rowPoints.length && !rowPoints.some((point) => alarmPoints.includes(point))) return const id = byLabel.get(row.part) if (id) entries[id] = hex if (!sceneCamera && row.camera && row.target) { sceneCamera = row.camera sceneTarget = row.target } }) const viewer = getViewer() viewer?.setFaultColors(entries) if (sceneCamera && sceneTarget) viewer?.flyToCamera(sceneCamera, sceneTarget) } return { rows, loaded, ensureLoaded, reload, apply, clear } })