You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

8.0 KiB

前端 API 对接快速上手

5 分钟快速上手前端 API 对接


🚀 快速开始

步骤 1:查看后端接口

# 查看后端接口文件
cat server/app/api/v1/projects.py

# 查看后端 Schema
cat server/app/schemas/project.py

步骤 2:添加前端 API 调用

文件: client/src/services/api/projects.ts

// ✅ 已存在!创建项目 API 已实现
async create(data: CreateProjectDto): Promise<Project> {
  return apiClient.post('/projects', data) as Promise<Project>;
}

步骤 3:创建 React Query Hook

文件: client/src/hooks/api/useProjects.ts

// ✅ 已存在!Hook 已实现
export function useCreateProject() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: CreateProjectDto) => projectApi.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: projectKeys.lists() });
    },
  });
}

步骤 4:在组件中使用

import { useCreateProject } from '@/hooks/api/useProjects';

function MyComponent() {
  const createProject = useCreateProject();

  const handleSubmit = async (formData) => {
    try {
      const newProject = await createProject.mutateAsync({
        name: formData.name,
        contentType: 'ad', // ad/movie/series等
        aspectRatio: '16:9',
        plannedDuration: 60,
      });
      
      console.log('创建成功:', newProject);
    } catch (error) {
      console.error('创建失败:', error);
    }
  };

  return (
    <button 
      onClick={handleSubmit}
      disabled={createProject.isPending}
    >
      {createProject.isPending ? '创建中...' : '创建项目'}
    </button>
  );
}

🎯 完整示例

使用表单 + React Hook Form + Zod

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { useCreateProject } from '@/hooks/api/useProjects';
import { useToast } from '@/hooks/use-toast';

// 1. 定义表单验证
const schema = z.object({
  name: z.string().min(1, '请输入项目名称'),
  contentType: z.enum(['ad', 'movie', 'series', 'anime', 'short', 'concept']),
  aspectRatio: z.enum(['16:9', '9:16', '4:3', '21:9', '1:1', '2.35:1', '2.39:1']),
  duration: z.number().min(1, '请输入时长'),
});

type FormData = z.infer<typeof schema>;

// 2. 创建表单组件
function CreateProjectForm() {
  const createProject = useCreateProject();
  const { toast } = useToast();
  const form = useForm<FormData>({
    resolver: zodResolver(schema),
    defaultValues: {
      name: '',
      contentType: 'ad',
      aspectRatio: '16:9',
      duration: 60,
    },
  });

  const onSubmit = async (data: FormData) => {
    try {
      const newProject = await createProject.mutateAsync({
        name: data.name,
        contentType: data.contentType,
        aspectRatio: data.aspectRatio,
        plannedDuration: data.duration,
      });

      toast({
        title: '项目已创建',
        description: `项目 "${newProject.name}" 已成功创建`,
      });

      // 跳转到新项目
      navigate(`/project/${newProject.id}`);
    } catch (error) {
      toast({
        title: '创建失败',
        description: error.message,
        variant: 'destructive',
      });
    }
  };

  return (
    <form onSubmit={form.handleSubmit(onSubmit)}>
      <input {...form.register('name')} placeholder="项目名称" />
      {form.formState.errors.name && (
        <span>{form.formState.errors.name.message}</span>
      )}

      <select {...form.register('contentType')}>
        <option value="ad">广告片</option>
        <option value="movie">电影</option>
        <option value="short">短视频</option>
      </select>

      <button 
        type="submit" 
        disabled={createProject.isPending}
      >
        {createProject.isPending ? '创建中...' : '创建项目'}
      </button>
    </form>
  );
}

🧪 测试联调

方法 1:手动测试(推荐)

# 1. 启动后端
cd server
uvicorn app.main:app --reload

# 2. 启动前端
cd client
npm run dev

# 3. 访问浏览器
open http://localhost:5173

检查点:

  • 打开浏览器开发者工具 → Network
  • 点击"创建项目"按钮
  • 填写表单并提交
  • 观察请求和响应

方法 2:使用 Playwright 自动化测试

# 安装依赖
cd client
npm install -D @playwright/test

# 运行测试
npx playwright test tests/e2e/create-project.spec.ts

# 查看测试报告
npx playwright show-report

参考测试文件: client/tests/e2e/create-project.spec.ts


🔍 常见问题

Q1: 如何查看请求/响应?

浏览器开发者工具:

  1. 按 F12 打开开发者工具
  2. 切换到 Network 标签
  3. 过滤 XHR/Fetch 请求
  4. 点击请求查看详情

Console 日志:

// apiClient 已自动打印请求日志
// 查看 Console 输出:
// 📡 API 请求: { method: 'POST', url: '/projects', ... }

Q2: Token 在哪里设置?

自动设置:

// client/src/services/api/client.ts
// 请求拦截器已自动从 localStorage 读取 token
const token = localStorage.getItem('token');
if (token) {
  config.headers.Authorization = `Bearer ${token}`;
}

手动设置(调试用):

// 浏览器 Console
localStorage.setItem('token', 'your_token_here');

Q3: 如何处理错误?

方式 1:try-catch

try {
  await createProject.mutateAsync(data);
} catch (error) {
  console.error('创建失败:', error);
  toast({ title: '创建失败', description: error.message });
}

方式 2:onError 回调

const createProject = useMutation({
  mutationFn: (data) => projectApi.create(data),
  onError: (error) => {
    toast({ title: '创建失败', description: error.message });
  },
});

Q4: 如何显示 Loading 状态?

const createProject = useCreateProject();

// ✅ 使用 isPending 状态
<button disabled={createProject.isPending}>
  {createProject.isPending ? '创建中...' : '创建项目'}
</button>

// ✅ 使用 isLoading(已废弃,建议用 isPending)
// createProject.isLoading

Q5: 如何刷新列表?

自动刷新(推荐):

// useCreateProject 已自动配置
onSuccess: () => {
  queryClient.invalidateQueries({ queryKey: projectKeys.lists() });
}

手动刷新:

const queryClient = useQueryClient();

// 刷新所有项目列表
queryClient.invalidateQueries({ queryKey: ['projects', 'list'] });

// 刷新特定查询
queryClient.invalidateQueries({ 
  queryKey: ['projects', 'list', { type: 'mine' }] 
});

📝 AI 提示词

创建新功能

为前端 [功能名] 功能对接后端 API

后端接口:POST /api/v1/[path]
Schema:[SchemaName]

需求:
1. 添加 API 调用(client/src/services/api/[module].ts)
2. 创建 React Query Hook
3. 实现 UI 组件

参考:client/src/services/api/projects.ts

调试问题

调试前端 API 对接问题:

问题:[描述问题]
错误信息:[错误信息]
请求:[请求数据]
响应:[响应数据]

检查:
1. Token 是否正确
2. 请求数据格式
3. 响应拦截器
4. 类型定义

📚 参考文档


检查清单

完成前端 API 对接前,请确认:

  • 后端接口已实现并测试通过
  • 后端 Schema 定义清晰
  • 前端类型定义与后端对齐
  • API 客户端配置正确(baseURL, 拦截器)
  • React Query Hook 配置正确
  • 错误处理完善
  • Loading 状态显示
  • 成功后刷新列表
  • 手动测试通过
  • E2E 测试通过(可选)

最后更新: 2026-02-06
维护者: Jointo 开发团队