定义前端特定的架构细节:
src/
├── components/
│ ├── ui/ # 基础UI组件(可复用)
│ ├── forms/ # 表单组件
│ ├── layout/ # 布局组件
│ └── features/ # 功能组件
// components/ui/button/Button.tsx
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
size?: 'default' | 'sm' | 'lg' | 'icon';
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>(({ className, variant = 'default', size = 'default', ...props }, ref) => {
return (
<button
className={cn(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',
// ...样式类
)}
ref={ref}
{...props}
/>
);
});
// stores/auth-store.ts
export const useAuthStore = create<AuthState>((set, get) => ({
user: null,
token: localStorage.getItem('token'),
isLoading: false,
login: async (email: string, password: string) => {
set({ isLoading: true });
try {
const response = await apiClient.auth.login.$post({ json: { email, password } });
const { user, token } = await response.json();
localStorage.setItem('token', token);
set({ user, token, isLoading: false });
} catch (error) {
set({ isLoading: false });
throw error;
}
},
}));
// routes/index.tsx
export const router = createBrowserRouter([
{
path: '/auth',
element: <AuthLayout />,
children: [
{ path: 'login', element: <LoginPage /> },
],
},
{
path: '/',
element: <AppLayout />,
children: [
{ index: true, element: <DashboardPage /> },
{ path: 'users', element: <UsersPage /> },
],
},
]);
// components/auth/ProtectedRoute.tsx
export function ProtectedRoute({ children }: ProtectedRouteProps) {
const { user, isLoading, initialize } = useAuthStore();
const navigate = useNavigate();
useEffect(() => {
if (!isLoading && !user) {
navigate('/auth/login');
}
}, [user, isLoading, navigate]);
return user ? <>{children}</> : null;
}
// lib/api-client.ts
export const apiClient = hc<AppType>(import.meta.env.VITE_API_URL || 'http://localhost:8080');
// 请求拦截器 - 自动添加token
apiClient._fetch = async (input, init) => {
const token = localStorage.getItem('token');
const headers = new Headers(init?.headers);
if (token) {
headers.set('Authorization', `Bearer ${token}`);
}
return fetch(input, { ...init, headers });
};