Initial commit: 网络验证平台
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
package main
|
||||
|
||||
// 重要提示:请始终从 backend/ 目录运行此服务
|
||||
// 正确的运行方式:
|
||||
// cd d:\Code\verify\verification-platform\backend
|
||||
// go run cmd/main.go
|
||||
//
|
||||
// 如果从其他目录运行,可能会导致数据库文件路径错误,造成数据丢失。
|
||||
//
|
||||
// 嵌入前端静态文件:
|
||||
// 1. 编译前端:cd frontend-new && npm run build
|
||||
// 2. 将 dist 目录内容复制到 backend/embedded/dist
|
||||
// 3. 取消下方 embed 相关代码的注释
|
||||
// 4. 重新编译后端
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"verification-platform-backend/internal/config"
|
||||
"verification-platform-backend/internal/database"
|
||||
"verification-platform-backend/internal/middleware"
|
||||
"verification-platform-backend/internal/router"
|
||||
"verification-platform-backend/internal/service"
|
||||
"verification-platform-backend/pkg/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//go:embed embedded/dist
|
||||
var embeddedFiles embed.FS
|
||||
|
||||
// @title 网络验证平台API
|
||||
// @version 1.0
|
||||
// @description 网络验证平台后端API接口文档
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
// @contact.email support@swagger.io
|
||||
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// @host localhost:8080
|
||||
// @BasePath /api/v1
|
||||
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
func main() {
|
||||
// 初始化配置
|
||||
config.Init()
|
||||
|
||||
// 初始化日志
|
||||
logger.Init()
|
||||
|
||||
// 初始化数据库
|
||||
database.Init()
|
||||
|
||||
// 设置Gin模式
|
||||
if config.GetString("app.env") == "production" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
// 创建Gin引擎
|
||||
r := gin.Default()
|
||||
|
||||
// 设置请求体大小限制 (32MB)
|
||||
r.MaxMultipartMemory = 32 << 20
|
||||
|
||||
// 添加中间件
|
||||
r.Use(middleware.Logger())
|
||||
r.Use(middleware.Recovery())
|
||||
r.Use(middleware.Cors())
|
||||
|
||||
r.Use(func(c *gin.Context) {
|
||||
fmt.Printf("全局中间件: %s %s\n", c.Request.Method, c.Request.URL.Path)
|
||||
c.Next()
|
||||
})
|
||||
|
||||
// 静态文件服务 - 用于访问上传的图标
|
||||
r.Static("/uploads", "uploads")
|
||||
|
||||
// 设置路由
|
||||
router.SetupRoutes(r)
|
||||
|
||||
// 嵌入前端静态文件服务
|
||||
setupEmbeddedFrontend(r)
|
||||
|
||||
// 启动服务器
|
||||
port := config.GetString("app.port")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
|
||||
log.Printf("Server starting on port %s", port)
|
||||
if err := r.Run(":" + port); err != nil {
|
||||
log.Fatal("Failed to start server: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func setupEmbeddedFrontend(r *gin.Engine) {
|
||||
distFS, err := fs.Sub(embeddedFiles, "embedded/dist")
|
||||
if err != nil {
|
||||
log.Printf("Warning: embedded dist not found, frontend will not be served")
|
||||
return
|
||||
}
|
||||
|
||||
indexHTML, err := fs.ReadFile(distFS, "index.html")
|
||||
if err != nil {
|
||||
log.Printf("Warning: index.html not found in embedded dist")
|
||||
return
|
||||
}
|
||||
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
if c.Request.Method == "GET" && !strings.HasPrefix(c.Request.URL.Path, "/api/") {
|
||||
serveIndexHTML(c, string(indexHTML))
|
||||
return
|
||||
}
|
||||
c.JSON(404, gin.H{"error": "not found"})
|
||||
})
|
||||
|
||||
r.GET("/assets/*filepath", func(c *gin.Context) {
|
||||
c.FileFromFS(c.Request.URL.Path, http.FS(distFS))
|
||||
})
|
||||
}
|
||||
|
||||
func serveIndexHTML(c *gin.Context, indexHTML string) {
|
||||
settingService := service.NewSettingService()
|
||||
settings, err := settingService.GetSettingsByCategory("basic")
|
||||
if err != nil {
|
||||
settings = make(map[string]interface{})
|
||||
}
|
||||
|
||||
siteName := getSettingString(settings, "siteName", "微授权")
|
||||
siteDescription := getSettingString(settings, "siteDescription", "专业的应用验证平台")
|
||||
siteKeywords := getSettingString(settings, "siteKeywords", "验证平台,软件授权,卡密验证")
|
||||
logoLight := getSettingString(settings, "logoLight", "")
|
||||
logoDark := getSettingString(settings, "logoDark", "")
|
||||
favicon := getSettingString(settings, "favicon", "")
|
||||
|
||||
html := indexHTML
|
||||
html = strings.ReplaceAll(html, "{{.SiteName}}", siteName)
|
||||
html = strings.ReplaceAll(html, "{{.SiteDescription}}", siteDescription)
|
||||
html = strings.ReplaceAll(html, "{{.SiteKeywords}}", siteKeywords)
|
||||
html = strings.ReplaceAll(html, "{{.LogoLight}}", logoLight)
|
||||
html = strings.ReplaceAll(html, "{{.LogoDark}}", logoDark)
|
||||
html = strings.ReplaceAll(html, "{{.Favicon}}", favicon)
|
||||
|
||||
c.Data(200, "text/html; charset=utf-8", []byte(html))
|
||||
}
|
||||
|
||||
func getSettingString(settings map[string]interface{}, key, defaultValue string) string {
|
||||
if val, ok := settings[key]; ok {
|
||||
if str, ok := val.(string); ok && str != "" {
|
||||
return str
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
Reference in New Issue
Block a user