This commit is contained in:
oneao committed 2026-04-06 21:15:11 +08:00
1 parent f08db1959b
commit c6671c8a8c
68 files changed
+13904 -1131

No files matched your search

@@ -3,6 +3,7 @@ package bootstrap
import (
"allapp-go/internal/bootstrap/boots"
"allapp-go/internal/config"
"allapp-go/pkg/db"
"allapp-go/pkg/logger"
"github.com/jackc/pgx/v5/pgxpool"
@@ -32,6 +33,8 @@ func NewApp() (*App, error) {
return nil, err
}
db.Init(pgsql)
// 其他组件
boots.InitUniqueId(cfg)
boots.InitJwt(cfg)
@@ -2,29 +2,33 @@ package bootstrap
import (
"allapp-go/internal/config"
"allapp-go/internal/errors"
"allapp-go/internal/middleware"
"allapp-go/internal/router"
"allapp-go/pkg/logger"
"fmt"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/recover"
"github.com/gofiber/fiber/v3/middleware/requestid"
)
func RunServer(cfg *config.Config) error {
app := fiber.New()
app := fiber.New(fiber.Config{
ErrorHandler: errors.ErrorHandler(),
})
// ===== middleware =====
app.Use(recover.New())
app.Use(requestid.New())
app.Use(middleware.Logger())
// ===== router =====
router.Setup(app)
router.SetupRouter(app)
addr := fmt.Sprintf(":%d", cfg.App.Port)
logger.Log.Info("服务启动")
// ❗ 关键:直接阻塞
return app.Listen(addr)
}
@@ -0,0 +1,10 @@
package errors
import "github.com/pkg/errors"
func WithStack(err error) error {
if err == nil {
return nil
}
return errors.WithStack(err)
}
@@ -0,0 +1,31 @@
package errors
import (
"allapp-go/internal/httpx"
"allapp-go/pkg/logger"
"errors"
"fmt"
"github.com/gofiber/fiber/v3"
"go.uber.org/zap"
)
func ErrorHandler() fiber.ErrorHandler {
return func(c fiber.Ctx, err error) error {
code := fiber.StatusInternalServerError
msg := "系统异常,请稍后再试!"
var e *fiber.Error
if errors.As(err, &e) {
code = e.Code
msg = e.Message
}
logger.FromCtx(c.Context()).Error("HTTP 请求异常",
zap.Int("status", code),
zap.String("error", fmt.Sprintf("%+v", err)),
)
return httpx.SystemError(c, msg)
}
}
@@ -0,0 +1,50 @@
package handle
import (
"allapp-go/internal/errors"
"allapp-go/internal/httpx"
"allapp-go/internal/types"
"allapp-go/pkg/db"
"github.com/gofiber/fiber/v3"
)
func LoadData(c fiber.Ctx) error {
var req types.LoadDataReq
err := httpx.BindAndValidate(c, &req)
if err != nil {
return errors.WithStack(err)
}
dbClient := db.New()
// 查询
data, err := dbClient.LoadData(c.Context(), req.ViewName, req.SearchCondition, req.OrderBy, req.SearchColumns, req.Args)
if err != nil {
return errors.WithStack(err)
}
return httpx.OK(c, data)
}
func LoadDataBySql(c fiber.Ctx) error {
var req types.LoadDataBySqlReq
err := httpx.BindAndValidate(c, &req)
if err != nil {
return errors.WithStack(err)
}
dbClient := db.New()
data, err := dbClient.LoadDataBySQL(c.Context(), req.Sql, req.Args)
if err != nil {
return errors.WithStack(err)
}
return httpx.OK(c, data)
}
@@ -0,0 +1,56 @@
package handle
import (
"allapp-go/internal/httpx"
"allapp-go/internal/types"
"allapp-go/pkg/db"
"github.com/gofiber/fiber/v3"
)
func SaveData(c fiber.Ctx) error {
var req []types.SaveDataReq
if err := httpx.BindAndValidate(c, &req); err != nil {
return err
}
if len(req) == 0 {
return httpx.OK(c, nil)
}
ctx := c.Context()
dbClient := db.New()
err := dbClient.WithTx(ctx, func(tx *db.Client) error {
for _, dataReq := range req {
tableName := dataReq.TableName
keyField := dataReq.KeyField
for _, insert := range dataReq.Inserts {
if err := tx.Insert(ctx, tableName, keyField, insert); err != nil {
return err
}
}
for _, update := range dataReq.Updates {
if err := tx.Update(ctx, tableName, keyField, update); err != nil {
return err
}
}
for _, del := range dataReq.Deletes {
if err := tx.Delete(ctx, tableName, keyField, del); err != nil {
return err
}
}
}
return nil
})
if err != nil {
return err
}
return httpx.OK(c, nil)
}
@@ -0,0 +1,20 @@
package httpx
import (
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v3"
)
var validate = validator.New()
func BindAndValidate(c fiber.Ctx, v any) error {
if err := c.Bind().Body(v); err != nil {
return err
}
if err := validate.Struct(v); err != nil {
return err
}
return nil
}
@@ -0,0 +1,63 @@
package httpx
import "github.com/gofiber/fiber/v3"
type Result struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
TrackId string `json:"track_id,omitempty"`
}
var BizCode = struct {
Success int // 成功
Unauthorized int // 未授权/Token失效
BusinessError int // 业务异常,例如参数错误、操作不允许
SystemError int // 系统异常,例如数据库崩溃、未知错误
}{
Success: 1000,
Unauthorized: 1001,
BusinessError: 2000,
SystemError: 3000,
}
// ------------------- 统一响应方法 -------------------
// Respond 返回通用响应,code和msg必填,data可选
func Respond(c fiber.Ctx, code int, msg string, data interface{}) error {
trackId := ""
if v := c.Context().Value("request_id"); v != nil {
if s, ok := v.(string); ok {
trackId = s
}
}
return c.JSON(Result{
Code: code,
Message: msg,
Data: data,
TrackId: trackId,
})
}
// ------------------- 便捷封装 -------------------
// OK 成功响应
func OK(c fiber.Ctx, data interface{}) error {
return Respond(c, BizCode.Success, "success", data)
}
// Fail 业务异常
func Fail(c fiber.Ctx, msg string) error {
return Respond(c, BizCode.BusinessError, msg, nil)
}
// SystemError 系统异常
func SystemError(c fiber.Ctx, msg string) error {
return Respond(c, BizCode.SystemError, msg, nil)
}
// Unauthorized 授权失败
func Unauthorized(c fiber.Ctx, msg string) error {
return Respond(c, BizCode.Unauthorized, msg, nil)
}
@@ -0,0 +1,47 @@
package middleware
import (
"allapp-go/internal/httpx"
"allapp-go/pkg/jwtx"
"strings"
"github.com/gofiber/fiber/v3"
)
const CtxUserIDKey = "user_id"
// Auth 登录校验中间件
func Auth() fiber.Handler {
return func(c fiber.Ctx) error {
token := strings.TrimSpace(c.Get("Token"))
if token == "" {
return httpx.Unauthorized(c, "未登录")
}
verifyToken, ok := jwtx.VerifyToken(c.Context(), token)
if !ok {
return httpx.Unauthorized(c, "登录已过期")
}
c.Locals(CtxUserIDKey, verifyToken.Data["user_id"])
return c.Next()
}
}
func GetUserID(c fiber.Ctx) (int64, error) {
v := c.Locals(CtxUserIDKey)
if v == nil {
return 0, httpx.Unauthorized(c, "登录已过期")
}
userID, ok := v.(int64)
if !ok {
return 0, httpx.Unauthorized(c, "登录已过期")
}
return userID, nil
}
@@ -1,22 +1,14 @@
package router
import (
"allapp-go/pkg/logger"
"allapp-go/internal/handle"
"github.com/gofiber/fiber/v3"
)
func Setup(app *fiber.App) {
// 健康检查
app.Get("/ping", func(c fiber.Ctx) error {
log := logger.FromCtx(c)
log.Info("测试")
return c.SendString("pong")
})
// 你后面可以这样分组:
// setupUserRoutes(app)
// setupOrderRoutes(app)
func SetupRouter(app *fiber.App) {
// ==================== data ====================
app.Post("/data/loadData", handle.LoadData)
app.Post("/data/loadDataBySql", handle.LoadDataBySql)
app.Post("/data/saveData", handle.SaveData)
}
@@ -0,0 +1,14 @@
package types
type LoadDataReq struct {
ViewName string `json:"view_name" validate:"required"`
SearchCondition string `json:"search_condition"`
OrderBy string `json:"order_by"`
SearchColumns []string `json:"search_columns"`
Args []any `json:"args"`
}
type LoadDataBySqlReq struct {
Sql string `json:"sql" validate:"required"`
Args []any `json:"args"`
}
@@ -0,0 +1,9 @@
package types
type SaveDataReq struct {
TableName string `json:"table_name"`
KeyField string `json:"key_field"`
Inserts []map[string]any `json:"inserts"`
Updates []map[string]any `json:"updates"`
Deletes []map[string]any `json:"deletes"`
}