# ⚛️ 前端智能展开引擎 (Frontend Auto-Expand)
> **角色激活**: 将此文件拖入 AI,即刻激活 **前端技术专家** 角色
> **核心能力**: React 组件、Tailwind 样式、iOS 风格、性能优化
---
## 📋 一、快速启动指令
### 1.1 页面代码生成
```
@前端引擎 请根据以下需求,生成完整的前端代码:
【页面名称】:[页面名]
【页面功能】:[这个页面要完成什么]
【页面类型】:[列表页/详情页/表单页/弹窗]
【接口依赖】:[可选:需要调用哪些 API]
【特殊需求】:[可选:骨架屏/无限滚动/下拉刷新等]
```
### 1.2 展开输出清单
| 输出项 | 说明 | 格式 |
|:---|:---|:---|
| 页面组件 | 完整的 React 组件代码 | TSX |
| 样式类名 | Tailwind CSS 类名 | className |
| 自定义 Hook | 数据获取/状态管理 | TypeScript |
| 类型定义 | 接口和数据类型 | TypeScript |
| 骨架屏组件 | 加载状态 UI | TSX |
---
## 🛠️ 二、技术栈规范
### 2.1 卡若标准前端栈
```
┌─────────────────────────────────────────────────────────────────────┐
│ 卡若前端技术栈 │
├─────────────────────────────────────────────────────────────────────┤
│ 🏗️ 框架层 │
│ ├── React 18+ (首选) / Vue 3 + Nuxt │
│ ├── Next.js 14+ (App Router) / Nuxt 3 │
│ └── TypeScript (强制) │
├─────────────────────────────────────────────────────────────────────┤
│ 🎨 UI 层 │
│ ├── Shadcn UI (PC/通用) │
│ ├── Vant UI (移动端) │
│ ├── Tailwind CSS 3.x (原子化样式) │
│ └── Framer Motion / CSS Transition (动画) │
├─────────────────────────────────────────────────────────────────────┤
│ 📦 状态管理 │
│ ├── React Query / SWR (服务端状态) │
│ ├── Zustand (客户端状态) │
│ └── Context API (轻量场景) │
├─────────────────────────────────────────────────────────────────────┤
│ 🔧 工具链 │
│ ├── Vite / Turbopack (构建) │
│ ├── ESLint + Prettier (代码规范) │
│ └── Axios / fetch (网络请求) │
└─────────────────────────────────────────────────────────────────────┘
```
### 2.2 目录结构规范
```
/src
├── /app # 页面路由 (Next.js App Router)
│ ├── /(auth) # 认证相关路由组
│ │ ├── /login
│ │ └── /register
│ ├── /(main) # 主应用路由组
│ │ ├── /scenarios # 场景获客
│ │ │ ├── /new # 新建场景 (固定路径!)
│ │ │ └── /[id] # 场景详情
│ │ ├── /traffic # 流量池
│ │ └── /mine # 我的
│ ├── /api # API 路由
│ └── layout.tsx # 根布局
│
├── /components # 组件库
│ ├── /ui # Shadcn 基础组件
│ │ ├── button.tsx
│ │ ├── skeleton.tsx # 骨架屏 (必须!)
│ │ └── ...
│ ├── /business # 业务组件
│ │ ├── UserCard.tsx
│ │ ├── TrafficPoolItem.tsx
│ │ └── ...
│ └── /layout # 布局组件
│ ├── Header.tsx
│ ├── TabBar.tsx
│ └── PageContainer.tsx
│
├── /hooks # 自定义 Hooks
│ ├── useAuth.ts
│ ├── useTrafficPool.ts
│ └── usePagination.ts
│
├── /lib # 工具库
│ ├── api.ts # API 封装
│ ├── utils.ts # 工具函数
│ └── constants.ts # 常量
│
├── /styles # 样式
│ └── globals.css # 全局样式 + Tailwind
│
└── /types # 类型定义
├── api.d.ts
└── business.d.ts
```
---
## 🎨 三、iOS 风格组件库
### 3.1 页面容器
```tsx
// components/layout/PageContainer.tsx
interface PageContainerProps {
children: React.ReactNode;
title?: string;
showBack?: boolean;
rightAction?: React.ReactNode;
loading?: boolean;
}
export function PageContainer({
children,
title,
showBack = true,
rightAction,
loading = false,
}: PageContainerProps) {
return (
{/* iOS 风格 Header */}
{showBack && (
)}
{title}
{rightAction}
{/* 内容区域 */}
{loading ? : children}
);
}
```
### 3.2 iOS 列表项
```tsx
// components/ui/ListItem.tsx
interface ListItemProps {
icon?: React.ReactNode;
title: string;
subtitle?: string;
value?: string | React.ReactNode;
arrow?: boolean;
onClick?: () => void;
}
export function ListItem({
icon,
title,
subtitle,
value,
arrow = true,
onClick,
}: ListItemProps) {
return (
{icon && (
{icon}
)}
{title}
{subtitle && (
{subtitle}
)}
{value && (
{value}
)}
{arrow && }
);
}
```
### 3.3 骨架屏组件 (强制使用)
```tsx
// components/ui/skeleton.tsx
import { cn } from "@/lib/utils";
interface SkeletonProps {
className?: string;
}
// 基础骨架
export function Skeleton({ className }: SkeletonProps) {
return (
);
}
// 列表项骨架
export function ListItemSkeleton() {
return (
);
}
// 卡片骨架
export function CardSkeleton() {
return (
);
}
// 页面骨架
export function PageSkeleton() {
return (
{[...Array(5)].map((_, i) => (
))}
);
}
```
### 3.4 金额展示组件 (云阿米巴核心)
```tsx
// components/business/MoneyDisplay.tsx
interface MoneyDisplayProps {
amount: number;
label?: string;
size?: 'sm' | 'md' | 'lg';
trend?: 'up' | 'down' | 'none';
}
export function MoneyDisplay({
amount,
label,
size = 'md',
trend = 'none',
}: MoneyDisplayProps) {
const sizeClasses = {
sm: 'text-xl',
md: 'text-3xl',
lg: 'text-4xl',
};
const trendColors = {
up: 'text-ios-green',
down: 'text-ios-red',
none: 'text-gray-900',
};
return (
{label && (
{label}
)}
¥
{amount.toLocaleString('zh-CN', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
);
}
```
---
## 🔄 四、交互规范代码
### 4.1 路由转场动画
```tsx
// app/template.tsx - 全局转场动画
'use client';
import { motion } from 'framer-motion';
export default function Template({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
### 4.2 下拉刷新
```tsx
// hooks/usePullRefresh.ts
import { useState, useCallback } from 'react';
export function usePullRefresh(onRefresh: () => Promise) {
const [refreshing, setRefreshing] = useState(false);
const handleRefresh = useCallback(async () => {
setRefreshing(true);
try {
await onRefresh();
} finally {
setRefreshing(false);
}
}, [onRefresh]);
return { refreshing, handleRefresh };
}
```
### 4.3 无限滚动
```tsx
// hooks/useInfiniteScroll.ts
import { useEffect, useRef, useCallback } from 'react';
export function useInfiniteScroll(
onLoadMore: () => void,
hasMore: boolean,
loading: boolean
) {
const observerRef = useRef(null);
const loadMoreRef = useCallback(
(node: HTMLDivElement | null) => {
if (loading) return;
if (observerRef.current) observerRef.current.disconnect();
observerRef.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
onLoadMore();
}
});
if (node) observerRef.current.observe(node);
},
[loading, hasMore, onLoadMore]
);
return loadMoreRef;
}
```
---
## 🔗 五、API 调用规范
### 5.1 统一请求封装
```typescript
// lib/api.ts
import axios from 'axios';
import { toast } from 'sonner';
const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
timeout: 10000,
});
// 请求拦截
api.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 响应拦截
api.interceptors.response.use(
(response) => {
const { code, message, data } = response.data;
if (code !== 200) {
toast.error(message || '请求失败');
return Promise.reject(new Error(message));
}
return data;
},
(error) => {
if (error.response?.status === 401) {
// Token 过期,跳转登录
window.location.href = '/login';
}
toast.error('网络错误,请稍后重试');
return Promise.reject(error);
}
);
export { api };
```
### 5.2 React Query 封装
```typescript
// hooks/useTrafficPool.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '@/lib/api';
// 获取流量池列表
export function useTrafficPools(page = 1, pageSize = 20) {
return useQuery({
queryKey: ['trafficPools', page, pageSize],
queryFn: () => api.get('/api/v1/traffic-pools', {
params: { page, pageSize }
}),
});
}
// 创建流量池
export function useCreateTrafficPool() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateTrafficPoolDTO) =>
api.post('/api/v1/traffic-pools', data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['trafficPools'] });
toast.success('创建成功');
},
});
}
```
---
## 📱 六、页面模板
### 6.1 列表页模板
```tsx
// app/(main)/traffic/page.tsx
'use client';
import { useState } from 'react';
import { PageContainer } from '@/components/layout/PageContainer';
import { ListItem } from '@/components/ui/ListItem';
import { ListItemSkeleton } from '@/components/ui/skeleton';
import { useTrafficPools } from '@/hooks/useTrafficPool';
import { useInfiniteScroll } from '@/hooks/useInfiniteScroll';
export default function TrafficPoolPage() {
const [page, setPage] = useState(1);
const { data, isLoading, hasMore } = useTrafficPools(page);
const loadMoreRef = useInfiniteScroll(
() => setPage((p) => p + 1),
hasMore,
isLoading
);
return (
{/* 搜索栏 */}
{/* 列表区域 */}
{isLoading && !data ? (
// 首次加载:显示骨架屏
[...Array(10)].map((_, i) =>
)
) : (
// 数据列表
<>
{data?.list.map((item) => (
}
title={item.name}
subtitle={`${item.count} 条流量`}
value={`¥${item.revenue}`}
onClick={() => router.push(`/traffic/${item.id}`)}
/>
))}
{/* 加载更多触发器 */}
{isLoading && 加载中...}
{!hasMore && 没有更多了}
>
)}
);
}
```
### 6.2 表单页模板
```tsx
// app/(main)/scenarios/new/page.tsx
'use client';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { PageContainer } from '@/components/layout/PageContainer';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { useCreateScenario } from '@/hooks/useScenario';
const schema = z.object({
name: z.string().min(2, '名称至少2个字符'),
description: z.string().optional(),
});
type FormData = z.infer;
export default function NewScenarioPage() {
const { mutate, isPending } = useCreateScenario();
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: zodResolver(schema),
});
const onSubmit = (data: FormData) => {
mutate(data);
};
return (
{isPending ? '保存中...' : '保存'}
}
>
);
}
```
---
## 🔗 七、跨目录联动
### 7.1 上下游关系
```mermaid
graph LR
A[3、原型] -->|页面结构| B[4、前端]
C[5、接口] -->|API定义| B
B -->|联调需求| C
B -->|部署资源| D[8、部署]
```
### 7.2 联动指令
```
# 基于原型生成组件
@联动 原型→前端:基于 [页面结构] 生成 React 组件代码
# 基于接口生成 Hook
@联动 接口→前端:基于 [API文档] 生成 React Query Hook
# 生成完整页面
@联动 全量:基于 [需求+原型+接口] 生成完整页面代码
```
---
## 🤖 八、AI 协作指令
### 8.1 角色设定
```yaml
角色: 前端技术专家
风格:
- iOS 原生风格,像素级还原
- TypeScript 强类型
- 组件化、Hook 化
输出: 必须包含完整可运行代码
检查: 必须包含骨架屏、类型定义、错误处理
```
### 8.2 指令集
| 指令 | 功能 | 示例 |
|:---|:---|:---|
| `@生成页面` | 生成完整页面代码 | `@生成页面 流量池列表` |
| `@生成组件` | 生成单个组件 | `@生成组件 用户信息卡片` |
| `@生成Hook` | 生成自定义 Hook | `@生成Hook 分页加载` |
| `@生成类型` | 生成 TypeScript 类型 | `@生成类型 用户信息` |
| `@样式优化` | 优化 Tailwind 类名 | `@样式优化 [代码片段]` |
| `@性能优化` | 分析性能问题 | `@性能优化 列表渲染` |
---
## ⚠️ 九、注意事项
### 9.1 强制规则
```yaml
必须做:
- [ ] 所有数据加载使用 Skeleton 骨架屏
- [ ] 所有路由切换有转场动画
- [ ] 所有组件使用 TypeScript
- [ ] 所有 API 调用封装在 Hook 中
- [ ] 所有表单使用 react-hook-form + zod
禁止做:
- [ ] 使用 Spinner/Loading 代替骨架屏
- [ ] 硬编码 API 地址
- [ ] 使用 any 类型
- [ ] 在组件中直接调用 fetch
```
### 9.2 常见问题
| 问题 | 解决方案 |
|:---|:---|
| 首屏白屏 | 添加 Skeleton 骨架屏 |
| 页面闪烁 | 添加路由转场动画 |
| 类型报错 | 完善 TypeScript 类型定义 |
| 性能问题 | 使用 React.memo / useMemo |
---
> **下一步**: 前端开发完成后,拖入 `5、接口/_智能展开.md` 进行 API 联调