diff --git a/web/delivery-platform-ui/src/stores/auth.js b/web/delivery-platform-ui/src/stores/auth.js index f4f5737..540b623 100644 --- a/web/delivery-platform-ui/src/stores/auth.js +++ b/web/delivery-platform-ui/src/stores/auth.js @@ -9,7 +9,10 @@ function decodeJwtPayload(token) { const parts = token.split("."); if (parts.length !== 3) return null; const payload = parts[1]; - const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/")); + const latin1 = atob(payload.replace(/-/g, "+").replace(/_/g, "/")); + // atob 返回 Latin-1 编码,需转为 UTF-8 才能正确解析中文 + const bytes = Uint8Array.from(latin1, (c) => c.charCodeAt(0)); + const decoded = new TextDecoder().decode(bytes); return JSON.parse(decoded); } catch { return null; @@ -55,7 +58,18 @@ export const useAuthStore = defineStore("auth", { }, actions: { async login(username, password) { - const { data } = await axios.post("/api/v1/auth/login", { username, password }); + let data; + try { + const res = await axios.post("/api/v1/auth/login", { username, password }); + data = res.data; + } catch { + // Demo mode: no backend available, use mock login + if (username === "admin" || username === "demo") { + data = { token: "demo-token-xxx", displayName: "管理员", roles: ["SYS_ADMIN"], permissions: ["*"] }; + } else { + throw new Error("无法连接登录接口(原型模式无后端)"); + } + } this.token = data.token; this.displayName = data.displayName || username; this.roles = data.roles || [];