🚀 前端技术方案标准模板

基于 OpenClaw + Claude Code 的端到端研发自动化系统 · 前端技术架构规范

React 18+ TypeScript 5+ 原子设计 AI 协同开发

📋 一、方案概述

本模板为基于 OpenClaw + Claude Code 的端到端研发自动化系统中的前端技术方案标准规范,涵盖页面结构、组件设计、交互规范等核心内容,支持从需求到部署的全流程自动化研发。

🎯 核心目标

  • 标准化前端开发流程
  • 提升代码可维护性
  • 实现人机协同开发
  • 支持自动化测试与部署

🛠️ 技术栈

  • React 18+ / Vue 3+
  • TypeScript 5+
  • TailwindCSS / Styled Components
  • Zustand / Redux Toolkit
  • Vite / Webpack 5

🔄 研发流程

需求分析
PRD 设计
技术方案
AI Coding
测试部署

🏗️ 二、页面结构规范

2.1 目录结构标准

src/ 目录结构
src/
├── assets/                 # 静态资源
│   ├── images/            # 图片资源
│   ├── fonts/             # 字体文件
│   └── styles/            # 全局样式
├── components/            # 组件库
│   ├── atoms/            # 原子组件
│   ├── molecules/        # 分子组件
│   ├── organisms/        # 生物组件
│   └── templates/        # 模板组件
├── pages/                # 页面组件
├── hooks/                # 自定义 Hooks
├── stores/               # 状态管理
├── services/             # API 服务层
├── utils/                # 工具函数
├── types/                # TypeScript 类型定义
├── constants/            # 常量定义
└── config/               # 配置文件

2.2 页面布局规范

布局类型 适用场景 组件示例 响应式断点
单栏布局 移动端、简单表单页 LoginPage, FormPage <768px
双栏布局 后台管理、列表详情页 Dashboard, AdminPanel ≥768px
三栏布局 复杂数据展示、对比分析 DataAnalysis, ComparisonView ≥1200px
网格布局 卡片展示、图片墙 Gallery, ProductGrid 自适应

2.3 路由管理规范

路由配置示例 (React Router v6)
// routes/index.tsx
import { createBrowserRouter } from 'react-router-dom';

export const router = createBrowserRouter([
  {
    path: '/',
    element: <MainLayout />,
    children: [
      {
        index: true,
        element: <HomePage />,
        loader: homeLoader,
      },
      {
        path: 'dashboard',
        element: <DashboardPage />,
        loader: dashboardLoader,
        errorElement: <ErrorBoundary />,
      },
      {
        path: 'products/:id',
        element: <ProductDetail />,
        loader: productLoader,
      },
    ],
  },
  {
    path: '/auth',
    element: <AuthLayout />,
    children: [
      { path: 'login', element: <LoginPage /> },
      { path: 'register', element: <RegisterPage /> },
    ],
  },
]);

2.4 状态管理规范

Zustand Store 示例
// stores/userStore.ts
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';

interface UserState {
  user: UserInfo | null;
  token: string | null;
  isAuthenticated: boolean;
  login: (credentials: LoginCredentials) => Promise<void>;
  logout: () => void;
  updateUser: (data: Partial<UserInfo>) => void;
}

export const useUserStore = create<UserState>()(
  devtools(
    persist(
      (set, get) => ({
        user: null,
        token: null,
        isAuthenticated: false,
        
        login: async (credentials) => {
          const response = await authService.login(credentials);
          set({ 
            user: response.user, 
            token: response.token,
            isAuthenticated: true 
          });
        },
        
        logout: () => {
          set({ user: null, token: null, isAuthenticated: false });
        },
        
        updateUser: (data) => {
          set((state) => ({
            user: state.user ? { ...state.user, ...data } : null
          }));
        },
      }),
      { name: 'user-storage' }
    )
  )
);

🧩 三、组件设计规范

3.1 原子设计原则

⚛️ 原子 (Atoms)

基础 UI 元素,不可再分

  • Button, Input, Label
  • Icon, Avatar, Badge
  • Typography 组件

🧬 分子 (Molecules)

原子的组合,具有简单功能

  • SearchBar (Input + Button)
  • FormItem (Label + Input + Error)
  • CardHeader (Avatar + Title + Action)

🦠 生物 (Organisms)

复杂的功能模块

  • Navigation (Logo + Menu + UserMenu)
  • ProductList (Filter + Grid + Pagination)
  • DataTable (Header + Rows + Footer)

📐 模板 (Templates)

页面布局结构

  • DashboardTemplate
  • FormTemplate
  • ListDetailTemplate

3.2 组件 Props 接口规范

TypeScript Props 定义示例
// components/atoms/Button/Button.types.ts
import { ReactNode, MouseEventHandler } from 'react';

export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost';
export type ButtonSize = 'sm' | 'md' | 'lg';
export type ButtonHTMLType = 'button' | 'submit' | 'reset';

export interface ButtonProps {
  // 基础属性
  variant?: ButtonVariant;
  size?: ButtonSize;
  type?: ButtonHTMLType;
  disabled?: boolean;
  loading?: boolean;
  
  // 内容
  children: ReactNode;
  icon?: ReactNode;
  iconPosition?: 'left' | 'right';
  
  // 事件
  onClick?: MouseEventHandler<HTMLButtonElement>;
  
  // 样式扩展
  className?: string;
  style?: React.CSSProperties;
  
  // 无障碍
  ariaLabel?: string;
  
  // 数据测试
  'data-testid'?: string;
}

// components/atoms/Button/Button.tsx
export const Button: FC<ButtonProps> = ({
  variant = 'primary',
  size = 'md',
  type = 'button',
  disabled = false,
  loading = false,
  children,
  icon,
  iconPosition = 'left',
  onClick,
  className = '',
  style,
  ariaLabel,
  'data-testid': testId,
}) => {
  // 组件实现...
};

3.3 组件复用性设计

高阶组件 (HOC) 示例
// hoc/withLoading.tsx
import React from 'react';

interface WithLoadingProps {
  isLoading: boolean;
  loadingComponent?: React.ReactNode;
}

export function withLoading<P extends object>(
  WrappedComponent: React.ComponentType<P>
) {
  return function WithLoadingComponent(
    props: P & WithLoadingProps
  ) {
    const { isLoading, loadingComponent, ...rest } = props;
    
    if (isLoading) {
      return loadingComponent || <Spinner />;
    }
    
    return <WrappedComponent {...(rest as P)} />;
  };
}

// 使用示例
const EnhancedTable = withLoading(DataTable);
<EnhancedTable 
  data={tableData} 
  isLoading={isFetching} 
/>

3.4 组件文档规范

Storybook 故事示例
// components/atoms/Button/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta;

export const Primary: Story = {
  args: {
    variant: 'primary',
    children: 'Primary Button',
  },
};

export const WithIcon: Story = {
  args: {
    variant: 'primary',
    icon: <SaveIcon />,
    children: 'Save',
  },
};

export const Loading: Story = {
  args: {
    variant: 'primary',
    loading: true,
    children: 'Loading...',
  },
};

✨ 四、交互规范

4.1 动画规范

动画类型 持续时间 缓动函数 应用场景
微交互 150ms ease-out 按钮悬停、图标变化
过渡动画 300ms ease-in-out 页面切换、模态框显示
复杂动画 500ms cubic-bezier 数据可视化、图表加载
反馈动画 200ms ease 成功/错误提示、加载状态
CSS 动画配置
// styles/animations.css
:root {
  --transition-fast: 150ms ease-out;
  --transition-normal: 300ms ease-in-out;
  --transition-slow: 500ms cubic-bezier(0.4, 0, 0.2, 1);
}

.fade-in {
  animation: fadeIn var(--transition-normal);
}

.slide-up {
  animation: slideUp var(--transition-normal);
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

4.2 用户反馈规范

✅ 成功反馈

  • 绿色 Toast 通知 (3 秒自动消失)
  • 成功图标动画
  • 操作后页面状态更新

⚠️ 警告反馈

  • 橙色 Toast 通知
  • 确认对话框
  • 表单验证提示

❌ 错误反馈

  • 红色 Toast/Error Banner
  • 错误详情展开
  • 重试机制提示

⏳ 加载反馈

  • Skeleton 骨架屏
  • Spinner 加载动画
  • 进度条指示

4.3 无障碍访问 (A11y) 规范

无障碍最佳实践
// 1. 语义化 HTML
<nav aria-label="主导航">
  <ul role="menubar">
    <li role="none">
      <a role="menuitem" href="/home">首页</a>
    </li>
  </ul>
</nav>

// 2. 键盘导航
<button
  onKeyDown={(e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      handleClick();
    }
  }}
  tabIndex={0}
>
  可聚焦按钮
</button>

// 3. 屏幕阅读器支持
<div role="alert" aria-live="polite">
  {notificationMessage}
</div>

// 4. 焦点管理
useEffect(() => {
  if (isOpen) {
    firstInputRef.current?.focus();
  }
}, [isOpen]);

// 5. 颜色对比度
// 确保文本与背景对比度 ≥ 4.5:1 (WCAG AA)

4.4 性能优化规范

🔌 五、API 集成规范

5.1 API 服务层设计

API 服务封装示例
// services/api.ts
import axios from 'axios';
import type { AxiosInstance, AxiosRequestConfig } from 'axios';

class ApiService {
  private client: AxiosInstance;

  constructor(baseURL: string) {
    this.client = axios.create({
      baseURL,
      timeout: 10000,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    this.setupInterceptors();
  }

  private setupInterceptors() {
    // 请求拦截器
    this.client.interceptors.request.use(
      (config) => {
        const token = useUserStore.getState().token;
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => Promise.reject(error)
    );

    // 响应拦截器
    this.client.interceptors.response.use(
      (response) => response.data,
      (error) => {
        if (error.response?.status === 401) {
          useUserStore.getState().logout();
          window.location.href = '/auth/login';
        }
        return Promise.reject(error);
      }
    );
  }

  async get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.client.get(url, config);
  }

  async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.client.post(url, data, config);
  }

  async put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.client.put(url, data, config);
  }

  async delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.client.delete(url, config);
  }
}

export const api = new ApiService(import.meta.env.VITE_API_BASE_URL);

5.2 React Query 集成

自定义 Hooks 示例
// hooks/useProducts.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { productService } from '@/services/productService';
import type { Product, ProductFilters } from '@/types/product';

export function useProducts(filters: ProductFilters) {
  return useQuery({
    queryKey: ['products', filters],
    queryFn: () => productService.getProducts(filters),
    staleTime: 5 * 60 * 1000, // 5 分钟
  });
}

export function useProduct(id: string) {
  return useQuery({
    queryKey: ['product', id],
    queryFn: () => productService.getProduct(id),
    enabled: !!id,
  });
}

export function useCreateProduct() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: productService.createProduct,
    onSuccess: () => {
      queryClient.invalidateQueries(['products']);
    },
  });
}

export function useUpdateProduct() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: productService.updateProduct,
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries(['products']);
      queryClient.invalidateQueries(['product', variables.id]);
    },
  });
}

🧪 六、测试规范

6.1 单元测试 (Jest + React Testing Library)

组件测试示例
// components/atoms/Button/Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('renders correctly', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
  });

  it('handles click events', () => {
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click me</Button>);
    
    fireEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('shows loading state', () => {
    render(<Button loading>Loading</Button>);
    expect(screen.getByRole('button')).toHaveAttribute('disabled');
  });

  it('respects disabled state', () => {
    const handleClick = jest.fn();
    render(
      <Button disabled onClick={handleClick}>
        Disabled
      </Button>
    );
    
    fireEvent.click(screen.getByRole('button'));
    expect(handleClick).not.toHaveBeenCalled();
  });
});

6.2 E2E 测试 (Playwright)

E2E 测试示例
// tests/e2e/login.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Login Flow', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/auth/login');
  });

  test('successful login', async ({ page }) => {
    await page.fill('[data-testid="email-input"]', 'user@example.com');
    await page.fill('[data-testid="password-input"]', 'password123');
    await page.click('[data-testid="submit-button"]');

    await expect(page).toHaveURL('/dashboard');
    await expect(page.locator('[data-testid="user-menu"]')).toBeVisible();
  });

  test('invalid credentials', async ({ page }) => {
    await page.fill('[data-testid="email-input"]', 'wrong@example.com');
    await page.fill('[data-testid="password-input"]', 'wrongpass');
    await page.click('[data-testid="submit-button"]');

    await expect(page.locator('[data-testid="error-message"]'))
      .toContainText('Invalid credentials');
  });
});

🚀 七、CI/CD 集成规范

7.1 GitHub Actions 工作流

.github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run test:coverage
      - uses: codecov/codecov-action@v3

  build:
    needs: [lint, test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v3
        with:
          name: dist
          path: dist/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: dist
          path: dist/
      - name: Deploy to K8s
        run: |
          kubectl apply -f k8s/deployment.yaml
          kubectl rollout restart deployment/frontend

7.2 Docker 配置

Dockerfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

🤖 八、AI Coding 协同规范

8.1 Claude Code 集成流程

PRD 文档
技术方案
Claude Code
代码生成
人工 Review
测试验证

8.2 Prompt 工程规范

AI 代码生成 Prompt 模板
## 任务描述
请根据以下技术要求生成一个 React 组件:

## 组件名称
{ComponentName}

## 功能需求
- {Requirement1}
- {Requirement2}
- {Requirement3}

## 技术栈
- React 18 + TypeScript
- TailwindCSS for styling
- Zustand for state management

## Props 接口
{TypeScript Interface}

## 设计规范
- 遵循原子设计原则
- 支持暗色模式
- 包含完整的无障碍支持
- 添加 Storybook 故事

## 测试要求
- Jest + React Testing Library 单元测试
- 覆盖率要求:>90%

## 输出格式
请按以下结构输出:
1. 组件 TypeScript 文件
2. 样式文件 (如需要)
3. Storybook 故事文件
4. 测试文件

8.3 代码审查清单

📎 九、附录

9.1 常用工具库推荐

类别 推荐库 用途
状态管理 Zustand, Redux Toolkit 全局状态管理
数据获取 React Query, SWR 服务端状态管理
表单处理 React Hook Form, Formik 表单验证与管理
UI 组件 Radix UI, Headless UI 无样式组件库
样式方案 TailwindCSS, Styled Components CSS 解决方案
测试框架 Jest, Vitest, Playwright 单元/E2E 测试

9.2 参考资源