diff --git a/server/internal/middleware/middleware.go b/server/internal/middleware/middleware.go index 7f97609..f7df354 100644 --- a/server/internal/middleware/middleware.go +++ b/server/internal/middleware/middleware.go @@ -104,6 +104,7 @@ func Auth() gin.HandlerFunc { } // AdminAuth 管理员认证中间件:要求携带 role=admin 的 JWT(Authorization 头或 HttpOnly Cookie) +// 浏览器导航(GET 页面请求)未登录时渲染登录页;API 请求未登录时返回 401 JSON func AdminAuth() gin.HandlerFunc { return func(c *gin.Context) { tokenString := "" @@ -115,18 +116,24 @@ func AdminAuth() gin.HandlerFunc { tokenString, _ = c.Cookie(service.AdminTokenCookie) } - if tokenString == "" { - c.JSON(http.StatusUnauthorized, gin.H{ - "code": 401, - "msg": "需要管理员权限", - }) - c.Abort() - return + authed := false + if tokenString != "" { + cfg := config.Load() + userService := service.NewUserService() + authed = userService.IsAdminToken(tokenString, cfg.JWT.Secret) } - cfg := config.Load() - userService := service.NewUserService() - if !userService.IsAdminToken(tokenString, cfg.JWT.Secret) { + if !authed { + // 页面导航(GET 且非 /admin/api/):返回登录页 + if c.Request.Method == http.MethodGet && !strings.HasPrefix(c.Request.URL.Path, "/admin/api/") { + c.HTML(http.StatusOK, "index.html", gin.H{ + "title": "管理员登录", + "page": "login", + "url": c.Request.URL.Path, + }) + c.Abort() + return + } c.JSON(http.StatusUnauthorized, gin.H{ "code": 401, "msg": "需要管理员权限", diff --git a/server/web/index.html b/server/web/index.html index c03684f..37192e1 100644 --- a/server/web/index.html +++ b/server/web/index.html @@ -19,6 +19,7 @@ createInertiaApp({ resolve: name => { const pages = { + login: () => import('/static/js/pages/Login.js'), dashboard: () => import('/static/js/pages/Dashboard.js'), users: () => import('/static/js/pages/Users.js'), orders: () => import('/static/js/pages/Orders.js'), diff --git a/server/web/static/js/pages/Login.js b/server/web/static/js/pages/Login.js new file mode 100644 index 0000000..a6db795 --- /dev/null +++ b/server/web/static/js/pages/Login.js @@ -0,0 +1,68 @@ +// Login 管理员登录页 +export default { + template: ` +
+
+
+

祈福小助手

+

管理后台登录

+
+
+
+ + +
+
{{ error }}
+ +
+
+
+ `, + data() { + return { + password: '', + loading: false, + error: '' + }; + }, + methods: { + async submit() { + if (!this.password || this.loading) return; + this.loading = true; + this.error = ''; + try { + const res = await fetch('/admin/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ password: this.password }) + }); + const data = await res.json(); + if (data.code === 0) { + // Cookie 已由服务端写入,跳回原本要访问的页面 + window.location.href = window.location.pathname === '/admin/login' + ? '/admin/' + : window.location.pathname; + } else { + this.error = data.msg || '登录失败'; + } + } catch (e) { + this.error = '网络错误,请重试'; + } finally { + this.loading = false; + } + } + } +};