From f14e62af66368f307fdf936460898dbac87f942d Mon Sep 17 00:00:00 2001 From: Leo <98382335+gaoziman@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:05:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现SQL文件上传功能 - 支持拖拽上传 --- src/components/FileUpload.js | 294 +++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 src/components/FileUpload.js diff --git a/src/components/FileUpload.js b/src/components/FileUpload.js new file mode 100644 index 0000000..258b361 --- /dev/null +++ b/src/components/FileUpload.js @@ -0,0 +1,294 @@ +/** + * 文件上传组件 + */ +import React, { useState } from 'react'; +import { + Upload, + Button, + Progress, + Alert, + Card, + Row, + Col, + Typography, + Space, + Divider, + Tag, + message, +} from 'antd'; +import { + UploadOutlined, + CheckCircleOutlined, + ExclamationCircleOutlined, + DownloadOutlined, + CopyOutlined, +} from '@ant-design/icons'; +import { apiService } from '../services/api'; +import { + formatFileSize, + formatConversionTime, + validateSQLFile, + downloadFile, + copyToClipboard +} from '../utils/helpers'; + +const { Title, Text, Paragraph } = Typography; +const { Dragger } = Upload; + +const FileUpload = ({ onUploadSuccess }) => { + const [uploading, setUploading] = useState(false); + const [uploadProgress, setUploadProgress] = useState(0); + const [result, setResult] = useState(null); + const [error, setError] = useState(null); + + // 处理文件上传 + const handleUpload = async (file) => { + // 验证文件类型 + if (!validateSQLFile(file)) { + message.error('只能上传.sql格式的文件'); + return false; + } + + // 验证文件大小 (50MB) + if (file.size > 50 * 1024 * 1024) { + message.error('文件大小不能超过50MB'); + return false; + } + + setUploading(true); + setUploadProgress(0); + setResult(null); + setError(null); + + try { + const response = await apiService.uploadFile(file, (progress) => { + setUploadProgress(progress); + }); + + if (response.data.status === 'success') { + setResult(response.data.data); + message.success('文件转换成功!'); + if (onUploadSuccess) { + onUploadSuccess(response.data.data); + } + } else { + throw new Error(response.data.message || '转换失败'); + } + } catch (err) { + const errorMsg = err.message || '上传失败,请重试'; + setError(errorMsg); + message.error(errorMsg); + } finally { + setUploading(false); + setUploadProgress(0); + } + + return false; // 阻止默认上传 + }; + + // 下载转换后的文件 + const handleDownload = async () => { + if (!result?.record_id) return; + + try { + const response = await apiService.downloadFile(result.record_id); + const blob = new Blob([response.data], { type: 'text/plain' }); + downloadFile(blob, result.converted_filename); + message.success('文件下载成功'); + } catch (err) { + message.error('下载失败: ' + err.message); + } + }; + + // 复制URL到剪贴板 + const handleCopyUrl = async (url) => { + const success = await copyToClipboard(url); + if (success) { + message.success('URL已复制到剪贴板'); + } else { + message.error('复制失败'); + } + }; + + return ( + + + + +

+ +

+

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

+

+ 支持单个文件上传,文件格式:.sql,最大支持50MB +

+
+ + {uploading && ( +
+ + + 正在上传并转换文件... + +
+ )} + + {error && ( + + )} + + + +
+ 转换说明 + + 本工具支持将 SQL Server 2008 的SQL语法转换为 MySQL 8 兼容语法。 + + + + + 主要转换内容: +
    +
  • 数据类型转换(nvarchar → VARCHAR)
  • +
  • 标识符转换([schema].[table] → `table`)
  • +
  • 自增长字段(IDENTITY → AUTO_INCREMENT)
  • +
  • 函数转换(GETDATE() → NOW())
  • +
  • 事务语法(BEGIN TRANSACTION → START TRANSACTION)
  • +
  • 移除SQL Server特定语法
  • +
+
+ +
+ + {result && ( +
+ + } + /> + + + + + } + > + + + 原始文件: +
+ {result.original_filename} + + + 转换后文件: +
+ {result.converted_filename} + + + 文件大小: +
+ {formatFileSize(result.file_size)} + + + 转换耗时: +
+ {formatConversionTime(result.conversion_time)} + +
+ + {result.converted_url && ( +
+ 下载链接: +
+ + + {result.converted_url} + + + +
+ )} + + {result.warnings && result.warnings.length > 0 && ( +
+ + {result.warnings.map((warning, index) => ( +
  • {warning}
  • + ))} + + } + type="warning" + showIcon + icon={} + /> +
    + )} + + {result.validation_issues && result.validation_issues.length > 0 && ( +
    + + {result.validation_issues.map((issue, index) => ( +
  • {issue}
  • + ))} + + } + type="info" + showIcon + /> +
    + )} +
    +
    + )} +
    + ); +}; + +export default FileUpload; \ No newline at end of file