feat: 持久化 AI 审查结果,文件级内联展示与页面集成
This commit is contained in:
+68
-10
@@ -84,23 +84,18 @@ func (h *ReviewHandler) Review(c *gin.Context) {
|
||||
h.db.Exec(`UPDATE repositories SET last_used = datetime('now') WHERE id = ?`, id)
|
||||
|
||||
// Run AI review
|
||||
err = services.GenerateReview(h.db, localPath, req.Base, req.Head, topN, sendEvent)
|
||||
reviewResult, err := services.GenerateReview(h.db, localPath, req.Base, req.Head, topN, sendEvent)
|
||||
if err != nil {
|
||||
sendEvent("error", map[string]interface{}{"message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Save analysis to DB
|
||||
resultData := map[string]interface{}{
|
||||
"base": req.Base,
|
||||
"head": req.Head,
|
||||
"top_n": topN,
|
||||
}
|
||||
resultJSON, _ := json.Marshal(resultData)
|
||||
result, err := h.db.Exec(`INSERT INTO analyses (repo_id, type, base_ref, head_ref, result) VALUES (?, 'code_review', ?, ?, ?)`,
|
||||
// Save analysis to DB with full review result
|
||||
resultJSON, _ := json.Marshal(reviewResult)
|
||||
res, err := h.db.Exec(`INSERT INTO analyses (repo_id, type, base_ref, head_ref, result) VALUES (?, 'code_review', ?, ?, ?)`,
|
||||
id, req.Base, req.Head, string(resultJSON))
|
||||
if err == nil {
|
||||
analysisID, _ := result.LastInsertId()
|
||||
analysisID, _ := res.LastInsertId()
|
||||
sendEvent("analysis_saved", map[string]interface{}{
|
||||
"analysis_id": analysisID,
|
||||
})
|
||||
@@ -166,6 +161,69 @@ func (h *ReviewHandler) GetNotes(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, notes)
|
||||
}
|
||||
|
||||
// ListReviews handles GET /api/repos/:id/review/analyses — list past code review analyses.
|
||||
func (h *ReviewHandler) ListReviews(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
rows, err := h.db.Query(`SELECT id, base_ref, head_ref, result, created_at FROM analyses WHERE repo_id = ? AND type = 'code_review' ORDER BY created_at DESC`, id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var analyses []map[string]interface{}
|
||||
for rows.Next() {
|
||||
var aid int64
|
||||
var baseRef, headRef, result string
|
||||
var createdAt string
|
||||
if err := rows.Scan(&aid, &baseRef, &headRef, &result, &createdAt); err != nil {
|
||||
continue
|
||||
}
|
||||
analyses = append(analyses, map[string]interface{}{
|
||||
"id": aid,
|
||||
"base_ref": baseRef,
|
||||
"head_ref": headRef,
|
||||
"created_at": createdAt,
|
||||
})
|
||||
}
|
||||
|
||||
if analyses == nil {
|
||||
analyses = []map[string]interface{}{}
|
||||
}
|
||||
c.JSON(http.StatusOK, analyses)
|
||||
}
|
||||
|
||||
// GetReview handles GET /api/repos/:id/review/analyses/:aid — get a single review with full result.
|
||||
func (h *ReviewHandler) GetReview(c *gin.Context) {
|
||||
aid := c.Param("aid")
|
||||
|
||||
var result, baseRef, headRef, createdAt string
|
||||
err := h.db.QueryRow(`SELECT result, base_ref, head_ref, created_at FROM analyses WHERE id = ? AND type = 'code_review'`, aid).Scan(&result, &baseRef, &headRef, &createdAt)
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "analysis not found"})
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Parse the result JSON to include structured data
|
||||
var reviewResult interface{}
|
||||
if err := json.Unmarshal([]byte(result), &reviewResult); err != nil {
|
||||
reviewResult = result
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"id": aid,
|
||||
"base_ref": baseRef,
|
||||
"head_ref": headRef,
|
||||
"created_at": createdAt,
|
||||
"result": reviewResult,
|
||||
})
|
||||
}
|
||||
|
||||
// GeneratePDF handles POST /api/repos/:id/review/pdf — generate and download a PDF report.
|
||||
func (h *ReviewHandler) GeneratePDF(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
Reference in New Issue
Block a user