import React, { useState } from 'react'; import { PageContainer } from '@ant-design/pro-components'; import { InboxOutlined, FileExcelOutlined, BarChartOutlined, FileWordOutlined } from '@ant-design/icons'; import { Upload, Card, Button, Steps, message, Input, Spin, Result, Progress, Alert, Typography } from 'antd'; import type { UploadFile } from 'antd/es/upload/interface'; import { marked } from 'marked'; import styles from './index.less'; import { Document, Packer, Paragraph as DocxParagraph, TextRun } from 'docx'; import { saveAs } from 'file-saver'; import * as XLSX from 'xlsx'; import useAIRequest from '@/hooks/useAIRequest'; const { Dragger } = Upload; const { TextArea } = Input; const { Title, Paragraph } = Typography; interface AnalysisResponse { id: string; choices: { message: { content: string; }; }[]; } interface ReportSection { title: string; content: string; } interface ReportData { title: string; summary: string; sections: ReportSection[]; charts: any[]; markdown: string; } const ReportPage: React.FC = () => { const [fileList, setFileList] = useState([]); const [currentStep, setCurrentStep] = useState(0); const [loading, setLoading] = useState(false); const [goal, setGoal] = useState(''); const [reportData, setReportData] = useState(null); const [wordUrl, setWordUrl] = useState(''); const [progress, setProgress] = useState(0); const [previewData, setPreviewData] = useState(null); const handleUpload = async (file: File) => { setLoading(true); try { const isImage = file.type.startsWith('image/'); const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type === 'application/vnd.ms-excel'; const isCsv = file.type === 'text/csv'; if (isImage) { // 处理图片文件 const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = async () => { const base64Image = reader.result as string; await analyzeData({ type: 'image_url', image_url: { url: base64Image } }); }; } else if (isExcel || isCsv) { // 处理 Excel/CSV 文件 const reader = new FileReader(); reader.onload = async (e) => { const data = e.target?.result; const workbook = XLSX.read(data, { type: 'array' }); const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; const jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); // 将数据转换为字符串 const textContent = jsonData.map(row => row.join('\t')).join('\n'); await analyzeData({ type: 'text', text: textContent }); }; reader.readAsArrayBuffer(file); } else { message.error('不支持的文件格式'); setLoading(false); } } catch (error) { message.error('文件处理失败'); console.error('文件处理失败:', error); setLoading(false); } }; const { loading: aiLoading, sendRequest } = useAIRequest(); const analyzeData = async (content: any) => { setLoading(true); try { const result = await sendRequest([ { type: 'text', text: '请分析这些数据的趋势和关键信息,并给出专业的分析见解。' }, content ]); setPreviewData({ columns: ['分析结果'], data: [[result]] }); message.success('数据分析成功'); setCurrentStep(1); } catch (error) { message.error('数据分析失败'); console.error('API调用失败:', error); } finally { setLoading(false); } }; const generateReport = async () => { try { const result = await sendRequest([ { type: 'text', text: `请基于以下分析目标和数据,生成一份详细的markdown格式分析报告,包含标题、概述、详细分析等章节:${goal}\n${previewData?.data[0][0]}` } ], { maxTokens: 2000 }); // 解析 markdown 内容 const titleMatch = result.match(/^#\s+(.+)$/m); const title = titleMatch ? titleMatch[1] : '数据分析报告'; setReportData({ title, summary: '', sections: [], charts: [], markdown: result }); setWordUrl('https://example.com/report.docx'); message.success('报告生成成功'); setCurrentStep(2); } catch (error) { message.error('报告生成失败'); } }; const generateWordDocument = async (markdown: string) => { const doc = new Document({ sections: [ { properties: {}, children: markdown.split('\n').map(line => { if (line.startsWith('# ')) { return new DocxParagraph({ text: line.replace('# ', ''), heading: 'Heading1' }); } if (line.startsWith('## ')) { return new DocxParagraph({ text: line.replace('## ', ''), heading: 'Heading2' }); } return new DocxParagraph({ children: [ new TextRun({ text: line, size: 24 }) ] }); }) } ] }); const blob = await Packer.toBlob(doc); saveAs(blob, '数据分析报告.docx'); }; const handleDownload = async () => { if (reportData?.markdown) { try { await generateWordDocument(reportData.markdown); message.success('报告下载成功'); } catch (error) { message.error('报告下载失败'); console.error('下载失败:', error); } } }; const renderPreview = () => { if (!previewData) return null; return ( {previewData.columns.map((col: string) => ( ))} {previewData.data.map((row: any[], index: number) => ( {row.map((cell, cellIndex) => ( ))} ))}
{col}
{cell}
); }; const renderReport = () => { if (!reportData?.markdown) return null; return (
); }; const steps = [ { title: '上传文件', icon: , content: (
{ // const isExcelOrCsv = // file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || // file.type === 'application/vnd.ms-excel' || // file.type === 'text/csv'; // if (!isExcelOrCsv) { // message.error('只支持上传 Excel 或 CSV 文件!'); // return false; // } setFileList([file]); handleUpload(file); return false; }} onRemove={() => { setFileList([]); setCurrentStep(0); setPreviewData(null); return true; }} >

点击或拖拽文件到此区域上传

支持 Excel 和 CSV 文件格式

{loading && ( )} {renderPreview()}
), }, { title: '设置目标', icon: , content: (
分析目标设置 请详细描述您的分析需求,例如:
  • 分析销售趋势和影响因素
  • 识别客户购买行为模式
  • 预测未来销售情况