| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import { ref } from 'vue';
- import { fetchTunnelInterpretation, fetchDeviceInterpretation } from './api';
- import { createTrigger, type TriggerHandle } from './useDataInterpretationTrigger';
- import type { TodoItem, ToolCallRecord } from './types';
- /** 数据解读 hook —— 调用后端 SSE 流式接口,实时追踪所有过程状态 */
- export function useDataInterpretation() {
- const loading = ref(false);
- const streamingText = ref('');
- const error = ref<string | null>(null);
- const threadId = ref('');
- const sessionId = ref('');
- // 过程状态
- const thinking = ref(false);
- const todos = ref<TodoItem[]>([]);
- const executingTools = ref<string[]>([]);
- const toolCalls = ref<ToolCallRecord[]>([]);
- /** 统一的事件处理 */
- function handleEvent(event: any) {
- switch (event.type) {
- case 'thinking':
- thinking.value = true;
- break;
- case 'executing':
- thinking.value = false;
- executingTools.value = event.tools || [];
- break;
- case 'tool_call':
- executingTools.value = [];
- toolCalls.value = [...toolCalls.value, { tool: event.tool || '', source: event.source || 'main', status: 'call' as const }];
- break;
- case 'tool_result':
- // 更新最近一条 tool_call 为 result 状态
- if (toolCalls.value.length > 0) {
- const last = toolCalls.value[toolCalls.value.length - 1];
- if (last.tool === event.tool && last.status === 'call') {
- last.status = 'result';
- }
- }
- break;
- case 'updated_todo_list':
- thinking.value = false;
- todos.value = event.todos || [];
- break;
- case 'token':
- thinking.value = false;
- if (event.content) {
- streamingText.value += event.content;
- }
- break;
- }
- }
- async function interpretTunnel(params: { tun_id: string; tun_name: string }) {
- loading.value = true;
- error.value = null;
- streamingText.value = '';
- thinking.value = false;
- todos.value = [];
- executingTools.value = [];
- toolCalls.value = [];
- try {
- const result = await fetchTunnelInterpretation(params, handleEvent);
- threadId.value = result.thread_id;
- sessionId.value = result.session_id;
- } catch (e: any) {
- const msg = e?.message || '数据解读请求失败';
- error.value = msg;
- throw e;
- } finally {
- loading.value = false;
- thinking.value = false;
- executingTools.value = [];
- }
- }
- async function interpretDevice(params: { device_id: string; device_name: string; device_type: string }) {
- loading.value = true;
- error.value = null;
- streamingText.value = '';
- thinking.value = false;
- todos.value = [];
- executingTools.value = [];
- toolCalls.value = [];
- try {
- const result = await fetchDeviceInterpretation(params, handleEvent);
- threadId.value = result.thread_id;
- sessionId.value = result.session_id;
- } catch (e: any) {
- const msg = e?.message || '数据解读请求失败';
- error.value = msg;
- throw e;
- } finally {
- loading.value = false;
- thinking.value = false;
- executingTools.value = [];
- }
- }
- function reset() {
- streamingText.value = '';
- error.value = null;
- threadId.value = '';
- sessionId.value = '';
- thinking.value = false;
- todos.value = [];
- executingTools.value = [];
- toolCalls.value = [];
- }
- return {
- loading,
- streamingText,
- error,
- threadId,
- sessionId,
- thinking,
- todos,
- executingTools,
- toolCalls,
- interpretTunnel,
- interpretDevice,
- reset,
- };
- }
- /**
- * 数据解读列表级便捷 Hook。
- * 整合了弹框状态 + 每行数据的悬浮触发器管理 + SSE 流式解读。
- *
- * @param mapParams - 将列表行数据映射为接口请求参数
- *
- * 使用:在列表/表格/卡片组等 v-for 场景的组件中调用一次即可。
- */
- export function useDataInterpretationList(
- mapParams: (item: any) => { tun_id: string; tun_name: string } | { device_id: string; device_name: string; device_type: string }
- ) {
- const { loading, streamingText, error, threadId, sessionId, thinking, todos, executingTools, toolCalls, interpretTunnel, interpretDevice, reset } =
- useDataInterpretation();
- const modalVisible = ref(false);
- const triggerMap = new Map<string, TriggerHandle>();
- function getTrigger(id: string): TriggerHandle {
- if (!triggerMap.has(id)) {
- triggerMap.set(id, createTrigger());
- }
- return triggerMap.get(id)!;
- }
- async function handleInterpret(item: any) {
- modalVisible.value = true;
- const params = mapParams(item);
- if ('tun_id' in params) {
- await interpretTunnel(params);
- } else {
- await interpretDevice(params);
- }
- }
- function handleClose() {
- modalVisible.value = false;
- reset();
- }
- return {
- modalVisible,
- loading,
- streamingText,
- error,
- threadId,
- sessionId,
- thinking,
- todos,
- executingTools,
- toolCalls,
- getTrigger,
- handleInterpret,
- handleClose,
- };
- }
|