1. 页面概览

「登录」是 AI 行动平台的统一认证入口(对应前端源码 action/web/src/views/LoginPage.vue)。用户用用户名 + 密码登录后,前端把 JWT token 存入 localStorage 的 aip_token,即可访问各产品受保护路由。本页现支持四种模式:登录、注册(用户名 + 密码,邮箱选填)、忘记密码(提交邮箱或用户名,触发重置邮件)、重置密码(用邮件中的令牌设置新密码,支持 /login?reset_token=xxx 链接直达)。一句话总结:本页是平台唯一登录/注册入口,登录成功即获得全平台访问令牌,忘记密码可自助找回。

2. 访问入口

2.1 路由与菜单

路由 path: /login、name: Login、meta 标题「登录」且 guest: true(公开路由);未登录访问受保护页面时,路由守卫重定向到 /login?redirect=<原路径>,登录后自动跳回。重置邮件中的链接为 /login?reset_token=<令牌>,页面挂载时读取该 query 并直接进入「重置密码」模式。本页无侧边栏菜单,未登录时顶部导航栏不渲染。

2.2 认证与权限

公开页无需 token;已登录(localStorage 有 aip_token)再访问 /login 会被守卫直接跳到 Foundry。登录成功后 token 类型为 JWT(Bearer),存 localStorage['aip_token'],用户名存 localStorage['aip_username']。

2.3 端口与 API 前缀

AIP 后端 18080。登录/注册走 action/web/src/api/client.js(baseURL /api/v1);自助找回的两个端点走 action/web/src/api/aipClient.js(baseURL /aip-api/v1,经 Vite 代理 rewrite 到 AIP 18080),确保请求恒定落到 AIP 而非默认代理目标。

3. 界面布局

居中卡片式,从上到下依次为标题区、提示条、表单区、模式切换区;表单区随模式切换(登录/注册共用一个表单,忘记密码与重置密码为独立表单):

┌──────────────────────────────┐
│        AI 行动平台             │
│  副标题随模式切换(4 种)        │
│   [操作提示条 alert]            │
│  ── 登录 / 注册 ──             │
│   用户名  [________________]   │
│   密码    [________________]   │
│   邮箱(选填,仅注册模式)[____]   │
│  ── 忘记密码 ──                │
│   邮箱或用户名 [____________]   │
│  ── 重置密码 ──                │
│   重置令牌 [________________]   │
│   新密码   [________________]   │
│   确认新密码 [______________]   │
│      [  主按钮(随模式变文案)  ] │
│   模式切换链接(注册/重置/返回登录)│
│  忘记密码? [自助找回]           │
└──────────────────────────────┘

4. 交互元素

控件位置含义与作用
输入框「用户名」表单(登录/注册)登录/注册用户名,必填
输入框「密码」表单(登录/注册)登录/注册密码,必填(type=password)
输入框「邮箱(选填)」表单(仅注册模式)注册时可填邮箱;该邮箱是后续自助找回的收件地址
按钮「登录」/「注册」表单底部提交表单;loading 时文案变「处理中...」并禁用
链接「立即注册」/「立即登录」表单底部switchMode() 切换模式并清空表单与提示
链接「忘记密码?自助找回」表单/模式切换下方切到「忘记密码」模式(原「请联系管理员」纯文案已升级为可点击入口)
输入框「邮箱或用户名」表单(忘记密码模式)提交自助找回申请,任一即可(后端 identifier,亦兼容 email/username 字段)
按钮「发送重置邮件」表单(忘记密码模式)调 POST /auth/forgot-password;loading 时文案变「发送中...」
输入框「重置令牌」表单(重置密码模式)粘贴邮件中的令牌;从 ?reset_token= 进入时自动预填
输入框「新密码」/「确认新密码」表单(重置密码模式)前端先校验「≥8 位」「两次一致」,不通过直接提示且不发请求
按钮「重置密码」表单(重置密码模式)调 POST /auth/reset-password;成功后清空令牌与密码并切回登录模式
链接「去重置密码」/「返回登录」表单底部(找回模式)无邮件直达链接时手工进入重置表单 / 返回登录

次要控件:表单上方 alert 提示条展示成功/失败消息,错误文案如实透传后端 error 字段(如「发送失败:请求过于频繁,请稍后再试」「重置失败:重置链接无效或已过期,请重新申请」)。

5. 后端关联

5.1 API 客户端

登录/注册用 action/web/src/api/client.js(axios baseURL /api/v1,timeout 30s,请求拦截器附 Bearer aip_token,401 清 token 跳 /login);自助找回用 action/web/src/api/aipClient.js(baseURL /aip-api/v1,同一套拦截器语义)。

5.2 端点表

方法路径请求体页面触发点成功响应
POST/auth/login{username, password}登录模式提交{user_id, username, token, token_type:"bearer"}
POST/auth/register{username, password, email?}注册模式提交201 {user_id, username}
POST/auth/forgot-password{identifier}(兼容 email/username)忘记密码模式提交200 {success:true, message:"如果该账号存在且已绑定邮箱,我们已发送密码重置邮件…"}
POST/auth/reset-password{token, new_password}重置密码模式提交200 {success:true, message:"密码重置成功,请使用新密码登录。"}

注:/auth/forgot-password 与 /auth/reset-password 注册在 AIP 公开路由组(products/aip/server/server.go,与 /auth/login、/auth/register 同级,无鉴权中间件),前端经 /aip-api 前缀恒定打到 AIP 18080。管理员侧的 POST /api/v1/users/:id/password(admin 组)仍保留,用于「用户管理」页(UsersPage.vue)人工重置。

5.3 关键机制

doLogin 兼容两种后端响应——AIP(18080) 返回顶层 {token, username},Foundry(18081) 返回 {code:0, data:{...}} 信封,前端先判断 data.data.token 是否存在再取内层,随后落库 aip_token/aip_username;Gotham 后端返回 refresh_token 时同步存入 gotham_refresh_token(供 401 自动重放)。登录成功后读 route.query.redirect 决定落地页(默认 /foundry);注册成功后自动切回登录模式。忘记密码成功后停留在原表单并展示后端统一报文;重置成功后清空令牌与密码、切回登录模式并(若 URL 带 reset_token)用 router.replace 清掉 query,避免令牌残留在浏览器历史里。

6. 权限与安全

7. 常见问题与排错

  1. 登录成功却立刻跳回登录页:原因是后端 401(token 无效),client.js 拦截器清除 token 并重定向。处理:重新登录;检查服务器时钟与 SECRET_KEY 是否稳定;频繁 401 看后端日志。
  2. 提示「操作失败:invalid request body」:原因是请求体字段缺失或格式不符(如密码为空、Content-Type 错误)。处理:确认用户名密码均已填写;用 curl 直接调 POST /api/v1/auth/login 复现。
  3. 注册成功但无法登录:原因是注册接口只创建账号不返回 token,需切登录模式再登录。处理:按提示「请切换到登录模式登录」切换;若仍失败检查用户名是否已存在。
  4. 访问 /login 被直接跳到 Foundry:原因是 localStorage 已有 aip_token,guest 页对已登录用户重定向。处理:属预期行为;如需换账号先在顶部导航栏登出(清 token)。
  5. 点了「发送重置邮件」但收不到信:先看提示条文案。若为 503「邮件服务未配置」,说明服务端未配 SMTP,需联系管理员;若为 429 则短时间内申请过多,等待窗口过期再试;200 但没收到则依次检查收件箱/垃圾邮件、账号是否绑定了该邮箱、注册时邮箱是否填错(邮箱选填,未填则不发信)。
  6. 提示「重置链接无效或已过期,请重新申请」:令牌已使用、已过期(默认 30 分钟)或已被更新的一次申请作废。处理:回到「忘记密码」重新申请;每次新申请都会让旧令牌立即失效。
  7. 重置时提示「新密码长度至少 8 位」:前端与后端同口径校验(后端返回 422 VALIDATION_ERROR)。处理:改用至少 8 位的新密码;弱密码失败不会消耗令牌,改正后可继续用同一令牌提交。

8. 已知缺陷与边界