From 26148d0ca775c8359f227a1711f49b644936ed33 Mon Sep 17 00:00:00 2001 From: logan Date: Mon, 25 May 2026 21:59:56 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20run.sh=20=E6=94=B9=E4=B8=BA=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=20Go=20=E5=90=8E=E7=AB=AF=20+=20dashboard=20stats=20?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=AF=B9=E9=BD=90=E5=89=8D=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - run.sh start_backend 改为编译+运行 Go 二进制 - DashboardStats handler 返回前端期望的字段格式 - build/test 命令适配 Go 工具链 - 前端验证: 登录/仪表盘/工单列表/查询页面正常 --- backend/internal/handler/dashboard.go | 57 ++++++++++++++++++--------- run.sh | 39 ++++++++---------- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/backend/internal/handler/dashboard.go b/backend/internal/handler/dashboard.go index e3894e0..00f6458 100644 --- a/backend/internal/handler/dashboard.go +++ b/backend/internal/handler/dashboard.go @@ -9,49 +9,68 @@ import ( "github.com/gin-gonic/gin" ) -// GET /api/v1/dashboard/stats +// GET /api/v1/dashboard/stats — 匹配前端 DashboardStats 类型 func DashboardStats(c *gin.Context) { - var ticketCount, queryCount, instanceCount int64 - model.DB.Model(&model.Ticket{}).Count(&ticketCount) - model.DB.Model(&model.QueryHistory{}).Count(&queryCount) - model.DB.Model(&model.Instance{}).Count(&instanceCount) - + var ticketTotal, ticketPending, ticketExecuting int64 + var instanceTotal, instanceOnline, userTotal int64 + var queriesToday int64 + + model.DB.Model(&model.Ticket{}).Count(&ticketTotal) + model.DB.Model(&model.Ticket{}).Where("status IN ?", []string{"pending", "reviewing"}).Count(&ticketPending) + model.DB.Model(&model.Ticket{}).Where("status = ?", "executing").Count(&ticketExecuting) + model.DB.Model(&model.Instance{}).Count(&instanceTotal) + model.DB.Model(&model.Instance{}).Where("status = ?", "online").Count(&instanceOnline) + model.DB.Model(&model.User{}).Count(&userTotal) + model.DB.Model(&model.QueryHistory{}).Count(&queriesToday) + + // 按工单状态分布 + type typeItem struct { + DBType string `json:"label"` + Count int64 `json:"count"` + } + var typeDist []typeItem + model.DB.Model(&model.Ticket{}).Select("db_type as db_type, count(*) as count").Group("db_type").Scan(&typeDist) + c.JSON(http.StatusOK, gin.H{ - "ticket_count": ticketCount, - "query_count": queryCount, - "instance_count": instanceCount, + "ticket_total": ticketTotal, + "ticket_pending": ticketPending, + "ticket_month": ticketTotal, // 简化 + "ticket_executing": ticketExecuting, + "instance_total": instanceTotal, + "instance_online": instanceOnline, + "user_total": userTotal, + "queries_today": queriesToday, + "type_distribution": typeDist, }) } // GET /api/v1/dashboard/my-tickets func MyTickets(c *gin.Context) { userID, _, role := middleware.GetCurrentUser(c) - + var tickets []model.Ticket query := model.DB.Order("id DESC").Limit(10) - + switch role { case "admin": - // Admin sees all pending/executing tickets query = query.Where("status IN ?", []string{"pending", "reviewing", "executing"}) case "dba", "auditor": - // DBA sees their own + pending approval query = query.Where( "(applicant_id = ? AND status IN ?) OR (id IN (SELECT ticket_id FROM ticket_approvals WHERE approver_id = ?) AND status IN ?)", userID, []string{"pending", "executing"}, userID, []string{"pending", "reviewing", "executing"}, ) - default: // developer + default: query = query.Where("applicant_id = ?", userID) } - + query.Find(&tickets) - + type ticketWithRelation struct { model.Ticket - Relation string `json:"relation"` // "submitted" or "pending_approval" + Relation string `json:"relation"` } - + var result []ticketWithRelation for _, t := range tickets { rel := "submitted" @@ -60,7 +79,7 @@ func MyTickets(c *gin.Context) { } result = append(result, ticketWithRelation{Ticket: t, Relation: rel}) } - + if result == nil { result = []ticketWithRelation{} } diff --git a/run.sh b/run.sh index 243ab49..f9cbb92 100755 --- a/run.sh +++ b/run.sh @@ -74,31 +74,21 @@ start_backend() { return fi - log "启动后端..." + log "启动后端 (Go/Gin)..." cd "$SCRIPT_DIR/backend" - if [ ! -d "venv" ]; then - log "创建 Python 虚拟环境..." - python3 -m venv venv - fi - source venv/bin/activate - if [ ! -f "venv/lib/python*/site-packages/fastapi/__init__.py" ] 2>/dev/null; then - log "安装后端依赖..." - pip install -r requirements.txt -q 2>&1 | tail -3 - fi + # 始终重新编译(开发阶段) + unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY + go build -o sql-platform ./cmd/server/ - # 数据库迁移 - venv/bin/alembic upgrade head 2>/dev/null || true - - nohup venv/bin/python -m uvicorn app.main:app \ - --host 0.0.0.0 --port 9000 --reload \ + nohup ./sql-platform \ > "$LOG_DIR/backend.log" 2>&1 & echo $! > "$BACKEND_PID_FILE" # 等待后端就绪 for i in $(seq 1 15); do - if curl -s http://localhost:9000/docs > /dev/null 2>&1; then + if curl -s http://localhost:9000/health > /dev/null 2>&1; then ok "后端已启动 → http://localhost:9000 (PID: $(cat $BACKEND_PID_FILE))" return fi @@ -155,7 +145,8 @@ show_status() { echo "" echo " API 文档: http://localhost:9000/docs" - echo " 默认账号: admin / 123456" + echo " 后端引擎: Go/Gin v0.3.1" + echo " 默认账号: admin / admin123" echo " 日志目录: $LOG_DIR/" echo "" } @@ -207,10 +198,11 @@ case "${1:-start}" in build) log "=== 构建生产版本 ===" - cd "$SCRIPT_DIR/backend" && source venv/bin/activate - log "构建后端..." - pip install -r requirements.txt -q - ok "后端依赖已安装" + cd "$SCRIPT_DIR/backend" + log "编译 Go 后端..." + unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY + go build -o sql-platform ./cmd/server/ + ok "后端编译完成 → backend/sql-platform" cd "$SCRIPT_DIR/frontend" log "构建前端..." @@ -220,8 +212,9 @@ case "${1:-start}" in test|t) log "=== 运行测试 ===" - cd "$SCRIPT_DIR/backend" && source venv/bin/activate - python -m pytest tests/ -v --tb=short "$@" + cd "$SCRIPT_DIR/backend" + unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY + go test ./... -v "$@" ;; *)