feat(admin): art-design-pro integration with local session auth
P1b Task 9: apps/admin based on art-design-pro v3.0.2 (tag, commit d224dd4; source recorded in apps/admin/SOURCE.md), trimmed to layout/login/i18n/request/table-form core. Login wired to real POST /v1/auth/password (single-token session), Bearer header on all requests, 401 interceptor logout+redirect, request-driven sliding renewal (refresh at ~80% TTL, single-flight), best-effort POST /v1/auth/logout on user-menu logout. One protected stub page (相册管理). Dev port 5176 strictPort + /v1 proxy to 8080. Admin keeps its own eslint9 flat config; root eslint ignores apps/admin/**. vitest unit tests for renewal pacing + Playwright e2e (guard redirect, localized wrong-password error, login lands on stub, token persists across reload, logout clears session). Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 认证接口(对齐 @photo/contracts 的 /v1/auth/* 端点)
|
||||
*
|
||||
* - 登录:POST /v1/auth/password {account, password} → {sessionToken, expiresAt}
|
||||
* - 续期:POST /v1/auth/refresh(Bearer)→ {expiresAt}(单令牌滑动续期,令牌本身不变)
|
||||
* - 注销:POST /v1/auth/logout(Bearer)→ 204 无响应体
|
||||
*
|
||||
* 用户信息无后端端点(契约未定义 /users/me),由本地拼装:
|
||||
* 登录时把账号写入 user store,fetchGetUserInfo 直接读 store,
|
||||
* 避免路由守卫为拿用户信息打一个不存在的接口。
|
||||
*/
|
||||
import request from '@/utils/http'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
|
||||
/**
|
||||
* 账号密码登录
|
||||
* @param params 登录参数(account + password)
|
||||
* @returns 会话令牌与过期时间
|
||||
*/
|
||||
export function fetchLogin(params: Api.Auth.LoginParams) {
|
||||
return request.post<Api.Auth.LoginResponse>({
|
||||
url: '/v1/auth/password',
|
||||
data: params,
|
||||
// 凭据错误也是 401,但不能触发「会话过期→登出」分支,标记豁免
|
||||
skipUnauthorizedLogout: true,
|
||||
showErrorMessage: false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 滑动续期(需 Authorization: Bearer)
|
||||
* @returns 新的过期时间(令牌不变)
|
||||
*/
|
||||
export function fetchRefreshSession() {
|
||||
return request.post<Api.Auth.RefreshResponse>({
|
||||
url: '/v1/auth/refresh',
|
||||
showErrorMessage: false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销会话(需 Authorization: Bearer),204 无响应体
|
||||
* 尽力而为:失败也继续本地登出
|
||||
*/
|
||||
export async function fetchLogout(): Promise<void> {
|
||||
await request.del<void>({ url: '/v1/auth/logout', showErrorMessage: false })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息(本地)
|
||||
* 模板守卫在动态路由初始化时调用;后端无对应端点,从 user store
|
||||
* 读取登录时保存的账号拼装,角色约定为 R_ADMIN。
|
||||
*/
|
||||
export async function fetchGetUserInfo(): Promise<Api.Auth.UserInfo> {
|
||||
const userStore = useUserStore()
|
||||
const account = userStore.info?.userName || 'admin'
|
||||
return {
|
||||
userId: 0,
|
||||
userName: account,
|
||||
email: '',
|
||||
buttons: [],
|
||||
roles: ['R_ADMIN']
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user