"use client" import { useState } from "react" import { useRouter } from "next/navigation" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" import { Progress } from "@/components/ui/progress" import { SiteHeader } from "@/components/site-header" import { Database, AlertTriangle, CheckCircle2 } from "lucide-react" import { migrateFromIndexedDB, clearIndexedDB } from "@/lib/migrate-data" export default function MigratePage() { const router = useRouter() const [status, setStatus] = useState<"idle" | "migrating" | "success" | "error">("idle") const [progress, setProgress] = useState(0) const [result, setResult] = useState(null) const [error, setError] = useState("") const handleMigrate = async () => { setStatus("migrating") setProgress(0) setError("") try { // 模拟进度 setProgress(20) // 这里需要先创建一个家族树,然后获取 treeId 和 userId // 为了演示,我们先创建一个默认的家族树 const treeResponse = await fetch("/api/trees", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "我的家族树", description: "从 IndexedDB 迁移的数据" }) }) if (!treeResponse.ok) { throw new Error("创建家族树失败") } const { tree } = await treeResponse.json() setProgress(40) // 执行迁移 const migrateResult = await migrateFromIndexedDB(tree.id, tree.ownerId) setProgress(80) setResult(migrateResult) setProgress(100) setStatus("success") } catch (err: any) { setError(err.message || "迁移失败") setStatus("error") } } const handleClearIndexedDB = async () => { if (!confirm("确定要清空 IndexedDB 数据吗?此操作不可撤销!")) { return } try { await clearIndexedDB() alert("IndexedDB 数据已清空") } catch (err: any) { alert("清空失败: " + err.message) } } return (

数据迁移

从 IndexedDB 迁移到 PostgreSQL 将本地浏览器中的家族数据迁移到云端数据库 注意 迁移前请确保:
  • 已登录账号
  • 本地有需要迁移的数据
  • 网络连接正常
{status === "migrating" && (
迁移进度 {progress}%
)} {status === "success" && result && ( 迁移成功! 成功迁移 {result.count} / {result.total} 个成员 {result.errors > 0 && `,失败 ${result.errors} 个`} )} {status === "error" && ( 迁移失败 {error} )}
{status === "success" && ( )}
危险操作 迁移成功后,可以选择清空本地数据
) }