The repo already layered file defaults under environment overrides, on both the backend (settings.yml < GOAUTO_*) and the frontend (.env.production < process.env). What was missing was a translator for production: config.yaml only ever existed for the PowerShell launchers, so a packaged binary read none of it and had no database credentials either — SYB was inheriting an existing gap, not creating one. The server now reads config.yaml itself, between settings.yml and the environment. Lookup is GOAUTO_CONFIG, then ./config.yaml, then beside the executable, so a packaged binary works wherever it is started. An absent file is not an error: containers supply everything through the environment. Scalars are read by YAML type and coerced, so an unquoted all-digit password cannot take startup down over a quoting detail. This removed the need for a Read-SybConfig in PowerShell: the launcher just hands over the path it already knows, rather than reimplementing a YAML parser. The server also serves the built frontend when dist is present, which is what .env.production's empty VUE_APP_BASE_API already assumes. The history fallback is restricted to non-API GETs, and is not installed at all without dist, so development 404s stay 404s. Precedence is mutation-tested: applying the local file after the environment instead of before makes the layering test fail. Not verified: the PowerShell change and any Windows deployment — both need a run on the Windows side. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
91 lines
2.5 KiB
Go
91 lines
2.5 KiB
Go
package router
|
|
|
|
import (
|
|
"go-admin/app/admin/apis"
|
|
"mime"
|
|
|
|
"github.com/go-admin-team/go-admin-core/sdk/config"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|
"github.com/go-admin-team/go-admin-core/sdk/pkg/ws"
|
|
ginSwagger "github.com/swaggo/gin-swagger"
|
|
|
|
swaggerfiles "github.com/swaggo/files"
|
|
|
|
"go-admin/common/middleware"
|
|
"go-admin/common/middleware/handler"
|
|
_ "go-admin/docs/admin"
|
|
)
|
|
|
|
func InitSysRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.RouterGroup {
|
|
g := r.Group("")
|
|
sysBaseRouter(g)
|
|
// 静态文件
|
|
sysStaticFileRouter(g)
|
|
// swagger;注意:生产环境可以注释掉
|
|
if config.ApplicationConfig.Mode != "prod" {
|
|
sysSwaggerRouter(g)
|
|
}
|
|
// 需要认证
|
|
sysCheckRoleRouterInit(g, authMiddleware)
|
|
// 前端构建产物(存在时才注册),见 InitSPARouter 的说明
|
|
InitSPARouter(r)
|
|
return g
|
|
}
|
|
|
|
func sysBaseRouter(r *gin.RouterGroup) {
|
|
|
|
go ws.WebsocketManager.Start()
|
|
go ws.WebsocketManager.SendService()
|
|
go ws.WebsocketManager.SendAllService()
|
|
|
|
if config.ApplicationConfig.Mode != "prod" {
|
|
r.GET("/", apis.GoAdmin)
|
|
}
|
|
r.GET("/info", handler.Ping)
|
|
}
|
|
|
|
func sysStaticFileRouter(r *gin.RouterGroup) {
|
|
err := mime.AddExtensionType(".js", "application/javascript")
|
|
if err != nil {
|
|
return
|
|
}
|
|
r.Static("/static", "./static")
|
|
if config.ApplicationConfig.Mode != "prod" {
|
|
r.Static("/form-generator", "./static/form-generator")
|
|
}
|
|
}
|
|
|
|
func sysSwaggerRouter(r *gin.RouterGroup) {
|
|
r.GET("/swagger/admin/*any", ginSwagger.WrapHandler(swaggerfiles.NewHandler(), ginSwagger.InstanceName("admin")))
|
|
}
|
|
|
|
func sysCheckRoleRouterInit(r *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
wss := r.Group("").Use(authMiddleware.MiddlewareFunc())
|
|
{
|
|
wss.GET("/ws/:id/:channel", ws.WebsocketManager.WsClient)
|
|
wss.GET("/wslogout/:id/:channel", ws.WebsocketManager.UnWsClient)
|
|
}
|
|
|
|
v1 := r.Group("/api/v1")
|
|
{
|
|
v1.POST("/login", authMiddleware.LoginHandler)
|
|
// Refresh time can be longer than token timeout
|
|
v1.GET("/refresh_token", authMiddleware.RefreshHandler)
|
|
}
|
|
registerBaseRouter(v1, authMiddleware)
|
|
}
|
|
|
|
func registerBaseRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
api := apis.SysMenu{}
|
|
api2 := apis.SysDept{}
|
|
v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
|
{
|
|
v1auth.GET("/roleMenuTreeselect/:roleId", api.GetMenuTreeSelect)
|
|
//v1.GET("/menuTreeselect", api.GetMenuTreeSelect)
|
|
v1auth.GET("/roleDeptTreeselect/:roleId", api2.GetDeptTreeRoleSelect)
|
|
v1auth.POST("/logout", handler.LogOut)
|
|
}
|
|
}
|