import { computed, inject, type InjectionKey, type MaybeRefOrGetter } from 'vue' import { usePolling } from '../../composables/usePolling' import { projectsApi } from './api' import type { ProjectDetail } from './types' import type { Checkpoint } from '../workflows/types' import type { Ref } from 'vue' /** 同一项目的各个 graph 共用一份查询,避免每个面板重复请求。 */ export function useProjectData(id: Ref, interval: MaybeRefOrGetter = 6000) { const query = usePolling( id, async (projectId, signal) => { const [project, checkpoints] = await Promise.all([ projectsApi.detail(projectId, signal), projectsApi.checkpoints(projectId, signal) ]) return { project, checkpoints } }, interval ) const project = computed(() => query.data.value?.project ?? null) const checkpoints = computed(() => query.data.value?.checkpoints ?? []) return { ...query, project, checkpoints } } /** 项目布局向子页面提供的类型安全上下文。 */ export const projectContextKey: InjectionKey> = Symbol('project-context') /** 读取项目上下文,错误布局在开发阶段立即暴露。 */ export function useProjectContext() { const context = inject(projectContextKey) if (!context) throw new Error('项目页面必须位于 ProjectLayout 中') return context }