React+TypeScript Agent开发规范

React + TypeScript Agent 开发规范 (Development Rules)

文章目录

  • [React + TypeScript Agent 开发规范 (Development Rules)](#React + TypeScript Agent 开发规范 (Development Rules))
      • [1. 项目架构与文件组织](#1. 项目架构与文件组织)
      • [2. 类型安全规范 (Strict TypeScript)](#2. 类型安全规范 (Strict TypeScript))
      • [3. 组件开发规范](#3. 组件开发规范)
      • [4. Hooks 开发规范](#4. Hooks 开发规范)
      • [5. 状态管理规范](#5. 状态管理规范)
      • [6. 数据获取规范 (TanStack Query)](#6. 数据获取规范 (TanStack Query))
      • [7. 表单处理规范 (React Hook Form + Zod)](#7. 表单处理规范 (React Hook Form + Zod))
      • [8. 性能优化规范](#8. 性能优化规范)
      • [9. 错误处理规范](#9. 错误处理规范)
      • [10. 测试规范](#10. 测试规范)
      • [11. ESLint & 代码质量配置](#11. ESLint & 代码质量配置)
      • [12. Agent 指令模板](#12. Agent 指令模板)

1. 项目架构与文件组织

typescript 复制代码
// 强制目录结构
src/
├── components/          // 纯展示组件 (Presentational)
│   ├── ui/             // 原子级基础组件 (Button, Input, Card)
│   ├── forms/          // 表单相关组件
│   └── layout/         // 布局组件 (Header, Sidebar, Footer)
├── features/           // 功能模块 (按业务域划分)
│   ├── auth/
│   │   ├── components/ // 该功能专用组件
│   │   ├── hooks/      // 该功能专用 Hooks
│   │   ├── services/   // API 调用
│   │   ├── types/      // 领域类型定义
│   │   └── utils/      // 工具函数
│   └── dashboard/
├── hooks/              // 全局通用 Hooks
├── lib/                // 第三方库配置 (axios, queryClient)
├── providers/          // React Context Providers
├── routes/             // 路由配置
├── stores/             // 状态管理 (Zustand/Redux)
├── styles/             // 全局样式、主题配置
├── types/              // 全局类型定义
├── utils/              // 纯工具函数 (无 React 依赖)
└── App.tsx

Agent 必须遵守:

  • 组件文件使用 PascalCase:UserProfile.tsx
  • 工具文件使用 camelCase:formatDate.ts
  • 类型文件使用 .types.ts 后缀:user.types.ts
  • 每个文件夹必须包含 index.ts 进行统一导出

2. 类型安全规范 (Strict TypeScript)

typescript 复制代码
// ✅ 必须:启用严格模式 (tsconfig.json)
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true
  }
}

// ✅ 必须:明确定义组件 Props 类型
interface UserCardProps {
  user: User;
  onEdit?: (id: string) => void;
  variant?: 'default' | 'compact';
}

// ❌ 禁止:使用 any
function processData(data: any) { ... }

// ✅ 必须:使用 unknown 并类型收窄
function processData(data: unknown) {
  if (isUser(data)) {
    // 类型安全操作
  }
}

// ✅ 必须:使用 satisfies 进行类型验证
const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000
} satisfies AppConfig;

// ✅ 必须:泛型组件明确定义约束
interface ListProps<T extends { id: string }> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
}

3. 组件开发规范

typescript 复制代码
// ✅ 必须:使用函数组件 + Hooks,禁止 Class 组件
// ✅ 必须:默认导出组件,Props 作为命名导出类型

// components/ui/Button.tsx
import { forwardRef, type ComponentPropsWithoutRef } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/utils/cn';

// 1. 定义样式变体
const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
        destructive: 'bg-destructive text-destructive-foreground',
        outline: 'border border-input bg-background hover:bg-accent',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
        link: 'text-primary underline-offset-4 hover:underline'
      },
      size: {
        default: 'h-10 px-4 py-2',
        sm: 'h-9 rounded-md px-3',
        lg: 'h-11 rounded-md px-8',
        icon: 'h-10 w-10'
      }
    },
    defaultVariants: {
      variant: 'default',
      size: 'default'
    }
  }
);

// 2. 定义 Props 类型(必须继承原生属性)
export interface ButtonProps
  extends ComponentPropsWithoutRef<'button'>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
  loading?: boolean;
}

// 3. 使用 forwardRef 支持 ref 转发
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, loading, disabled, children, ...props }, ref) => {
    const Comp = asChild ? Slot : 'button';
    
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        disabled={disabled || loading}
        {...props}
      >
        {loading && <Spinner className="mr-2 h-4 w-4 animate-spin" />}
        {children}
      </Comp>
    );
  }
);

Button.displayName = 'Button';

// 4. 统一导出
export { buttonVariants };

组件开发 checklist:

  • 使用 forwardRef 支持 ref 转发
  • Props 类型继承原生 HTML 属性 (ComponentPropsWithoutRef)
  • 使用 displayName 便于调试
  • 支持 className 合并(使用 cn 工具函数)
  • 加载状态、禁用状态处理
  • 无障碍属性 (aria-label, role 等)

4. Hooks 开发规范

typescript 复制代码
// ✅ 必须:自定义 Hook 以 use 开头
// ✅ 必须:返回类型使用 as const 或明确接口

// hooks/useAsync.ts
import { useState, useCallback, useRef, useEffect } from 'react';

interface UseAsyncOptions<T> {
  immediate?: boolean;
  onSuccess?: (data: T) => void;
  onError?: (error: Error) => void;
}

interface UseAsyncReturn<T, Args extends unknown[]> {
  execute: (...args: Args) => Promise<T | undefined>;
  data: T | null;
  error: Error | null;
  isLoading: boolean;
  isSuccess: boolean;
  isError: boolean;
  reset: () => void;
}

export function useAsync<T, Args extends unknown[] = []>(
  asyncFunction: (...args: Args) => Promise<T>,
  options: UseAsyncOptions<T> = {}
): UseAsyncReturn<T, Args> {
  const { immediate = false, onSuccess, onError } = options;
  
  const [state, setState] = useState<{
    data: T | null;
    error: Error | null;
    isLoading: boolean;
    status: 'idle' | 'pending' | 'success' | 'error';
  }>({
    data: null,
    error: null,
    isLoading: false,
    status: 'idle'
  });

  // 使用 ref 避免闭包问题
  const asyncFunctionRef = useRef(asyncFunction);
  const isMountedRef = useRef(true);

  useEffect(() => {
    asyncFunctionRef.current = asyncFunction;
  }, [asyncFunction]);

  useEffect(() => {
    return () => {
      isMountedRef.current = false;
    };
  }, []);

  const execute = useCallback(async (...args: Args): Promise<T | undefined> => {
    setState(prev => ({ ...prev, isLoading: true, status: 'pending' }));

    try {
      const data = await asyncFunctionRef.current(...args);
      
      if (isMountedRef.current) {
        setState({ data, error: null, isLoading: false, status: 'success' });
        onSuccess?.(data);
      }
      
      return data;
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      
      if (isMountedRef.current) {
        setState({ data: null, error: err, isLoading: false, status: 'error' });
        onError?.(err);
      }
      
      throw err;
    }
  }, [onSuccess, onError]);

  const reset = useCallback(() => {
    setState({ data: null, error: null, isLoading: false, status: 'idle' });
  }, []);

  // 立即执行逻辑
  useEffect(() => {
    if (immediate) {
      execute();
    }
  }, [immediate, execute]);

  return {
    execute,
    data: state.data,
    error: state.error,
    isLoading: state.isLoading,
    isSuccess: state.status === 'success',
    isError: state.status === 'error',
    reset
  } as const;
}

// ✅ 必须:提供使用示例和文档注释
/**
 * 用于管理异步操作的 Hook
 * @example
 * const { data, isLoading, execute } = useAsync(fetchUser, { immediate: true });
 * 
 * // 手动触发
 * const handleSubmit = async (id: string) => {
 *   const result = await execute(id);
 * };
 */

Hooks 开发 checklist:

  • 处理组件卸载时的内存泄漏
  • 使用 useRef 解决闭包陈旧问题
  • 返回稳定的引用(使用 useCallback/useMemo
  • 提供完整的类型定义和 JSDoc
  • 支持取消/重置操作

5. 状态管理规范

typescript 复制代码
// ✅ 推荐:使用 Zustand 进行状态管理
// stores/userStore.ts
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';

interface User {
  id: string;
  email: string;
  name: string;
  role: 'admin' | 'user';
}

interface UserState {
  // State
  user: User | null;
  isAuthenticated: boolean;
  preferences: {
    theme: 'light' | 'dark' | 'system';
    language: string;
  };
  
  // Computed (使用 selector 模式)
  isAdmin: () => boolean;
  
  // Actions
  setUser: (user: User | null) => void;
  updatePreferences: (prefs: Partial<UserState['preferences']>) => void;
  logout: () => void;
}

export const useUserStore = create<UserState>()(
  devtools(
    persist(
      immer((set, get) => ({
        // Initial state
        user: null,
        isAuthenticated: false,
        preferences: {
          theme: 'system',
          language: 'zh-CN'
        },
        
        // Computed
        isAdmin: () => get().user?.role === 'admin',
        
        // Actions
        setUser: (user) => set((state) => {
          state.user = user;
          state.isAuthenticated = !!user;
        }),
        
        updatePreferences: (prefs) => set((state) => {
          Object.assign(state.preferences, prefs);
        }),
        
        logout: () => set((state) => {
          state.user = null;
          state.isAuthenticated = false;
        })
      })),
      {
        name: 'user-storage',
        partialize: (state) => ({ 
          preferences: state.preferences 
          // 不持久化敏感信息
        })
      }
    ),
    { name: 'UserStore' }
  )
);

// ✅ 必须:使用 Selector 优化重渲染
// 组件中使用
function UserProfile() {
  // ❌ 错误:订阅整个 store
  const { user } = useUserStore();
  
  // ✅ 正确:只订阅需要的字段
  const userName = useUserStore(state => state.user?.name);
  
  // ✅ 正确:使用 selector 进行复杂计算
  const isAdmin = useUserStore(state => state.isAdmin());
  
  // ✅ 正确:使用 shallow 比较数组/对象
  const preferences = useUserStore(
    state => state.preferences,
    shallow
  );
}

6. 数据获取规范 (TanStack Query)

typescript 复制代码
// ✅ 必须:使用 TanStack Query 进行服务端状态管理
// features/users/api/queries.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { userApi } from './api';
import type { User, CreateUserInput, UpdateUserInput } from './types';

// Query Keys 工厂模式
export const userKeys = {
  all: ['users'] as const,
  lists: () => [...userKeys.all, 'list'] as const,
  list: (filters: UserFilters) => [...userKeys.lists(), filters] as const,
  details: () => [...userKeys.all, 'detail'] as const,
  detail: (id: string) => [...userKeys.details(), id] as const,
};

// 获取用户列表
export function useUsers(filters: UserFilters) {
  return useQuery({
    queryKey: userKeys.list(filters),
    queryFn: () => userApi.getUsers(filters),
    staleTime: 5 * 60 * 1000, // 5分钟
    gcTime: 10 * 60 * 1000,   // 10分钟
    select: (data) => ({
      ...data,
      users: data.users.map(normalizeUser) // 数据转换
    })
  });
}

// 获取单个用户
export function useUser(id: string) {
  return useQuery({
    queryKey: userKeys.detail(id),
    queryFn: () => userApi.getUser(id),
    enabled: !!id, // 条件查询
    retry: (failureCount, error) => {
      if (error.status === 404) return false; // 404 不重试
      return failureCount < 3;
    }
  });
}

// 创建用户
export function useCreateUser() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (input: CreateUserInput) => userApi.createUser(input),
    onSuccess: (newUser) => {
      // 乐观更新或重新获取
      queryClient.invalidateQueries({ queryKey: userKeys.lists() });
      queryClient.setQueryData(userKeys.detail(newUser.id), newUser);
    },
    onError: (error) => {
      toast.error(`创建失败: ${error.message}`);
    }
  });
}

// 组件中使用
function UserList() {
  const [filters, setFilters] = useState({ page: 1, search: '' });
  const { data, isLoading, error, isFetching } = useUsers(filters);
  
  if (isLoading) return <Skeleton />;
  if (error) return <ErrorBoundary error={error} />;
  
  return (
    <div>
      {isFetching && <LoadingOverlay />}
      <UserTable data={data.users} />
    </div>
  );
}

7. 表单处理规范 (React Hook Form + Zod)

typescript 复制代码
// ✅ 必须:使用 React Hook Form + Zod 进行表单验证
// features/auth/components/LoginForm.tsx
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

// 1. 定义 Schema
const loginSchema = z.object({
  email: z.string().email('请输入有效的邮箱地址'),
  password: z.string().min(8, '密码至少需要8位'),
  rememberMe: z.boolean().default(false)
});

type LoginFormData = z.infer<typeof loginSchema>;

export function LoginForm() {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting, isDirty, isValid },
    setError,
    reset
  } = useForm<LoginFormData>({
    resolver: zodResolver(loginSchema),
    mode: 'onBlur', // 验证时机
    defaultValues: {
      email: '',
      password: '',
      rememberMe: false
    }
  });

  const onSubmit = async (data: LoginFormData) => {
    try {
      await authApi.login(data);
      reset();
    } catch (error) {
      // 设置表单级错误
      if (error.code === 'INVALID_CREDENTIALS') {
        setError('root', {
          message: '邮箱或密码错误'
        });
      }
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      <div>
        <Label htmlFor="email">邮箱</Label>
        <Input
          id="email"
          type="email"
          {...register('email')}
          aria-invalid={!!errors.email}
        />
        {errors.email && (
          <ErrorMessage>{errors.email.message}</ErrorMessage>
        )}
      </div>

      <div>
        <Label htmlFor="password">密码</Label>
        <Input
          id="password"
          type="password"
          {...register('password')}
        />
        {errors.password && (
          <ErrorMessage>{errors.password.message}</ErrorMessage>
        )}
      </div>

      <div className="flex items-center space-x-2">
        <Checkbox id="rememberMe" {...register('rememberMe')} />
        <Label htmlFor="rememberMe">记住我</Label>
      </div>

      {errors.root && (
        <Alert variant="destructive">{errors.root.message}</Alert>
      )}

      <Button 
        type="submit" 
        disabled={!isDirty || !isValid || isSubmitting}
        loading={isSubmitting}
      >
        登录
      </Button>
    </form>
  );
}

8. 性能优化规范

typescript 复制代码
// ✅ 必须:使用 React.memo 优化纯展示组件
interface ExpensiveListProps {
  items: Item[];
  onItemClick: (id: string) => void;
}

export const ExpensiveList = React.memo<ExpensiveListProps>(
  function ExpensiveList({ items, onItemClick }) {
    return (
      <ul>
        {items.map(item => (
          <ListItem 
            key={item.id} 
            item={item} 
            onClick={onItemClick}
          />
        ))}
      </ul>
    );
  },
  (prevProps, nextProps) => {
    // 自定义比较函数
    return (
      prevProps.items === nextProps.items &&
      prevProps.onItemClick === nextProps.onItemClick
    );
  }
);

// ✅ 必须:使用 useMemo 缓存计算
function Dashboard({ data }: { data: DataPoint[] }) {
  const stats = useMemo(() => {
    return data.reduce((acc, point) => ({
      total: acc.total + point.value,
      avg: acc.avg + point.value / data.length,
      max: Math.max(acc.max, point.value)
    }), { total: 0, avg: 0, max: 0 });
  }, [data]);

  // ✅ 必须:使用 useCallback 缓存回调
  const handleRefresh = useCallback(() => {
    refetch();
  }, [refetch]);

  return <DashboardView stats={stats} onRefresh={handleRefresh} />;
}

// ✅ 必须:代码分割和懒加载
const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<PageSkeleton />}>
      <HeavyComponent />
    </Suspense>
  );
}

// ✅ 必须:虚拟列表处理大数据
import { useVirtualizer } from '@tanstack/react-virtual';

function VirtualList({ items }: { items: Item[] }) {
  const parentRef = useRef<HTMLDivElement>(null);
  
  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
    overscan: 5
  });

  return (
    <div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
      <div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
        {virtualizer.getVirtualItems().map((virtualItem) => (
          <div
            key={virtualItem.key}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: `${virtualItem.size}px`,
              transform: `translateY(${virtualItem.start}px)`
            }}
          >
            {items[virtualItem.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}

9. 错误处理规范

typescript 复制代码
// ✅ 必须:使用 Error Boundary 捕获渲染错误
// components/ErrorBoundary.tsx
import { Component, type ErrorInfo, type ReactNode } from 'react';

interface Props {
  children: ReactNode;
  fallback?: ReactNode;
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
}

interface State {
  hasError: boolean;
  error: Error | null;
}

export class ErrorBoundary extends Component<Props, State> {
  state: State = { hasError: false, error: null };

  static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.error('Error caught by boundary:', error, errorInfo);
    this.props.onError?.(error, errorInfo);
    // 上报到监控服务
    reportError(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback || <DefaultErrorFallback error={this.state.error} />;
    }
    return this.props.children;
  }
}

// ✅ 必须:API 错误统一处理
// lib/api.ts
import axios, { AxiosError } from 'axios';

class ApiError extends Error {
  constructor(
    message: string,
    public status: number,
    public code: string,
    public data?: unknown
  ) {
    super(message);
    this.name = 'ApiError';
  }
}

api.interceptors.response.use(
  (response) => response.data,
  (error: AxiosError) => {
    if (error.response) {
      throw new ApiError(
        error.response.data?.message || '请求失败',
        error.response.status,
        error.response.data?.code || 'UNKNOWN_ERROR',
        error.response.data
      );
    }
    throw new ApiError('网络错误', 0, 'NETWORK_ERROR');
  }
);

// ✅ 必须:使用 react-error-boundary 处理异步错误
import { ErrorBoundary } from 'react-error-boundary';

function QueryErrorBoundary({ children }: { children: ReactNode }) {
  return (
    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onReset={() => {
        // 重置 QueryClient
        queryClient.clear();
      }}
    >
      {children}
    </ErrorBoundary>
  );
}

10. 测试规范

typescript 复制代码
// ✅ 必须:组件使用 Testing Library + Vitest
// Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
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 = vi.fn();
    render(<Button onClick={handleClick}>Click me</Button>);
    
    fireEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('is disabled when loading', () => {
    render(<Button loading>Loading</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
    expect(screen.getByRole('status')).toBeInTheDocument(); // spinner
  });

  it('forwards ref correctly', () => {
    const ref = { current: null as HTMLButtonElement | null };
    render(<Button ref={ref}>Click me</Button>);
    expect(ref.current).toBeInstanceOf(HTMLButtonElement);
  });
});

// ✅ 必须:Hooks 使用 renderHook 测试
// hooks/useAsync.test.ts
import { renderHook, waitFor } from '@testing-library/react';
import { useAsync } from './useAsync';

describe('useAsync', () => {
  it('handles successful execution', async () => {
    const mockFn = vi.fn().mockResolvedValue('data');
    const { result } = renderHook(() => useAsync(mockFn));
    
    expect(result.current.isLoading).toBe(false);
    
    act(() => {
      result.current.execute();
    });
    
    expect(result.current.isLoading).toBe(true);
    
    await waitFor(() => {
      expect(result.current.isSuccess).toBe(true);
      expect(result.current.data).toBe('data');
    });
  });
});

11. ESLint & 代码质量配置

json 复制代码
// .eslintrc.json
{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended-type-checked",
    "plugin:@typescript-eslint/stylistic-type-checked",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:jsx-a11y/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "plugins": ["@typescript-eslint", "react", "react-refresh"],
  "rules": {
    "react-refresh/only-export-components": "warn",
    "@typescript-eslint/no-floating-promises": "error",
    "@typescript-eslint/no-misused-promises": "error",
    "@typescript-eslint/strict-boolean-expressions": "error",
    "no-console": ["warn", { "allow": ["error", "warn"] }]
  }
}

12. Agent 指令模板

当你作为 Agent 生成代码时,必须遵循以下流程:

markdown 复制代码
## Agent 代码生成指令

### 前置检查
1. 检查项目是否已存在相关功能,避免重复
2. 确认技术栈版本(React 18+, TypeScript 5+)
3. 检查是否有可用的 UI 组件库

### 代码生成步骤
1. **类型优先**:先定义 Props 和返回类型
2. **逻辑分离**:将业务逻辑提取到 Hooks
3. **组件实现**:使用函数组件 + forwardRef
4. **样式处理**:使用 Tailwind CSS + cn 工具函数
5. **错误处理**:添加 Error Boundary 和 loading 状态
6. **性能优化**:检查是否需要 memo/useMemo/useCallback
7. **导出配置**:添加 index.ts 统一导出

### 禁止事项
- ❌ 使用 any 类型
- ❌ 在组件内定义函数(除非使用 useCallback)
- ❌ 直接修改 state(必须使用不可变更新)
- ❌ 在 useEffect 中直接使用 async 函数
- ❌ 忽略 accessibility 属性
- ❌ 硬编码字符串(使用 i18n)
- ❌ 在 render 中执行副作用

### 必须包含
- [ ] TypeScript 严格类型
- [ ] JSDoc 注释
- [ ] 使用示例
- [ ] 错误处理
- [ ] 单元测试(复杂逻辑)
- [ ] Storybook 文档(UI 组件)

这套规范涵盖了现代 React + TypeScript 开发的核心最佳实践,可以作为 .cursorrules.claude-rules 或类似的 Agent 配置文件使用。

相关推荐
①条咸鱼2 小时前
React 项目运用 RxJS 设置节流
react.js
SuperEugene2 小时前
Vue3 表格封装实战:列配置 + slot 扩展 + 请求生命周期|Vue生态精选篇
前端·javascript·vue.js·前端框架
小鹿软件办公2 小时前
Firefox Nova:火狐浏览器即将迎来大规模改版
前端·firefox
Lee_Yu_Fan2 小时前
在vue3 + ElementUI 项目中自定义 Icon
前端·elementui
吴声子夜歌2 小时前
小程序——转发API
java·前端·小程序
小马_xiaoen2 小时前
后端动态路由 + RBAC 权限控制全实战(Vue3 + TS)
前端
Cobyte2 小时前
面试官:大模型是怎么调用工具的呢 ?
前端·后端·aigc
@大迁世界2 小时前
32.CSS魔术师 (CSS Houdini)
前端·css·人工智能·tensorflow·houdini