faultParts.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { defineStore } from 'pinia'
  2. import { ref } from 'vue'
  3. import { fetchFaultPartMap } from '../api/faultMap'
  4. import { getViewer } from '../three/instance'
  5. import type { FaultMapRow } from '../types'
  6. import { levelColor } from '../utils/level'
  7. import { useAlarmsStore } from './alarms'
  8. import { useModelStore } from './model'
  9. import { usePartsStore } from './parts'
  10. export const useFaultPartsStore = defineStore('faultParts', () => {
  11. const rows = ref<FaultMapRow[]>([])
  12. const loaded = ref(false)
  13. async function ensureLoaded(): Promise<void> {
  14. if (loaded.value) return
  15. await reload()
  16. }
  17. async function reload(): Promise<void> {
  18. rows.value = await fetchFaultPartMap()
  19. loaded.value = true
  20. }
  21. function splitPoints(value: string): string[] {
  22. return String(value || '')
  23. .split(/[|,]/)
  24. .map((item) => item.trim())
  25. .filter(Boolean)
  26. }
  27. function clear(): void {
  28. getViewer()?.clearFaultColors()
  29. }
  30. /** 依据当前选中告警与当前模型,给命中的 3D 部件上故障等级色(临时、不持久化)。 */
  31. function apply(): void {
  32. const alarms = useAlarmsStore()
  33. const partsStore = usePartsStore()
  34. const modelStore = useModelStore()
  35. const alarm = alarms.selected
  36. if (!alarm || !loaded.value) {
  37. clear()
  38. return
  39. }
  40. const model = modelStore.current
  41. const alarmPoints = splitPoints(alarm.device_point)
  42. const byLabel = new Map(partsStore.parts.map((part) => [part.label, part.id]))
  43. const hex = levelColor(alarm.alarm_level)
  44. const entries: Record<string, string> = {}
  45. let sceneCamera: [number, number, number] | null = null
  46. let sceneTarget: [number, number, number] | null = null
  47. rows.value.forEach((row) => {
  48. if (row.model !== model || row.alarm_type !== alarm.alarm_type) return
  49. const rowPoints = splitPoints(row.device_point)
  50. if (rowPoints.length && !rowPoints.some((point) => alarmPoints.includes(point))) return
  51. const id = byLabel.get(row.part)
  52. if (id) entries[id] = hex
  53. if (!sceneCamera && row.camera && row.target) {
  54. sceneCamera = row.camera
  55. sceneTarget = row.target
  56. }
  57. })
  58. const viewer = getViewer()
  59. viewer?.setFaultColors(entries)
  60. if (sceneCamera && sceneTarget) viewer?.flyToCamera(sceneCamera, sceneTarget)
  61. }
  62. return { rows, loaded, ensureLoaded, reload, apply, clear }
  63. })