feat: 初始化平台总后台与核心API
This commit is contained in:
107
backend/internal/http/router.go
Normal file
107
backend/internal/http/router.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// Package http 提供平台总后台的 HTTP 路由和统一响应。
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.apinb.com/heqiapp/platforms/backend/internal/platform"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// NewRouter 注册首期平台总后台所需的只读列表、仪表盘与气站创建接口。
|
||||
func NewRouter(pool *pgxpool.Pool, logger *slog.Logger) http.Handler {
|
||||
repository := platform.NewRepository(pool)
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("GET /healthz", func(writer http.ResponseWriter, request *http.Request) {
|
||||
writeJSON(writer, http.StatusOK, map[string]any{"status": "ok"})
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/dashboard/overview", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.DashboardOverview(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/org/gas-station", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListOrgGasStation(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("POST /api/v1/org/gas-station", func(writer http.ResponseWriter, request *http.Request) {
|
||||
var body struct {
|
||||
StationCode string `json:"stationCode"`
|
||||
Name string `json:"name"`
|
||||
Principal string `json:"principal"`
|
||||
ServiceArea string `json:"serviceArea"`
|
||||
}
|
||||
if err := json.NewDecoder(request.Body).Decode(&body); err != nil || body.StationCode == "" || body.Name == "" || body.Principal == "" || body.ServiceArea == "" {
|
||||
writeError(writer, http.StatusBadRequest, "参数不完整:站点编码、名称、负责人和服务区域均为必填")
|
||||
return
|
||||
}
|
||||
respondRepositoryWithStatus(writer, request, logger, http.StatusCreated, func() (any, error) {
|
||||
return repository.CreateOrgGasStation(request.Context(), body.StationCode, body.Name, body.Principal, body.ServiceArea)
|
||||
})
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/org/delivery-point", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListOrgDeliveryPoint(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/org/service-person", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListOrgServicePerson(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/idn/account", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListIdnAccount(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/saf/event", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListSafEvent(request.Context()) })
|
||||
})
|
||||
|
||||
return requestLogger(cors(mux), logger)
|
||||
}
|
||||
|
||||
func respondRepository(writer http.ResponseWriter, request *http.Request, logger *slog.Logger, query func() (any, error)) {
|
||||
respondRepositoryWithStatus(writer, request, logger, http.StatusOK, query)
|
||||
}
|
||||
|
||||
func respondRepositoryWithStatus(writer http.ResponseWriter, request *http.Request, logger *slog.Logger, status int, query func() (any, error)) {
|
||||
result, err := query()
|
||||
if err != nil {
|
||||
logger.Error("处理平台 API 请求失败", "method", request.Method, "path", request.URL.Path, "error", err)
|
||||
writeError(writer, http.StatusInternalServerError, "服务暂不可用,请稍后重试")
|
||||
return
|
||||
}
|
||||
writeJSON(writer, status, map[string]any{"data": result})
|
||||
}
|
||||
|
||||
func writeJSON(writer http.ResponseWriter, status int, data any) {
|
||||
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
writer.WriteHeader(status)
|
||||
_ = json.NewEncoder(writer).Encode(data)
|
||||
}
|
||||
|
||||
func writeError(writer http.ResponseWriter, status int, message string) {
|
||||
writeJSON(writer, status, map[string]any{"error": message})
|
||||
}
|
||||
|
||||
func cors(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
|
||||
writer.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
|
||||
writer.Header().Set("Access-Control-Allow-Headers", "Content-Type,Idempotency-Key")
|
||||
if request.Method == http.MethodOptions {
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(writer, request)
|
||||
})
|
||||
}
|
||||
|
||||
func requestLogger(next http.Handler, logger *slog.Logger) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
requestID, err := uuid.NewV7()
|
||||
if err == nil {
|
||||
writer.Header().Set("X-Request-Id", requestID.String())
|
||||
}
|
||||
startedAt := time.Now()
|
||||
next.ServeHTTP(writer, request)
|
||||
logger.Info("平台 API 请求完成", "method", request.Method, "path", request.URL.Path, "duration", time.Since(startedAt).String())
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user