# 平台数据列表页 API 错误修复

## 问题描述

平台数据列表页（`/analytics/platform`）在加载数据时出现 500 错误，错误信息显示：
```
Unexpected token '<', "<!doctype \"... is not valid JSON
```

这表明服务器返回的是 HTML 错误页面而不是预期的 JSON 数据。

## 问题原因

1. **Python API 服务未运行或连接失败**
   - Python 服务（默认端口 5005）可能未启动
   - 网络连接问题导致无法访问 Python 服务

2. **Node.js 端错误处理不完善**
   - `callPythonAnalyticsApi` 函数直接调用 `resp.json()`，没有检查响应状态和内容类型
   - 当 Python 服务返回 HTML 错误页面时，JSON 解析失败导致错误

3. **错误信息不明确**
   - 前端无法获取详细的错误信息，难以定位问题

## 修复方案

### 1. 改进 `callPythonAnalyticsApi` 函数

**文件**: `server/src/routes/analytics.ts`

**改进内容**:
- 添加响应状态检查（`resp.ok`）
- 检查 Content-Type，确保是 JSON 响应
- 添加详细的错误处理和错误信息
- 处理网络连接错误（连接失败、超时等）

**修复后的代码**:
```typescript
async function callPythonAnalyticsApi(pathname: string, params: Record<string, string | number | undefined>) {
  const base = process.env.PYTHON_API_URL || 'http://localhost:5005';
  const url = new URL(base);
  url.pathname = pathname.startsWith('/') ? pathname : `/${pathname}`;

  const search = new URLSearchParams();
  Object.entries(params).forEach(([key, value]) => {
    if (value !== undefined && value !== null) {
      search.append(key, String(value));
    }
  });
  url.search = search.toString();

  try {
    const resp = await fetch(url.toString(), { method: 'GET' });
    
    // 检查响应状态
    if (!resp.ok) {
      // 尝试解析 JSON 错误响应
      let errorData: any;
      try {
        errorData = await resp.json();
      } catch {
        // 如果不是 JSON，读取文本内容
        const text = await resp.text();
        errorData = {
          success: false,
          error: `Python API 返回错误 (${resp.status}): ${text.substring(0, 500)}`,
        };
      }
      throw new Error(errorData.error || `Python API 返回错误: ${resp.status} ${resp.statusText}`);
    }

    // 检查 Content-Type
    const contentType = resp.headers.get('content-type') || '';
    if (!contentType.includes('application/json')) {
      const text = await resp.text();
      throw new Error(`Python API 返回非 JSON 响应: ${text.substring(0, 500)}`);
    }

    const json = await resp.json();
    return json;
  } catch (error: any) {
    // 如果是网络错误（连接失败、超时等）
    if (error.name === 'TypeError' && error.message.includes('fetch')) {
      throw new Error(`无法连接 Python API (${base}): ${error.message}`);
    }
    // 其他错误直接抛出
    throw error;
  }
}
```

### 2. 改进路由错误处理

**文件**: `server/src/routes/analytics.ts`

**改进内容**:
- 添加 try-catch 块捕获所有错误
- 返回详细的错误信息给前端
- 使用正确的 HTTP 状态码（500）

**修复后的代码**:
```typescript
router.get(
  '/platforms-from-python',
  [
    query('startDate').notEmpty().withMessage('开始日期不能为空'),
    query('endDate').notEmpty().withMessage('结束日期不能为空'),
    validateRequest,
  ],
  asyncHandler(async (req, res) => {
    const { startDate, endDate } = req.query;

    try {
      const pythonResult = await callPythonAnalyticsApi('/work_day_statistics/platforms', {
        user_id: req.user!.userId,
        start_date: String(startDate),
        end_date: String(endDate),
      });

      if (!pythonResult || pythonResult.success === false) {
        return res.status(500).json({
          success: false,
          error: pythonResult?.error || '获取平台数据失败',
          message: pythonResult?.error || '获取平台数据失败',
        });
      }

      return res.json({
        success: true,
        data: pythonResult.data,
      });
    } catch (error: any) {
      // 捕获并返回详细的错误信息
      console.error('[platforms-from-python] 调用 Python API 失败:', error);
      return res.status(500).json({
        success: false,
        error: error.message || '调用 Python API 失败',
        message: error.message || '调用 Python API 失败',
      });
    }
  })
);
```

## 检查清单

如果问题仍然存在，请按以下步骤检查：

### 1. 检查 Python 服务是否运行

```bash
# 检查端口 5005 是否被占用
netstat -ano | findstr :5005  # Windows
lsof -i :5005                 # Linux/Mac

# 检查 Python 服务日志
# 查看 Python 服务控制台输出，确认服务是否正常启动
```

### 2. 检查环境变量

确保 Node.js 服务能正确访问 Python 服务：

```bash
# 检查环境变量
echo $PYTHON_API_URL  # Linux/Mac
echo %PYTHON_API_URL% # Windows

# 默认值应该是 http://localhost:5005
```

### 3. 手动测试 Python API

```bash
# 测试 Python API 健康检查
curl http://localhost:5005/health

# 测试平台统计接口（需要替换 user_id）
curl "http://localhost:5005/work_day_statistics/platforms?user_id=1&start_date=2026-01-27&end_date=2026-01-27"
```

### 4. 检查 Node.js 服务日志

查看 Node.js 服务的控制台输出，确认：
- 是否有连接错误
- 是否有超时错误
- 是否有其他异常信息

### 5. 检查网络连接

确保 Node.js 服务能够访问 Python 服务：
- 如果 Python 服务运行在不同的机器上，检查防火墙设置
- 如果使用 Docker，检查容器网络配置

## 常见错误及解决方案

### 错误 1: "无法连接 Python API"

**原因**: Python 服务未启动或无法访问

**解决方案**:
1. 启动 Python 服务：
   ```bash
   cd server/python
   python app.py
   ```

2. 检查 Python 服务是否在正确的端口运行（默认 5005）

3. 如果 Python 服务运行在不同的地址，设置环境变量：
   ```bash
   export PYTHON_API_URL=http://your-python-server:5005
   ```

### 错误 2: "Python API 返回错误 (500)"

**原因**: Python 服务内部错误

**解决方案**:
1. 查看 Python 服务日志，找出具体错误
2. 检查 Python 服务是否能正常连接数据库
3. 检查 Python 服务的依赖是否完整安装

### 错误 3: "Python API 返回非 JSON 响应"

**原因**: Python 服务返回了 HTML 错误页面

**解决方案**:
1. 检查 Python 服务的错误处理逻辑
2. 确保所有路由都返回 JSON 格式
3. 检查 Flask 的错误处理中间件

## 测试

修复后，请测试以下场景：

1. **正常情况**: Python 服务正常运行，数据正常返回
2. **Python 服务未启动**: 应该返回明确的错误信息
3. **Python 服务返回错误**: 应该返回详细的错误信息
4. **网络超时**: 应该返回超时错误信息

## 相关文件

- `server/src/routes/analytics.ts` - Node.js API 路由
- `server/python/app.py` - Python Flask 服务
- `client/src/views/Analytics/Platform/index.vue` - 前端页面

## 修复日期

2026-01-28
