# 数据分析报告生成应用

一个基于 React、TypeScript 和 Vite 的数据分析报告生成应用，用于导入 Excel 业务数据、渲染多页中文数据报告，并导出为 PDF 文件。项目包含前端报告页面、Excel 模板生成与解析、ECharts 数据可视化，以及基于 Puppeteer 的服务端 PDF 生成能力。

## 功能概览

- 多页中文数据报告展示
- Excel 模板下载与数据导入
- 区域地图、漏斗图、旭日图、柱状对比图等数据可视化
- 浏览器端报告预览
- 服务端 PDF 导出
- 默认演示数据兜底
- 支持局域网访问与 Vite API 代理

## 技术栈

- React 19
- TypeScript
- Vite
- Tailwind CSS
- ECharts
- xlsx
- html2pdf.js
- Express
- Puppeteer

## 项目结构

```text
.
├── src/
│   ├── App.tsx                  # 前端主应用入口，负责导入、预览和导出操作
│   ├── main.tsx                 # React 挂载入口
│   ├── components/              # 报告页面与图表组件
│   │   ├── CoverPage.tsx        # 封面页
│   │   ├── ContentPage.tsx      # 通用内容页容器
│   │   ├── Page02Industry.tsx   # 地区采集与地图页
│   │   ├── Page03Duration.tsx   # 采集时长与漏损页
│   │   ├── Page04Portrait.tsx   # 企业画像页
│   │   ├── Page05Risk.tsx       # 风险指标页
│   │   ├── Page06ExportTax.tsx  # 出口退税分布页
│   │   ├── Page07Association.tsx # 关联企业分布页
│   │   ├── BackCover.tsx        # 风险扫描与封底页
│   │   └── ChinaMap.tsx         # 中国地图组件
│   ├── data/
│   │   └── defaultData.ts       # 默认报告数据
│   ├── types/
│   │   └── data.ts              # 报告数据类型定义
│   ├── utils/
│   │   └── excelUtils.ts        # Excel 模板生成与导入解析
│   ├── assets/
│   │   ├── china.json           # 中国地图 GeoJSON
│   │   └── images/              # 报告使用的图片资源
│   ├── constants.ts             # 静态资源与报告常量
│   └── index.css                # 全局样式与打印样式
├── server/
│   ├── src/index.js             # PDF 生成服务
│   ├── package.json             # 服务端依赖
│   └── package-lock.json
├── public/                      # Vite 静态资源目录
├── tools/                       # 历史辅助工具页面
├── index.html                   # Vite HTML 入口
├── start.sh                     # 一键启动前端与 PDF 服务
├── vite.config.ts               # Vite 配置与 API 代理
├── tailwind.config.js           # Tailwind 配置
├── package.json                 # 前端依赖与脚本
└── README.md
```

## 环境要求

- Node.js 18 或更高版本
- npm
- 本地需允许 Puppeteer 启动 Chromium

## 安装依赖

安装前端依赖：

```bash
npm install
```

安装服务端依赖：

```bash
cd server
npm install
cd ..
```

## 启动项目

推荐使用一键启动脚本：

```bash
./start.sh
```

脚本会执行以下操作：

- 清理 `3002` 和 `5173` 端口上的旧进程
- 检查并安装前端依赖
- 检查并安装服务端依赖
- 启动 PDF 生成服务
- 启动 Vite 开发服务器

启动后访问：

```text
前端应用：http://localhost:5173
PDF 服务：http://localhost:3002
```

## 手动启动

启动 PDF 服务：

```bash
cd server
npm start
```

另开一个终端启动前端：

```bash
npm run dev
```

前端请求 `/api/generate-pdf` 会通过 Vite 代理转发到 `http://localhost:3002`。

## 数据导入流程

应用内点击“数据导入”后，可以下载标准 Excel 模板并上传填充后的文件。解析逻辑位于 `src/utils/excelUtils.ts`。

模板包含以下 Sheet：

| Sheet 名称 | 用途 |
| --- | --- |
| 基础信息 | 企业名称、核心指标、画像描述 |
| 地图展示 | 省份采集数据 |
| 地区统计 | 地区采集数量、转换率、成功率、采集时长 |
| 时长分布 | 各地区采集时长区间分布 |
| 页面漏损 | 采集流程漏斗数据 |
| 企业全景洞察 | 全量客户行业画像 |
| 劣质客户洞察 | 风险客户行业画像 |
| 优质客户洞察 | 优质客户行业画像 |
| 风险占比 | 发票风险、高新技术、进出口、预缴税款指标 |
| 出口退税分布 | 出口免抵退税与出口退税金额分布 |
| 关联企业分布 | 登录人和法定代表人关联企业数量分布 |
| 风险扫描分布 | 企业风险扫描结果分布 |
| 图表描述 | 图表说明文案 |

导入失败时，优先检查：

- Sheet 名称是否被修改
- 表头是否与模板一致
- 百分比字段是否使用模板格式
- 指标类型字段是否保留原值

## PDF 导出流程

当前主流程使用服务端导出：

1. 前端点击“导出 PDF”
2. 前端将当前 `reportData` POST 到 `/api/generate-pdf`
3. Vite 代理转发到 `server/src/index.js`
4. Puppeteer 打开前端页面并追加 `?print=true`
5. 前端通过 `window.loadServerData` 接收服务端注入的数据
6. 前端等待图表渲染完成并设置 `window.isReportReady = true`
7. Puppeteer 调用 `page.pdf()` 生成 PDF 并返回给浏览器下载

## 常用命令

```bash
npm run dev
```

启动 Vite 开发服务器。

```bash
npm run build
```

执行 TypeScript 编译检查并构建生产产物。

```bash
npm run preview
```

预览生产构建结果。

```bash
npm run lint
```

运行 ESLint。

```bash
npx tsc --noEmit
```

只执行 TypeScript 类型检查。

```bash
cd server && npm start
```

启动 PDF 生成服务。

## 开发说明

- 主入口是 `src/App.tsx`，不是 `src/App-fixed.tsx`
- 报告数据的完整结构定义在 `src/types/data.ts`
- 默认数据在 `src/data/defaultData.ts`
- Excel 导入和模板生成逻辑集中在 `src/utils/excelUtils.ts`
- PDF 服务依赖前端页面的 `window.loadServerData` 和 `window.isReportReady`
- 打印与 PDF 相关样式主要在 `src/index.css`
- 报告图片资源通过 `src/constants.ts` 统一导出


## 常见问题

### 点击导出 PDF 失败

确认 PDF 服务已启动：

```bash
curl http://localhost:3002
```

如果服务未启动，执行：

```bash
cd server
npm start
```

### Excel 上传后数据没有变化

确认使用的是应用内下载的模板，并检查 Sheet 名称和表头是否被修改。

### 局域网无法访问

确认防火墙允许访问 `5173` 和 `3002` 端口。Vite 已配置 `host: '0.0.0.0'`，服务端也监听 `0.0.0.0`。

### PDF 中图表显示异常

服务端导出会等待 `window.isReportReady`。如果新增图表，请确保数据变化后有足够的渲染等待时间，且图表容器尺寸稳定。
