4fe9fc0c95
CI/CD Pipeline / Deploy Staging (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Failing after 66h12m36s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 66h13m59s
任务 1:登录持久化 + Token 刷新 - authStore: partialize 持久化 accessToken/refreshToken 到 localStorage - auth.ts: 新增 refreshAccessToken API 函数 - client.ts: 401 拦截器实现刷新队列,无感续期 任务 2:片段逻辑重构(片段 = 时间规划 + 类型标记,不绑定素材) - types.ts: 创建统一 ClipData/ClipType 类型定义 - EditingPlanner.tsx: handleAddClip 改为接收 type+duration,移除素材绑定 - TimelinePanel.tsx: "+" 卡片改为类型+时长选择器,移除素材拖拽 - ClipPropertiesPanel.tsx: 片段详情改为类型选择器+时长+startOffset - PreviewPlayer.tsx: 适配新 ClipData 类型,用 type 显示图标 - EditingPlanner.css: 新增类型选择器样式,移除旧素材选择器样式 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
132 lines
3.0 KiB
TypeScript
132 lines
3.0 KiB
TypeScript
/**
|
|
* 认证相关 API
|
|
*/
|
|
import axios from "axios";
|
|
import apiClient from "./client";
|
|
|
|
// 类型定义
|
|
export interface LoginRequest {
|
|
email: string;
|
|
password: string;
|
|
}
|
|
|
|
export interface LoginResponse {
|
|
access_token: string;
|
|
refresh_token?: string | null;
|
|
token_type: string;
|
|
expires_in: number;
|
|
user_id: string;
|
|
email: string;
|
|
username: string;
|
|
display_name: string;
|
|
}
|
|
|
|
export interface RegisterRequest {
|
|
email: string;
|
|
password: string;
|
|
username: string;
|
|
display_name?: string;
|
|
}
|
|
|
|
export interface User {
|
|
id: string;
|
|
user_id: string;
|
|
email: string;
|
|
username: string;
|
|
display_name: string;
|
|
is_email_verified: boolean;
|
|
email_verified: boolean;
|
|
created_at?: string;
|
|
}
|
|
|
|
export interface UserResponse {
|
|
id?: string;
|
|
user_id?: string;
|
|
email: string;
|
|
username: string;
|
|
display_name: string;
|
|
is_email_verified?: boolean;
|
|
email_verified?: boolean;
|
|
created_at?: string;
|
|
}
|
|
|
|
export const normalizeUser = (data: UserResponse): User => {
|
|
const userId = data.id ?? data.user_id ?? "";
|
|
const emailVerified = data.is_email_verified ?? data.email_verified ?? false;
|
|
|
|
return {
|
|
id: userId,
|
|
user_id: userId,
|
|
email: data.email,
|
|
username: data.username,
|
|
display_name: data.display_name,
|
|
is_email_verified: emailVerified,
|
|
email_verified: emailVerified,
|
|
created_at: data.created_at,
|
|
};
|
|
};
|
|
|
|
// 登录
|
|
export const login = async (data: LoginRequest): Promise<LoginResponse> => {
|
|
const response = await apiClient.post("/auth/login", data);
|
|
return response.data;
|
|
};
|
|
|
|
// 刷新 access_token(使用裸 axios 避免拦截器递归)
|
|
export const refreshAccessToken = async (
|
|
refreshToken: string,
|
|
): Promise<LoginResponse> => {
|
|
const baseURL = apiClient.defaults.baseURL ?? "";
|
|
const response = await axios.post(`${baseURL}/auth/refresh`, {
|
|
refresh_token: refreshToken,
|
|
});
|
|
return response.data;
|
|
};
|
|
|
|
// 注册
|
|
export const register = async (
|
|
data: RegisterRequest,
|
|
): Promise<{ message: string }> => {
|
|
const response = await apiClient.post("/auth/register", data);
|
|
return response.data;
|
|
};
|
|
|
|
// 登出
|
|
export const logout = async (): Promise<void> => {
|
|
await apiClient.post("/auth/logout");
|
|
};
|
|
|
|
// 获取当前用户
|
|
export const getCurrentUser = async (): Promise<User> => {
|
|
const response = await apiClient.get<UserResponse>("/auth/me");
|
|
return normalizeUser(response.data);
|
|
};
|
|
|
|
// 请求密码重置
|
|
export const requestPasswordReset = async (
|
|
email: string,
|
|
): Promise<{ message: string }> => {
|
|
const response = await apiClient.post("/auth/forgot-password", { email });
|
|
return response.data;
|
|
};
|
|
|
|
// 重置密码
|
|
export const resetPassword = async (
|
|
token: string,
|
|
newPassword: string,
|
|
): Promise<{ message: string }> => {
|
|
const response = await apiClient.post("/auth/reset-password", {
|
|
token,
|
|
new_password: newPassword,
|
|
});
|
|
return response.data;
|
|
};
|
|
|
|
// 验证邮箱
|
|
export const verifyEmail = async (
|
|
token: string,
|
|
): Promise<{ message: string }> => {
|
|
const response = await apiClient.post("/auth/verify-email", { token });
|
|
return response.data;
|
|
};
|