fix: restore topology view and mapping progress state

This commit is contained in:
ji ruo committed 2026-10-28 21:10:43 +08:00
1 parent 495ab57ba7
commit 14ebf44362
4 files changed
+59 -3

No files matched your search

+1
View File
@@ -767,6 +767,7 @@ func (s *Server) Handler() http.Handler {
mux.HandleFunc("GET /api/tasks/{id}/coverage", s.taskCoverage)
mux.HandleFunc("GET /api/tasks/{id}/coverage-graph", s.taskCoverageGraph)
mux.HandleFunc("POST /api/tasks/{id}/asset-mapping", s.taskAssetMapping)
mux.HandleFunc("GET /api/tasks/{id}/asset-mapping/status", s.taskAssetMappingStatus)
mux.HandleFunc("GET /api/tasks/{id}/asset-refs", s.taskAssetRefs)
mux.HandleFunc("POST /api/tasks/{id}/assets", s.attachTaskAssets)
mux.HandleFunc("DELETE /api/tasks/{id}/assets/{assetID}", s.detachTaskAsset)
+26
View File
@@ -80,3 +80,29 @@ func (s *Server) taskAssetMapping(w http.ResponseWriter, r *http.Request) {
"status": "accepted", "agent_key": "asset_mapper", "conversation_id": conversation.ID,
})
}
func (s *Server) taskAssetMappingStatus(w http.ResponseWriter, r *http.Request) {
t, ok := s.m.Task(r.PathValue("id"))
if !ok {
writeErr(w, http.StatusNotFound, "task not found")
return
}
conversations, err := s.m.pg.ListConversations()
if err != nil {
writeErr(w, http.StatusInternalServerError, err.Error())
return
}
title := fmt.Sprintf("资产梳理 · 任务 #%s", t.ID)
for _, conversation := range conversations {
if conversation.AgentKey != "asset_mapper" || conversation.Title != title {
continue
}
busyKey := s.convBusyKey(conversation.ID)
s.chatMu.Lock()
running := s.chatBusy[busyKey]
s.chatMu.Unlock()
writeJSON(w, http.StatusOK, map[string]any{"running": running, "conversation_id": conversation.ID})
return
}
writeJSON(w, http.StatusOK, map[string]any{"running": false})
}
@@ -594,6 +594,26 @@ function GraphInner({ taskId, coverageEnabled = true }: { taskId: string; covera
fetchGraph();
}, [fetchGraph]);
React.useEffect(() => {
let cancelled = false;
api
.assetMappingStatus(taskId)
.then((status) => {
if (cancelled) return;
setMapping(status.running);
setMappingConversationId(status.conversation_id ?? null);
})
.catch(() => {
/* status is best effort; the graph remains usable */
});
setActivePath([]);
setSelectedAsset(null);
setSelectedFoldId(null);
return () => {
cancelled = true;
};
}, [taskId]);
const { renderNodes, renderEdges } = React.useMemo(
() =>
data
@@ -631,9 +651,16 @@ function GraphInner({ taskId, coverageEnabled = true }: { taskId: string; covera
graph.setData(gDataRef.current);
// render() 异步跑布局;若组件在布局落地前被卸载/销毁,g6 会在已清空的
// context 上访问 transform 抛错。这是纯 teardown 竞态,吞掉它,不影响功能。
void graph.render().catch((err) => {
if (!graph.destroyed) console.error("[coverage-graph] render:", err);
});
void graph
.render()
.then(() => {
if (graph.destroyed) return;
const active = gDataRef.current.nodes.filter((node) => node.active).map((node) => node.id);
return active.length > 0 ? graph.focusElement(active) : graph.fitView();
})
.catch((err) => {
if (!graph.destroyed) console.error("[coverage-graph] render:", err);
});
}, []);
// 建图(一次)。动态 import 避开 SSR/静态导出期的 window 依赖。
+2
View File
@@ -453,6 +453,8 @@ export const api = {
taskCoverageGraph: (id: string) => get<CoverageGraphData>(`/tasks/${id}/coverage-graph`),
startAssetMapping: (id: string) =>
post<{ status: string; agent_key: string; conversation_id: number }>(`/tasks/${id}/asset-mapping`, {}),
assetMappingStatus: (id: string) =>
get<{ running: boolean; conversation_id?: number }>(`/tasks/${id}/asset-mapping/status`),
// 全局 llm_usage 聚合(仪表盘新版 token 视图):按 profile 总量 + 按天分桶。
usageStats: (days = 365) => get<UsageStats>(`/tokens/usage?days=${days}`),
// ---- 目标管理(总览)----