# 前端常见问题与解决方案

> 本文档记录前端开发过程中遇到的常见问题及其解决方案，供 AI 和开发者参考。

---

## 目录

1. [白屏问题](#1-白屏问题)
2. [图标问题](#2-图标问题)
3. [路由配置问题](#3-路由配置问题)
4. [组件导出问题](#4-组件导出问题)
5. [编码问题](#5-编码问题)
6. [Ant Design 弃用警告](#6-ant-design-弃用警告)

---

## 1. 白屏问题

### 1.1 症状
- 页面加载后显示空白
- 浏览器控制台显示 `net::ERR_ABORTED` 错误
- 页面无法正常渲染

### 1.2 常见原因

#### 原因 1：路由未定义
**问题**：布局文件中的菜单链接指向未在 `.umirc.ts` 中定义的路由。

**解决方案**：
在 `.umirc.ts` 中添加缺失的路由配置：

```typescript
routes: [
  // 确保所有菜单链接都有对应的路由
  {
    path: '/dashboard/ai-suggestion',
    component: '@/pages/AISuggestionPage',
  },
  // ... 其他路由
],
```

#### 原因 2：组件导入错误
**问题**：组件文件使用了错误的导出方式，导致导入失败。

**解决方案**：
确保组件使用正确的导出方式：

```typescript
// ❌ 错误：同时使用 export const 和 export default
export const MyComponent: React.FC = () => { ... };
export default MyComponent;

// ✅ 正确：只使用 export default
const MyComponent: React.FC = () => { ... };
export default MyComponent;
```

#### 原因 3：图标不存在
**问题**：使用了 `@ant-design/icons` 中不存在的图标。

**解决方案**：
替换为存在的图标：

```typescript
// ❌ 错误：BrainOutlined 不存在
import { BrainOutlined } from '@ant-design/icons';

// ✅ 正确：使用 RobotOutlined
import { RobotOutlined } from '@ant-design/icons';
```

---

## 2. 图标问题

### 2.1 症状
- 页面白屏
- 控制台显示 `Element type is invalid` 错误
- 图标无法显示

### 2.2 常见问题图标

| 问题图标 | 替代图标 | 说明 |
|---------|---------|------|
| `BrainOutlined` | `RobotOutlined` | AI 相关功能 |
| `MindOutlined` | `BulbOutlined` | 思维/想法相关 |

### 2.3 批量替换命令

```powershell
# 搜索所有使用 BrainOutlined 的文件
Get-ChildItem -Path "src" -Recurse -Filter "*.tsx" | Select-String -Pattern "BrainOutlined"

# 批量替换（注意：必须使用 UTF-8 编码）
Get-ChildItem -Path "src" -Recurse -Filter "*.tsx" | ForEach-Object { 
  $content = [System.IO.File]::ReadAllText($_.FullName, [System.Text.Encoding]::UTF8)
  if ($content -match 'BrainOutlined') {
    $newContent = $content -replace 'BrainOutlined', 'RobotOutlined'
    [System.IO.File]::WriteAllText($_.FullName, $newContent, [System.Text.Encoding]::UTF8)
    Write-Host "Fixed: $($_.Name)"
  }
}
```

---

## 3. 路由配置问题

### 3.1 症状
- 访问页面返回 404
- 页面白屏，显示 `net::ERR_ABORTED`
- 菜单链接无法跳转

### 3.2 路由配置规范

```typescript
// .umirc.ts
export default defineConfig({
  routes: [
    // 根路由
    {
      path: '/',
      component: '@/pages/Homepage',
    },
    // Dashboard 路由
    {
      path: '/dashboard',
      component: '@/pages/DashboardPage',
    },
    // 子路由（必须完整定义）
    {
      path: '/dashboard/ai-suggestion',
      component: '@/pages/AISuggestionPage',
    },
    // ... 其他路由
  ],
});
```

### 3.3 路由与组件对应关系

| 路由路径 | 组件文件 | 说明 |
|---------|---------|------|
| `/dashboard/ai-suggestion` | `AISuggestionPage.tsx` | AI 建议页面 |
| `/dashboard/human-approval` | `HumanApprovalPage.tsx` | 人工审批页面 |
| `/dashboard/execution-results` | `ExecutionResults.tsx` | 执行结果页面 |
| `/dashboard/client-management` | `ClientManagement.tsx` | 客户管理页面 |

---

## 4. 组件导出问题

### 4.1 症状
- 页面白屏
- 控制台显示 `Element type is invalid` 错误
- 组件无法正常渲染

### 4.2 正确的导出方式

```typescript
// ❌ 错误：同时使用 export const 和 export default
export const MyComponent: React.FC = () => {
  return <div>My Component</div>;
};
export default MyComponent;

// ✅ 正确：只使用 export default
const MyComponent: React.FC = () => {
  return <div>My Component</div>;
};
export default MyComponent;

// ✅ 正确：命名导出（用于工具函数）
export const helperFunction = () => {
  return 'helper';
};
```

### 4.3 批量修复命令

```powershell
# 修复所有使用 export const 的组件文件
Get-ChildItem -Path "src\pages" -Recurse -Filter "*.tsx" | ForEach-Object { 
  $content = [System.IO.File]::ReadAllText($_.FullName, [System.Text.Encoding]::UTF8)
  if ($content -match 'export const (\w+): React\.FC') {
    $newContent = $content -replace 'export const (\w+): React\.FC', 'const $1: React.FC'
    [System.IO.File]::WriteAllText($_.FullName, $newContent, [System.Text.Encoding]::UTF8)
    Write-Host "Fixed: $($_.Name)"
  }
}
```

---

## 5. 编码问题

### 5.1 症状
- 中文字符显示为乱码
- 编译错误：`Unterminated string literal`
- 文件内容损坏

### 5.2 原因
PowerShell 的 `Set-Content` 命令默认使用系统编码（通常是 GBK），而不是 UTF-8。

### 5.3 正确的文件读写方式

```powershell
# ❌ 错误：使用 Set-Content（会损坏中文）
$content = Get-Content $_.FullName -Raw
Set-Content -Path $_.FullName -Value $newContent

# ✅ 正确：使用 .NET API 并指定 UTF-8 编码
$content = [System.IO.File]::ReadAllText($_.FullName, [System.Text.Encoding]::UTF8)
[System.IO.File]::WriteAllText($_.FullName, $newContent, [System.Text.Encoding]::UTF8)
```

### 5.4 恢复损坏的文件

```bash
# 使用 Git 恢复文件
git checkout -- src/pages
```

---

## 6. Ant Design 弃用警告

### 6.1 Drawer visible 弃用

**警告信息**：
```
Warning: [antd: Drawer] `visible` is deprecated. Please use `open` instead.
```

**解决方案**：
```typescript
// ❌ 旧写法
<Drawer visible={visible} onClose={onClose}>
  Content
</Drawer>

// ✅ 新写法
<Drawer open={visible} onClose={onClose}>
  Content
</Drawer>
```

**批量修复命令**：
```powershell
Get-ChildItem -Path "src" -Recurse -Filter "*.tsx" | ForEach-Object { 
  $content = [System.IO.File]::ReadAllText($_.FullName, [System.Text.Encoding]::UTF8)
  if ($content -match 'visible=\{') {
    $newContent = $content -replace 'visible=\{', 'open={'
    [System.IO.File]::WriteAllText($_.FullName, $newContent, [System.Text.Encoding]::UTF8)
    Write-Host "Fixed: $($_.Name)"
  }
}
```

### 6.2 Dropdown overlay 弃用

**警告信息**：
```
Warning: [antd: Dropdown] `overlay` is deprecated. Please use `menu` instead.
```

**解决方案**：
```typescript
// ❌ 旧写法
<Dropdown overlay={<Menu>...</Menu>}>
  <Button>Menu</Button>
</Dropdown>

// ✅ 新写法
<Dropdown menu={{ items: [...] }}>
  <Button>Menu</Button>
</Dropdown>
```

### 6.2 Tabs.TabPane 弃用

**警告信息**：
```
Warning: [antd: Tabs] `Tabs.TabPane` is deprecated. Please use `items` instead.
```

**解决方案**：
```typescript
// ❌ 旧写法
<Tabs>
  <Tabs.TabPane tab="Tab 1" key="1">Content 1</Tabs.TabPane>
  <Tabs.TabPane tab="Tab 2" key="2">Content 2</Tabs.TabPane>
</Tabs>

// ✅ 新写法
<Tabs 
  items={[
    { label: 'Tab 1', key: '1', children: 'Content 1' },
    { label: 'Tab 2', key: '2', children: 'Content 2' },
  ]}
/>
```

### 6.3 Form.Item defaultValue 警告

**警告信息**：
```
Warning: [antd: Form.Item] `defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.
```

**解决方案**：
```typescript
// ❌ 错误：在 Form.Item 中使用 defaultValue
<Form.Item name="field" defaultValue="value">
  <Input />
</Form.Item>

// ✅ 正确：在 Form 中使用 initialValues
<Form initialValues={{ field: 'value' }}>
  <Form.Item name="field">
    <Input />
  </Form.Item>
</Form>
```

---

## 7. React Hooks 错误

### 7.1 Invalid hook call

**错误信息**：
```
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component.
```

**常见原因**：
1. React 版本不匹配
2. 违反 Hooks 使用规则
3. 同一个应用中有多个 React 副本

### 7.2 图表库冲突

**问题**：同时使用 `@ant-design/plots` 和 `@ant-design/charts` 会导致 React Hooks 错误。

**解决方案**：
统一使用 `@ant-design/charts`：

```powershell
# 批量替换
Get-ChildItem -Path "src" -Recurse -Filter "*.tsx" | ForEach-Object { 
  $content = [System.IO.File]::ReadAllText($_.FullName, [System.Text.Encoding]::UTF8)
  if ($content -match '@ant-design/plots') {
    $newContent = $content -replace '@ant-design/plots', '@ant-design/charts'
    [System.IO.File]::WriteAllText($_.FullName, $newContent, [System.Text.Encoding]::UTF8)
    Write-Host "Fixed: $($_.Name)"
  }
}
```

### 7.3 图表组件内部警告

**警告信息**：
```
Warning: The tag <%s> is unrecognized in this browser.
ExpressionError: Unexpected character: }
```

**原因**：这是 `@ant-design/charts` 库内部渲染 SVG 元素时产生的警告，不影响页面功能。

**状态**：无需修复，这是库的内部行为。如果警告过多影响开发，可以考虑：
1. 升级 `@ant-design/charts` 到最新版本
2. 或者使用其他图表库（如 `recharts`、`echarts`）

### 7.4 懒加载组件问题

**错误信息**：
```
Warning: lazy: Expected the result of a dynamic import() call.
Error: Element type is invalid. Received a promise that resolves to: undefined.
```

**原因**：
1. Umi 框架的 MFSU（Module Federation Speed Up）特性与某些组件不兼容
2. 组件导出方式不正确
3. 组件文件路径错误

**解决方案**：

1. **检查组件导出方式**：
```typescript
// ❌ 错误：没有默认导出
export const MyComponent = () => { ... };

// ✅ 正确：使用默认导出
const MyComponent: React.FC = () => { ... };
export default MyComponent;
```

2. **检查路由配置**：
```typescript
// .umirc.ts
{
  path: '/dashboard/inventory',
  component: '@/pages/Inventory/index',  // 确保路径正确
}
```

3. **清除缓存并重启**：
```bash
# 清除 Umi 缓存
rm -rf .umi node_modules/.cache

# 重启开发服务器
npm run dev
```

4. **禁用 MFSU（临时方案）**：
```typescript
// .umirc.ts
export default defineConfig({
  mfsu: false,
  // ... 其他配置
});
```

---

## 8. 快速排查清单

当遇到白屏问题时，按以下顺序排查：

1. **检查浏览器控制台**
   - 是否有 JavaScript 错误？
   - 是否有网络请求失败？

2. **检查路由配置**
   - 路由是否在 `.umirc.ts` 中定义？
   - 组件路径是否正确？

3. **检查组件导出**
   - 是否同时使用了 `export const` 和 `export default`？
   - 导入语句是否正确？

4. **检查图标使用**
   - 是否使用了不存在的图标？
   - 图标是否从 `@ant-design/icons` 正确导入？

5. **检查文件编码**
   - 文件是否使用 UTF-8 编码？
   - 中文字符是否正常显示？

---

## 9. DataSource 抽象层规范

### 9.1 为什么需要 DataSource 抽象层

**问题**：直接在组件中硬编码 mock 数据会导致：
1. AI 上下文污染 - AI 无法区分真实业务逻辑和 mock 数据
2. 维护困难 - 数据分散在各个组件中，难以统一管理
3. 切换困难 - 从 mock 切换到真实 API 需要大量修改

**解决方案**：使用 DataSource 抽象层

### 9.2 正确的数据获取方式

```typescript
// ❌ 错误：硬编码 mock 数据
const MyComponent: React.FC = () => {
  const mockData = [
    { id: 1, name: '商品1' },
    { id: 2, name: '商品2' },
  ];
  // ...
};

// ✅ 正确：使用 DataSource 抽象层
import { productDataSource } from '@/services/productDataSource';

const MyComponent: React.FC = () => {
  const [products, setProducts] = useState([]);
  
  useEffect(() => {
    productDataSource.list().then(data => setProducts(data));
  }, []);
  // ...
};
```

### 9.3 DataSource 文件规范

**位置**：`src/services/*DataSource.ts`

**命名**：`[模块名]DataSource.ts`

**标记**：所有 mock 实现必须包含标记：
```typescript
/**
 * [MOCK-XXX] 模块名DataSource
 * AI注意: 这是Mock实现，不是真实业务逻辑
 * 仅在USE_MOCK=true时启用
 */
```

### 9.4 现有 DataSource 列表

| 模块 | DataSource 文件 | 状态 |
|------|----------------|------|
| 商品 | productDataSource.ts | ✅ 已实现 |
| 订单 | orderDataSource.ts | ✅ 已实现 |
| 库存 | inventoryDataSource.ts | ✅ 已实现 |
| 财务 | financeDataSource.ts | ✅ 已实现 |
| 分析 | analyticsDataSource.ts | ✅ 已实现 |
| 物流 | logisticsDataSource.ts | ✅ 已实现 |
| 供应商 | suppliersDataSource.ts | ✅ 已实现 |
| 用户 | userDataSource.ts | ✅ 已实现 |
| 设置 | settingsDataSource.ts | ✅ 已实现 |
| 广告 | adOptimizationDataSource.ts | ✅ 已实现 |

### 9.5 待改进的页面（使用硬编码 mock 数据）

以下 35 个页面使用了硬编码 mock 数据，需要迁移到 DataSource 抽象层：

| 页面 | 文件路径 |
|------|---------|
| AI 决策日志 | `AIDecisionLog/index.tsx` |
| 订单管理 | `Orders/index.tsx` |
| 异常订单 | `Orders/ExceptionOrder.tsx` |
| 任务中心 | `TaskCenter/index.tsx` |
| 报表 | `Reports/index.tsx` |
| 执行结果 | `ExecutionResults.tsx` |
| 人工审批 | `HumanApprovalPage.tsx` |
| AI 任务管理 | `AIActionTaskManager.tsx` |
| 运营代理增强 | `OperationAgentEnhanced.tsx` |
| B2B 批量订单 | `B2B/BatchOrder.tsx` |
| B2B 合同管理 | `B2B/ContractManage.tsx` |
| B2B 企业报价 | `B2BTrade/EnterpriseQuote.tsx` |
| B2B 贸易合同 | `B2BTrade/ContractManage.tsx` |
| 售后退款 | `AfterSales/RefundProcess.tsx` |
| 客户服务 | `AfterSales/CustomerService.tsx` |
| 平台账户配置 | `Settings/PlatformAccountConfig.tsx` |
| 系统设置 | `Settings/SystemSettings.tsx` |
| 用户管理 | `Settings/UserManagement.tsx` |
| 成本模板配置 | `Settings/CostTemplateConfig.tsx` |
| Win 节点配置 | `Settings/WinNodeConfig.tsx` |
| 汇率配置 | `Settings/ExchangeRateConfig.tsx` |
| 供应商详情 | `Suppliers/SupplierDetail.tsx` |
| 域名管理 | `IndependentSite/DomainManagement.tsx` |
| 独立站订单 | `IndependentSite/IndependentSiteOrder.tsx` |
| 竞品分析 | `Marketing/Competitors.tsx` |
| 广告自动调整 | `Ad/AutoAdjustment/index.tsx` |
| AI 优化 | `Ad/AIOptimization/index.tsx` |
| 广告效果 | `Ad/Performance/index.tsx` |
| AI 定价 | `Product/AIPricing/index.tsx` |
| ROI 分析 | `Product/ROIAnalysis/index.tsx` |
| 利润监控 | `Product/ProfitMonitor/index.tsx` |
| 利润报表 | `Reports/ProfitReport.tsx` |
| 绩效报表 | `Reports/PerformanceReport.tsx` |
| 库存预测 | `Inventory/InventoryForecast.tsx` |
| 批量上架 | `OperationAgent/components/ProductBatch/BatchListingModal.tsx` |

---

## 10. 相关文档

- [TypeScript 编译规约](./13_TypeScript_Standards.md)
- [代码质量规范](./14_Code_Quality_Standards.md)
- [前端开发指南](../03_Frontend/02_Development_Guide.md)
- [Mock 架构设计](./11_Mock_Architecture.md)

---

*最后更新：2026-03-26*
