/* eslint-disable @typescript-eslint/no-explicit-any */ 'use client'; import { AlertTriangle, Download, FileCheck, Lock, Upload } from 'lucide-react'; import { useRef, useState } from 'react'; import Swal from 'sweetalert2'; interface DataMigrationProps { onRefreshConfig?: () => Promise; } const DataMigration = ({ onRefreshConfig }: DataMigrationProps) => { const [exportPassword, setExportPassword] = useState(''); const [importPassword, setImportPassword] = useState(''); const [selectedFile, setSelectedFile] = useState(null); const [isExporting, setIsExporting] = useState(false); const [isImporting, setIsImporting] = useState(false); const fileInputRef = useRef(null); // 导出数据 const handleExport = async () => { if (!exportPassword.trim()) { Swal.fire({ icon: 'error', title: '错误', text: '请输入加密密码', returnFocus: false, }); return; } try { setIsExporting(true); const response = await fetch('/api/admin/data_migration/export', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ password: exportPassword, }), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error(errorData.error || `导出失败: ${response.status}`); } // 获取文件名 const contentDisposition = response.headers.get('content-disposition'); const filenameMatch = contentDisposition?.match(/filename="(.+)"/); const filename = filenameMatch?.[1] || 'moontv-backup.dat'; // 下载文件 const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.style.display = 'none'; a.style.position = 'fixed'; a.style.top = '0'; a.style.left = '0'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); Swal.fire({ icon: 'success', title: '导出成功', text: '数据已成功导出,请妥善保管备份文件和密码', timer: 3000, showConfirmButton: false, returnFocus: false, }); setExportPassword(''); } catch (error) { Swal.fire({ icon: 'error', title: '导出失败', text: error instanceof Error ? error.message : '导出过程中发生错误', returnFocus: false, }); } finally { setIsExporting(false); } }; // 文件选择处理 const handleFileSelect = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { setSelectedFile(file); } }; // 导入数据 const handleImport = async () => { if (!selectedFile) { Swal.fire({ icon: 'error', title: '错误', text: '请选择备份文件', returnFocus: false, }); return; } if (!importPassword.trim()) { Swal.fire({ icon: 'error', title: '错误', text: '请输入解密密码', returnFocus: false, }); return; } try { setIsImporting(true); const formData = new FormData(); formData.append('file', selectedFile); formData.append('password', importPassword); const response = await fetch('/api/admin/data_migration/import', { method: 'POST', body: formData, }); const result = await response.json(); if (!response.ok) { throw new Error(result.error || `导入失败: ${response.status}`); } await Swal.fire({ icon: 'success', title: '导入成功', html: `

导入完成!

导入的用户数量: ${result.importedUsers}

备份时间: ${new Date(result.timestamp).toLocaleString('zh-CN')}

服务器版本: ${result.serverVersion || '未知版本'}

请刷新页面以查看最新数据。

`, confirmButtonText: '刷新页面', returnFocus: false, }); // 清理状态 setSelectedFile(null); setImportPassword(''); if (fileInputRef.current) { fileInputRef.current.value = ''; } // 刷新配置 if (onRefreshConfig) { await onRefreshConfig(); } // 刷新页面 window.location.reload(); } catch (error) { Swal.fire({ icon: 'error', title: '导入失败', text: error instanceof Error ? error.message : '导入过程中发生错误', returnFocus: false, }); } finally { setIsImporting(false); } }; return (
{/* 简洁警告提示 */}

数据迁移操作请谨慎,确保已备份重要数据

{/* 主要操作区域 - 响应式布局 */}
{/* 数据导出 */}

数据导出

创建加密备份文件

{/* 密码输入 */}
setExportPassword(e.target.value)} placeholder="设置强密码保护备份文件" className="w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors" disabled={isExporting} />

导入时需要使用相同密码

{/* 备份内容列表 */}

备份内容:

• 管理配置
• 用户数据
• 播放记录
• 收藏夹
{/* 导出按钮 */}
{/* 数据导入 */}

数据导入

⚠️ 将清空现有数据

{/* 文件选择 */}
{/* 密码输入 */}
setImportPassword(e.target.value)} placeholder="输入导出时的加密密码" className="w-full px-3 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-red-500 focus:border-red-500 transition-colors" disabled={isImporting} />
{/* 导入按钮 */}
); }; export default DataMigration;