Files
Atlas/web/src/composables/useInvoke.ts
T
renjue f26f334a2d
CI / docker (push) Failing after 2m7s
实现 Atlas AI 平台一期能力并完成品牌化改造。
引入用户端对话/生图与管理端 Provider 配置,统一 invoke 编排、Gateway、请求日志与模型管理;前端按设计规范拆分布局,Go module 更名为 github.com/rose_cat707/Atlas;生图长任务进度改为 SSE 推送,后端仍轮询上游。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-29 20:18:37 +08:00

83 lines
2.1 KiB
TypeScript

import { onMounted, onUnmounted, ref } from 'vue'
import api from '@/api/client'
export interface TaskItem {
id: number
status: string
progress: number
result_json: string
error: string
}
const terminalStatuses = new Set(['succeeded', 'failed', 'canceled'])
export function useInvoke(serviceType: string) {
const activeTasks = ref<TaskItem[]>([])
const streams = new Map<number, EventSource>()
function upsertTask(task: TaskItem) {
const idx = activeTasks.value.findIndex((t) => t.id === task.id)
if (idx >= 0) activeTasks.value[idx] = task
else activeTasks.value.push(task)
}
function closeStream(taskId: number) {
const es = streams.get(taskId)
if (es) {
es.close()
streams.delete(taskId)
}
}
function watchTask(taskId: number) {
if (streams.has(taskId)) return
const es = new EventSource(`/api/v1/user/tasks/${taskId}/events`, { withCredentials: true })
streams.set(taskId, es)
es.addEventListener('task', (ev) => {
const task = JSON.parse(ev.data) as TaskItem
upsertTask(task)
if (terminalStatuses.has(task.status)) {
closeStream(taskId)
}
})
es.addEventListener('done', () => closeStream(taskId))
es.onerror = () => closeStream(taskId)
}
async function loadActiveTasks() {
const res = await api.get<{ items: TaskItem[] }>('/user/tasks/active', {
params: { service_type: serviceType },
})
activeTasks.value = res.data.items
for (const t of res.data.items) {
watchTask(t.id)
}
}
async function generate(params: Record<string, unknown>, mode: 'sync' | 'async', model: string) {
const res = await api.post('/user/generate', {
service_type: serviceType,
params,
mode,
model,
})
if (mode === 'async' && res.data.task_id) {
watchTask(res.data.task_id)
}
return res.data
}
async function cancelTask(taskId: number) {
await api.post(`/user/tasks/${taskId}/cancel`)
}
onMounted(loadActiveTasks)
onUnmounted(() => {
streams.forEach((es) => es.close())
streams.clear()
})
return { activeTasks, generate, loadActiveTasks, cancelTask, watchTask }
}