feat(client): 初始化前端壳与鉴权守卫(P1-5)
- 技术栈:React 18 + TypeScript + Vite + Tailwind - API 层:ApiError + 401 自动刷新 + single-flight 重试 - 鉴权:内存 Access Token + Cookie Refresh + 启动 bootstrap - RBAC:权限映射 + RequireAuth/RequirePermission 路由守卫 - 布局:OA 工作台壳层 + 侧边栏 + 5 个占位页面 - 样式:复用 hyb-web 视觉 token(单向同步) - 文档:新增 client README,补充 server 联调说明
这个提交包含在:
@@ -0,0 +1,47 @@
|
||||
import { apiRequestData } from "../api/http";
|
||||
import type { LoginRequest, LoginResponse, MeResponse } from "../api/types";
|
||||
import { getDeviceFingerprint } from "./deviceFingerprint";
|
||||
|
||||
const JSON_HEADERS = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
|
||||
export async function loginWithPassword(payload: LoginRequest) {
|
||||
return apiRequestData<LoginResponse>("/api/auth/login", {
|
||||
method: "POST",
|
||||
auth: false,
|
||||
retryOn401: false,
|
||||
headers: {
|
||||
...JSON_HEADERS,
|
||||
"x-device-fingerprint": getDeviceFingerprint(),
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function refreshSession() {
|
||||
return apiRequestData<LoginResponse>("/api/auth/refresh", {
|
||||
method: "POST",
|
||||
auth: false,
|
||||
retryOn401: false,
|
||||
headers: {
|
||||
"x-device-fingerprint": getDeviceFingerprint(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function logoutSession() {
|
||||
return apiRequestData<Record<string, never>>("/api/auth/logout", {
|
||||
method: "POST",
|
||||
auth: false,
|
||||
retryOn401: false,
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchCurrentEmployee(accessToken: string) {
|
||||
return apiRequestData<MeResponse>("/api/me", {
|
||||
auth: true,
|
||||
retryOn401: false,
|
||||
accessTokenOverride: accessToken,
|
||||
});
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户