feat(coverage): 任务新增「资产覆盖图」力导向图 tab
后端(只读,无迁移):
- db BuildCoverageGraph(taskID,expID) 复用 covTargetCTE 拉范围内全部类型资产 +
tested 标记,补连接节点(缺失根域名/公司,灰),按字段派生 child→parent 边
- server GET /api/tasks/{id}/coverage-graph
前端:
- 新 tab coverage-graph-tab:xyflow 渲染 + d3-force 静态力导向布局
- 已测=实色高亮、范围内未测=灰、范围外连接节点=灰虚线;点节点看详情抽屉
- 折叠/分页:同父同类型子节点默认展示 20(已测优先),超出收进折叠节点,
抽屉「展示更多(+20)」把下一批拉进图;布局仅在可见集合变化时重算
- types/api + d3-force 依赖声明 + 注册 tab
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
4c4f65f40a
commit
c396674d2b
8 files changed
+970
-5
No files matched your search
+4
-1
@@ -11,7 +11,7 @@ import type {
|
||||
PromptVersion, MCPServer, MCPTool, SkillItem, TokenUsage, TokenTotal, DailyTokenBucket,
|
||||
Tool, Conversation, AgentTrigger,
|
||||
InterceptRule, InterceptPending, InterceptApprovalRow,
|
||||
TaskAssetView, SSProject, SSTask, ConvTokenSummary,
|
||||
TaskAssetView, SSProject, SSTask, ConvTokenSummary, CoverageGraphData,
|
||||
CommandRecord, LLMRecordItem, LLMRecordDetail,
|
||||
} from "@/lib/types";
|
||||
|
||||
@@ -124,6 +124,9 @@ export const api = {
|
||||
pct: number | null;
|
||||
by_type: { type: string; total: number; tested: number }[];
|
||||
}>(`/tasks/${id}/coverage`),
|
||||
// 资产覆盖图:范围内全部资产 + 连接用的根域名/公司节点,含 tested/in_scope。
|
||||
taskCoverageGraph: (id: string) =>
|
||||
get<CoverageGraphData>(`/tasks/${id}/coverage-graph`),
|
||||
|
||||
// ---- assets ----
|
||||
// Server-side paginated: pass limit/offset, get back the page + full match total.
|
||||
|
||||
@@ -133,6 +133,38 @@ export interface Asset {
|
||||
last_seen: string;
|
||||
}
|
||||
|
||||
// ---- Asset coverage graph (per task) ----
|
||||
// 力导向「资产覆盖图」的一个节点。key 唯一:资产="a:<id>"、公司="c:<id>"、
|
||||
// 无资产行的根域名="r:<domain>"。in_scope=false 的是仅用于连线的灰色上下文节点。
|
||||
export interface CoverageGraphNode {
|
||||
key: string;
|
||||
kind: "company" | "root_domain" | "subdomain" | "ip" | "service" | "app" | "endpoint";
|
||||
label: string;
|
||||
tested: boolean;
|
||||
in_scope: boolean;
|
||||
asset_id?: number;
|
||||
company_id?: number;
|
||||
domain?: string;
|
||||
root_domain?: string;
|
||||
ip?: string;
|
||||
url?: string;
|
||||
port?: number;
|
||||
service_type?: string;
|
||||
app_name?: string;
|
||||
page_title?: string;
|
||||
status_code?: number;
|
||||
}
|
||||
|
||||
export interface CoverageGraphEdge {
|
||||
src: string;
|
||||
dst: string;
|
||||
}
|
||||
|
||||
export interface CoverageGraphData {
|
||||
nodes: CoverageGraphNode[];
|
||||
edges: CoverageGraphEdge[];
|
||||
}
|
||||
|
||||
// 公司资产范围规则的一条(归属唯一真值来源)。
|
||||
export interface ScopeRow {
|
||||
id: number;
|
||||
|
||||
Reference in new issue
Block a user