feat: v0.3.1 — Go/Gin 后端重写 + gh-ost 集成
架构变更: - Python/FastAPI → Go/Gin 重写(Python 后端保留在 backend-python/) - GORM + SQLite(兼容现有数据库表结构) - JWT 认证 + RBAC 权限中间件 Go 后端结构: - cmd/server/main.go — 入口,端口 9000 - config/config.go — 环境变量配置 - internal/model/ — GORM 模型(30张表,完全兼容 SQLite) - internal/handler/ — auth/instance/ticket/dashboard/ghost handler - internal/middleware/ — JWT 认证 + CORS - internal/ghost/ — gh-ost 集成模块(同步/异步执行,任务管理) - router/router.go — API 路由注册(/api/v1/...) gh-ost 集成: - RunGhOst() 同步执行 - RunGhOstAsync() 异步执行 + 进度追踪 - TaskManager 管理多个并发任务 - API: POST /ghost/dry-run, /ghost/execute, GET /ghost/status/:taskId 核心 API 已对齐: - POST /auth/login (JWT) - GET /dashboard/stats, /dashboard/my-tickets - GET /tickets/statistics, CRUD + approve/execute - GET/POST/PUT/DELETE /instances - GET /users, /audit-rules, /announcements, /settings 已验证: - 登录 admin/admin123 ✅ - Dashboard 99工单/110查询/4实例 ✅ - 工单统计按角色过滤 ✅
This commit is contained in:
1 parent
43d1f3a234
commit
ca308e277d
202 files changed
+2265
-51181
No files matched your search
@@ -0,0 +1,68 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"sql-platform/internal/middleware"
|
||||
"sql-platform/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GET /api/v1/dashboard/stats
|
||||
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)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"ticket_count": ticketCount,
|
||||
"query_count": queryCount,
|
||||
"instance_count": instanceCount,
|
||||
})
|
||||
}
|
||||
|
||||
// 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
|
||||
query = query.Where("applicant_id = ?", userID)
|
||||
}
|
||||
|
||||
query.Find(&tickets)
|
||||
|
||||
type ticketWithRelation struct {
|
||||
model.Ticket
|
||||
Relation string `json:"relation"` // "submitted" or "pending_approval"
|
||||
}
|
||||
|
||||
var result []ticketWithRelation
|
||||
for _, t := range tickets {
|
||||
rel := "submitted"
|
||||
if t.ApplicantID != userID {
|
||||
rel = "pending_approval"
|
||||
}
|
||||
result = append(result, ticketWithRelation{Ticket: t, Relation: rel})
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
result = []ticketWithRelation{}
|
||||
}
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
Reference in new issue
Block a user