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
@@ -483,6 +483,7 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("POST /api/tasks", s.createTask)
|
||||
mux.HandleFunc("GET /api/tasks/{id}", s.getTask)
|
||||
mux.HandleFunc("GET /api/tasks/{id}/coverage", s.taskCoverage)
|
||||
mux.HandleFunc("GET /api/tasks/{id}/coverage-graph", s.taskCoverageGraph)
|
||||
mux.HandleFunc("GET /api/tasks/{id}/scope", s.taskScopeList)
|
||||
mux.HandleFunc("POST /api/tasks/{id}/control", s.control)
|
||||
mux.HandleFunc("POST /api/active", s.setActive)
|
||||
@@ -1107,6 +1108,28 @@ func (s *Server) taskCoverage(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, 200, cov)
|
||||
}
|
||||
|
||||
// taskCoverageGraph returns the force-directed asset coverage graph for a task:
|
||||
// all in-scope assets (每种类型) + 连接用的根域名/公司节点, each carrying tested/in_scope.
|
||||
func (s *Server) taskCoverageGraph(w http.ResponseWriter, r *http.Request) {
|
||||
t, ok := s.m.Task(r.PathValue("id"))
|
||||
if !ok {
|
||||
writeErr(w, 404, "task not found")
|
||||
return
|
||||
}
|
||||
as := s.m.Assets()
|
||||
if as == nil {
|
||||
writeErr(w, 503, "asset store 未启用")
|
||||
return
|
||||
}
|
||||
taskID, _ := strconv.ParseInt(t.ID, 10, 64)
|
||||
g, err := as.BuildCoverageGraph(taskID, t.ExpID)
|
||||
if err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, 200, g)
|
||||
}
|
||||
|
||||
// taskScopeList returns a task's scope rows (coverage denominator sources).
|
||||
func (s *Server) taskScopeList(w http.ResponseWriter, r *http.Request) {
|
||||
t, ok := s.m.Task(r.PathValue("id"))
|
||||
|
||||
Reference in new issue
Block a user