前端技术方案标准模板

基于 OpenClaw + Claude Code 的端到端研发自动化系统 · 前端研发岗位 Agent 标准化输出

版本 v1.0 | 2026 年 3 月

📑 目录导航

1. 文档概述

🎯 文档目的:本模板为前端研发岗位 Agent 提供标准化的技术方案输出框架,确保在端到端研发自动化系统中,前端技术方案的一致性、完整性和可执行性。

1.1 适用范围

1.2 输入输出定义

📥 输入物
  • 产品需求文档 (PRD)
  • UI/UX 设计稿 (Figma/Sketch)
  • 后端技术方案设计文档
  • 前后端 API 接口协议
  • 业务流程图
📤 输出物
  • 前端技术方案设计文档
  • 页面结构拆解图
  • 组件设计清单
  • 交互流程说明
  • 技术风险评估报告

2. 技术架构设计

2.1 技术栈选型

类别 技术选项 版本要求 选型理由
核心框架 React / Vue 3 React 18+ / Vue 3.3+ 组件化开发、生态完善、性能优异
语言 TypeScript 5.0+ 类型安全、代码智能提示、降低运行时错误
状态管理 Zustand / Pinia 最新稳定版 轻量级、易用、DevTools 支持
路由 React Router / Vue Router v6+ / v4+ 成熟稳定、支持懒加载
UI 组件库 Ant Design / Element Plus 最新稳定版 企业级组件、主题定制能力强
构建工具 Vite 5.0+ 极速启动、热更新、打包优化
HTTP 客户端 Axios / TanStack Query 最新稳定版 请求拦截、缓存策略、错误处理
测试框架 Vitest + Testing Library 最新稳定版 快速执行、覆盖率报告、组件测试

2.2 整体架构图

用户层
展示层 (Pages/Layouts)
组件层 (Components)
状态管理层 (Store)
服务层 (API/Hooks)
后端服务

2.3 目录结构规范

# 标准项目目录结构 src/ ├── assets/ # 静态资源 │ ├── images/ │ ├── fonts/ │ └── styles/ # 全局样式 ├── components/ # 公共组件 │ ├── base/ # 基础组件 │ ├── business/ # 业务组件 │ └── layouts/ # 布局组件 ├── pages/ # 页面组件 ├── hooks/ # 自定义 Hooks ├── stores/ # 状态管理 ├── services/ # API 服务 ├── utils/ # 工具函数 ├── types/ # TypeScript 类型定义 ├── constants/ # 常量定义 ├── config/ # 配置文件 ├── routes/ # 路由配置 └── App.tsx

3. 页面结构设计规范

3.1 路由设计规范

路由命名原则:使用 kebab-case,语义清晰,符合 RESTful 风格
// 路由配置示例 const routes: RouteRecordRaw[] = [ { path: '/', component: Layout, children: [ { path: 'dashboard', name: 'Dashboard', component: () => import('@/pages/Dashboard/index.vue'), meta: { title: '工作台', requiresAuth: true, keepAlive: true } }, { path: 'user-management/:id', name: 'UserDetail', component: () => import('@/pages/User/Detail.vue'), meta: { title: '用户详情' } } ] } ]

3.2 页面组件拆分原则

📄 Page 层
  • 负责数据获取
  • 状态初始化
  • 页面级布局
  • 路由参数处理
🧩 Section 层
  • 页面功能区块
  • 独立业务逻辑
  • 可复用模块
  • 数据转换处理
🔷 Component 层
  • 纯 UI 组件
  • props/emit 通信
  • 无副作用
  • 高可复用性

3.3 布局系统

// 布局组件结构 interface LayoutProps { showHeader?: boolean; showSidebar?: boolean; showFooter?: boolean; sidebarWidth?: string; } // 响应式断点 const breakpoints = { mobile: '(max-width: 768px)', tablet: '(max-width: 1024px)', desktop: '(min-width: 1025px)' }

4. 组件设计规范

4.1 组件分类体系

组件类型 职责 示例 存放位置
基础组件 原子级 UI 元素,无业务逻辑 Button, Input, Modal components/base/
业务组件 包含业务逻辑的可复用组件 UserTable, ProductCard components/business/
复合组件 组合多个组件完成复杂功能 DataTable, FormWizard components/composite/
布局组件 页面结构布局 Header, Sidebar, Container components/layouts/

4.2 组件 API 设计标准

Props 设计原则:单一职责、类型明确、默认值合理、避免双向绑定
// 组件 Props 定义示例 (Vue 3 + TypeScript) interface UserTableProps { // 数据源 dataSource: UserType[]; // 列配置 columns: ColumnType[]; // 加载状态 loading?: boolean; // 分页配置 pagination?: PaginationConfig; // 行选择模式 rowSelection?: 'checkbox' | 'radio'; // 尺寸 size?: 'small' | 'medium' | 'large'; } // 组件事件定义 interface UserTableEmits { (e: 'rowClick', row: UserType): void; (e: 'selectionChange', selectedRows: UserType[]): void; (e: 'pageChange', page: number): void; (e: 'sortChange', sorter: SorterResult): void; }

4.3 组件文档模板

/** * UserTable 用户表格组件 * * @description 用于展示用户列表数据,支持排序、筛选、分页等功能 * * @param {UserType[]} dataSource - 表格数据源 * @param {ColumnType[]} columns - 列配置数组 * @param {boolean} [loading=false] - 加载状态 * @param {PaginationConfig} [pagination] - 分页配置 * @param {'checkbox'|'radio'} [rowSelection] - 行选择模式 * * @event {Function} rowClick - 行点击事件 * @event {Function} selectionChange - 选择变化事件 * @event {Function} pageChange - 分页变化事件 * * @slot header - 自定义表头 * @slot action - 操作列插槽 * * @example * <UserTable * :data-source="users" * :columns="columns" * @row-click="handleRowClick" * /> */

5. 交互设计规范

5.1 用户操作流程规范

用户触发
事件捕获
数据验证
状态更新
UI 反馈
异步请求
结果处理

5.2 表单交互规范

✅ 验证规则
  • 实时验证 + 提交前验证
  • 错误信息清晰明确
  • 必填项标识明显
  • 支持键盘导航
  • 自动聚焦首个错误字段
⚡ 用户体验
  • 防抖处理 (300ms)
  • 提交按钮 Loading 状态
  • 防止重复提交
  • 表单自动保存草稿
  • 支持快捷键提交 (Ctrl+S)

5.3 反馈机制

反馈类型 使用场景 持续时间 组件
Success 操作成功 3s 自动关闭 Message/Notification
Error 操作失败/异常 手动关闭 Modal/Notification
Warning 警告提示 5s 自动关闭 Message
Loading 异步操作进行中 操作完成 Spin/Button.loading
Info 信息提示 4s 自动关闭 Message

5.4 空状态处理

// 空状态组件规范 interface EmptyStateProps { image?: string; // 空状态图片 description?: string; // 描述文案 action?: { text: string; onClick: () => void; }; } // 常见空状态文案 const EMPTY_STATES = { NO_DATA: '暂无数据', NO_SEARCH_RESULT: '未找到相关结果', NO_PERMISSION: '暂无访问权限', NETWORK_ERROR: '网络异常,请重试' }

6. 状态管理规范

6.1 状态分层策略

🌐 全局状态
  • 用户信息
  • 权限配置
  • 主题设置
  • 系统配置
📁 模块状态
  • 页面级数据
  • 列表筛选条件
  • 表单数据
  • 弹窗状态
🔸 组件状态
  • UI 交互状态
  • 本地临时数据
  • 受控组件值
  • 动画状态

6.2 Store 设计规范

// Zustand Store 示例 interface UserStore { // State userInfo: UserInfo | null; permissions: string[]; isLoading: boolean; // Actions fetchUserInfo: () => Promise<void>; updateUserInfo: (data: Partial<UserInfo>) => void; logout: () => void; hasPermission: (permission: string) => boolean; } const useUserStore = create<UserStore>((set, get) => ({ userInfo: null, permissions: [], isLoading: false, fetchUserInfo: async () => { set({ isLoading: true }); try { const data = await api.getUserInfo(); set({ userInfo: data, permissions: data.permissions }); } finally { set({ isLoading: false }); } }, hasPermission: (permission) => get().permissions.includes(permission) }))

6.3 服务端状态管理

推荐使用 TanStack Query:自动缓存、背景更新、重试机制、请求去重
// React Query Hook 封装 export function useUserList(params: UserQueryParams) { return useQuery({ queryKey: ['users', params], queryFn: () => api.getUserList(params), staleTime: 5 * 60 * 1000, // 5 分钟新鲜度 retry: 2, retryDelay: attemptIndex => Math.min(1000 * Math.pow(2, attemptIndex), 30000) }); } export function useUpdateUser() { const queryClient = useQueryClient(); return useMutation({ mutationFn: api.updateUser, onSuccess: () => { // 无效化用户列表缓存 queryClient.invalidateQueries({ queryKey: ['users'] }); } }); }

7. API 接口对接规范

7.1 HTTP 请求封装

// Axios 实例配置 const apiClient = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 30000, headers: { 'Content-Type': 'application/json' } }); // 请求拦截器 apiClient.interceptors.request.use( (config) => { const token = localStorage.getItem('access_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } // 添加请求 ID 用于追踪 config.headers['X-Request-ID'] = generateRequestId(); return config; }, (error) => Promise.reject(error) ); // 响应拦截器 apiClient.interceptors.response.use( (response) => { const { code, data, message } = response.data; if (code === 200) { return data; } // 业务错误处理 handleBusinessError(code, message); return Promise.reject(new Error(message)); }, (error) => { // HTTP 错误处理 if (error.response?.status === 401) { handleUnauthorized(); } return Promise.reject(error); } );

7.2 API 服务层组织

// services/user.ts import apiClient from '@/utils/request'; import type { UserType, UserQueryParams } from '@/types/user'; export const userService = { /** * 获取用户列表 */ getUserList: (params: UserQueryParams) => { return apiClient.get<UserType[]>('/api/users', { params }); }, /** * 获取用户详情 */ getUserById: (id: string) => { return apiClient.get<UserType>(`/api/users/${id}`); }, /** * 创建用户 */ createUser: (data: CreateUserDTO) => { return apiClient.post<UserType>('/api/users', data); }, /** * 更新用户 */ updateUser: (id: string, data: UpdateUserDTO) => { return apiClient.put<UserType>(`/api/users/${id}`, data); }, /** * 删除用户 */ deleteUser: (id: string) => { return apiClient.delete(`/api/users/${id}`); } };

7.3 接口响应类型定义

// types/api.ts export interface ApiResponse<T> { code: number; data: T; message: string; timestamp: number; } export interface PageResponse<T> { list: T[]; total: number; page: number; pageSize: number; totalPages: number; } export interface QueryParams { page?: number; pageSize?: number; sortField?: string; sortOrder?: 'ascend' | 'descend'; [key: string]: any; }

8. 开发环境与工程配置

8.1 环境变量配置

# .env.development VITE_APP_TITLE="开发环境" VITE_API_BASE_URL="/api/dev" VITE_WS_URL="ws://localhost:8080/ws" # .env.production VITE_APP_TITLE="生产环境" VITE_API_BASE_URL="/api/prod" VITE_WS_URL="wss://example.com/ws"

8.2 Vite 配置

// vite.config.ts import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import path from 'path'; export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': path.resolve(__dirname, './src') } }, server: { port: 3000, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }, build: { rollupOptions: { output: { manualChunks: { vendor: ['vue', 'vue-router', 'pinia'], ui: ['element-plus'] } } }, chunkSizeWarningLimit: 1500 } });

8.3 脚本命令

// package.json scripts { "scripts": { "dev": "vite", "build": "vue-tsc && vite build", "preview": "vite preview", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx --fix", "type-check": "vue-tsc --noEmit", "test": "vitest", "test:coverage": "vitest --coverage", "test:e2e": "playwright test" } }

9. 代码规范与质量保障

9.1 ESLint 配置

// .eslintrc.cjs module.exports = { root: true, env: { browser: true, es2021: true, node: true }, extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-recommended' ], parser: 'vue-eslint-parser', parserOptions: { ecmaVersion: 'latest', parser: '@typescript-eslint/parser', sourceType: 'module' }, rules: { 'no-console': 'warn', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], 'vue/multi-word-component-names': 'off' } }

9.2 命名规范

类型 命名规则 示例
文件/文件夹 PascalCase (组件) / camelCase (其他) UserTable.vue, userService.ts
组件名 PascalCase,多单词 UserTable, ProductCard
变量/函数 camelCase userInfo, getUserList
常量 UPPER_SNAKE_CASE MAX_RETRY_COUNT, API_TIMEOUT
类型/接口 PascalCase UserType, ApiResponse
CSS 类名 kebab-case user-table, btn-primary

9.3 Git 工作流

分支策略:采用 Git Flow 工作流,支持 CI/CD 自动化
# 分支命名规范 main # 主分支,生产环境 develop # 开发分支 feature/* # 功能分支 (feature/user-management) release/* # 发布分支 (release/v1.2.0) hotfix/* # 热修复分支 (hotfix/login-bug) # Commit Message 规范 (Conventional Commits) <type>(<scope>): <subject> # type 类型: feat: # 新功能 fix: # Bug 修复 docs: # 文档更新 style: # 代码格式调整 refactor: # 重构 test: # 测试相关 chore: # 构建/工具链 # 示例: feat(user): 添加用户批量删除功能 fix(auth): 修复登录 token 过期问题 refactor(api): 重构 HTTP 请求拦截器

10. 测试策略

10.1 测试金字塔

🔺
少量 E2E 测试 适量集成测试 大量单元测试

10.2 单元测试规范

// __tests__/userService.test.ts import { describe, it, expect, vi, beforeEach } from 'vitest'; import { userService } from '@/services/user'; import apiClient from '@/utils/request'; vi.mock('@/utils/request'); describe('userService', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should fetch user list successfully', async () => { // Arrange const mockUsers = [ { id: '1', name: 'John' }, { id: '2', name: 'Jane' } ]; vi.mocked(apiClient.get).mockResolvedValue(mockUsers); // Act const result = await userService.getUserList({ page: 1 }); // Assert expect(result).toEqual(mockUsers); expect(apiClient.get).toHaveBeenCalledWith('/api/users', { params: { page: 1 } }); }); it('should handle error when fetch fails', async () => { // Arrange vi.mocked(apiClient.get).mockRejectedValue(new Error('Network Error')); // Act & Assert await expect(userService.getUserList({})) .rejects.toThrow('Network Error'); }); });

10.3 组件测试

// __tests__/UserTable.test.tsx import { render, screen, fireEvent } from '@testing-library/vue'; import UserTable from '@/components/business/UserTable.vue'; describe('UserTable', () => { const defaultProps = { dataSource: [ { id: '1', name: 'John', email: 'john@example.com' }, { id: '2', name: 'Jane', email: 'jane@example.com' } ], columns: [ { key: 'name', title: '姓名' }, { key: 'email', title: '邮箱' } ] }; it('renders user data correctly', () => { render(UserTable, { props: defaultProps }); expect(screen.getByText('John')).toBeInTheDocument(); expect(screen.getByText('jane@example.com')).toBeInTheDocument(); }); it('emits rowClick event when row is clicked', async () => { const { emitted } = render(UserTable, { props: defaultProps }); const firstRow = screen.getByText('John').closest('tr'); await fireEvent.click(firstRow); expect(emitted().rowClick).toHaveLength(1); expect(emitted().rowClick[0]).toEqual([defaultProps.dataSource[0]]); }); });

10.4 E2E 测试

// e2e/user-management.spec.ts (Playwright) import { test, expect } from '@playwright/test'; test.describe('User Management', () => { test.beforeEach(async ({ page }) => { await page.goto('/login'); await page.fill('[name="username"]', 'admin'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]'); await expect(page).toHaveURL('/dashboard'); }); test('should create new user successfully', async ({ page }) => { await page.goto('/users'); // Click create button await page.click('text=新建用户'); // Fill form await page.fill('[name="name"]', 'Test User'); await page.fill('[name="email"]', 'test@example.com'); // Submit await page.click('button[type="submit"]'); // Verify success message await expect(page.locator('.ant-message-success')).toBeVisible(); // Verify user in table await expect(page.getByText('Test User')).toBeVisible(); }); });

11. 部署与监控

11.1 Docker 配置

# Dockerfile FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build 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;"]

11.2 Nginx 配置

# nginx.conf server { listen 80; server_name example.com; root /usr/share/nginx/html; index index.html; # Gzip 压缩 gzip on; gzip_types text/plain application/javascript text/css application/json; # 历史路由支持 location / { try_files $uri $uri/ /index.html; } # API 代理 location /api/ { proxy_pass http://backend:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 缓存策略 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } }

11.3 K8S 部署配置

# k8s/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: frontend-app namespace: production spec: replicas: 3 selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: containers: - name: frontend image: registry.example.com/frontend:v1.0.0 ports: - containerPort: 80 resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m" livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 10 periodSeconds: 10 --- apiVersion: v1 kind: Service metadata: name: frontend-service spec: selector: app: frontend ports: - port: 80 targetPort: 80 type: ClusterIP

11.4 监控指标

📊 性能监控
  • FCP (First Contentful Paint)
  • LCP (Largest Contentful Paint)
  • FID (First Input Delay)
  • CLS (Cumulative Layout Shift)
  • API 响应时间
⚠️ 错误监控
  • JS 运行时错误
  • 资源加载失败
  • API 请求错误
  • 白屏检测
  • 性能降级告警

12. 人机协同工作流程

12.1 AI Coding 工作流

PRD 输入
Claude Code
生成技术方案
人工审核
AI 生成代码
人工 Review
自动化测试
CI/CD 部署

12.2 人机协同检查清单

阶段 AI 负责 人工负责
技术方案 生成初稿、组件拆分、API 设计 架构评审、技术选型确认、风险评估
代码开发 生成组件代码、单元测试 代码 Review、边界情况处理、性能优化
测试验证 生成测试用例、执行自动化测试 探索性测试、用户体验验证、验收测试
部署上线 生成部署配置、执行 CI/CD 灰度发布决策、线上监控、应急响应

12.3 Prompt 工程最佳实践

高效 Prompt 模板:角色设定 + 任务描述 + 约束条件 + 输出格式 + 示例
# 前端技术方案生成 Prompt 示例 You are an expert front-end architect with 10+ years of experience. Task: Generate a comprehensive front-end technical solution for [FEATURE_NAME] Requirements: 1. Use Vue 3 + TypeScript + Vite stack 2. Follow enterprise-level code standards 3. Include component design, state management, API integration 4. Consider performance optimization and accessibility Output Format: - Technical architecture diagram - Component hierarchy - Directory structure - Key code examples - Risk assessment Context: - PRD: [Attach PRD summary] - API Docs: [Attach API specification] - UI Design: [Attach Figma link]

📎 附录

附录 A: 常用工具库推荐

工具类
  • lodash-es - 工具函数
  • dayjs - 日期处理
  • axios - HTTP 客户端
  • qs - 查询字符串解析
UI 增强
  • @vueuse/core - Composition API 工具集
  • animate.css - 动画库
  • echarts - 图表库
  • virtual-scroller - 虚拟滚动
开发工具
  • prettier - 代码格式化
  • husky - Git hooks
  • commitlint - Commit 规范
  • size-limit - 包大小限制

附录 B: 参考资源