160 lines
4.7 KiB
TypeScript
160 lines
4.7 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useState, useCallback } from "react";
|
||
import { useSession } from "next-auth/react";
|
||
import { useRouter } from "next/navigation";
|
||
import Header from "@/components/Header";
|
||
import AudioRecorder from "@/components/AudioRecorder";
|
||
import RecordingList from "@/components/RecordingList";
|
||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||
|
||
interface Recording {
|
||
id: string;
|
||
title: string;
|
||
duration: number;
|
||
createdAt: string;
|
||
audioUrl: string;
|
||
}
|
||
|
||
export default function DashboardPage() {
|
||
const { data: session, status } = useSession();
|
||
const router = useRouter();
|
||
const [recordings, setRecordings] = useState<Recording[]>([]);
|
||
const [isLoading, setIsLoading] = useState(true);
|
||
|
||
// 处理录音更新
|
||
const handleRecordingUpdated = useCallback((updatedRecording: Recording) => {
|
||
setRecordings((prevRecordings) =>
|
||
prevRecordings.map((recording) =>
|
||
recording.id === updatedRecording.id ? updatedRecording : recording
|
||
)
|
||
);
|
||
}, []);
|
||
|
||
// 获取录音列表
|
||
const fetchRecordings = useCallback(async () => {
|
||
try {
|
||
const response = await fetch("/api/recordings");
|
||
if (response.ok) {
|
||
const result = await response.json();
|
||
if (result.success && Array.isArray(result.data)) {
|
||
setRecordings(result.data);
|
||
} else {
|
||
console.error("API 返回数据格式错误:", result);
|
||
setRecordings([]);
|
||
}
|
||
} else {
|
||
console.error("获取录音列表失败:", response.status);
|
||
setRecordings([]);
|
||
}
|
||
} catch (error) {
|
||
console.error("获取录音列表失败:", error);
|
||
setRecordings([]);
|
||
} finally {
|
||
setIsLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 监听录音上传和删除事件
|
||
useEffect(() => {
|
||
const handleRecordingUploaded = () => {
|
||
// 延迟一点时间确保服务器处理完成
|
||
setTimeout(() => {
|
||
fetchRecordings();
|
||
}, 500);
|
||
};
|
||
|
||
const handleRecordingDeleted = () => {
|
||
// 延迟一点时间确保服务器处理完成
|
||
setTimeout(() => {
|
||
fetchRecordings();
|
||
}, 500);
|
||
};
|
||
|
||
const handleRecordingRenamed = () => {
|
||
// 立即清除可能的缓存
|
||
// 延迟一点时间确保服务器处理完成
|
||
setTimeout(() => {
|
||
fetchRecordings();
|
||
}, 100); // 减少延迟时间
|
||
};
|
||
|
||
window.addEventListener("recording-uploaded", handleRecordingUploaded);
|
||
window.addEventListener("recording-deleted", handleRecordingDeleted);
|
||
window.addEventListener("recording-renamed", handleRecordingRenamed);
|
||
|
||
return () => {
|
||
window.removeEventListener("recording-uploaded", handleRecordingUploaded);
|
||
window.removeEventListener("recording-deleted", handleRecordingDeleted);
|
||
window.removeEventListener("recording-renamed", handleRecordingRenamed);
|
||
};
|
||
}, [fetchRecordings]);
|
||
|
||
// 初始加载录音列表
|
||
useEffect(() => {
|
||
if (status === "authenticated") {
|
||
fetchRecordings();
|
||
}
|
||
}, [status]);
|
||
|
||
// 检查认证状态
|
||
if (status === "loading") {
|
||
return (
|
||
<div className="flex justify-center items-center min-h-screen">
|
||
<LoadingSpinner size="lg" color="blue" text="加载中..." />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (status === "unauthenticated") {
|
||
router.push("/login");
|
||
return null;
|
||
}
|
||
|
||
if (!session?.user) {
|
||
return null;
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||
<Header />
|
||
|
||
<main className="container mx-auto p-4 md:p-8 max-w-6xl">
|
||
<div className="mb-12">
|
||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||
你好, {session.user.name || session.user.email}!
|
||
</h2>
|
||
<p className="text-gray-600 dark:text-gray-400 text-lg">
|
||
准备好录制你的下一个杰作了吗?点击下方按钮开始。
|
||
</p>
|
||
</div>
|
||
|
||
<div className="mb-16">
|
||
<AudioRecorder />
|
||
</div>
|
||
|
||
<div>
|
||
<div className="flex justify-between items-center mb-6">
|
||
<h3 className="text-2xl md:text-3xl font-semibold text-gray-900 dark:text-white">
|
||
我的录音
|
||
</h3>
|
||
<button
|
||
onClick={fetchRecordings}
|
||
className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
|
||
>
|
||
刷新列表
|
||
</button>
|
||
</div>
|
||
{isLoading ? (
|
||
<div className="text-center py-12">
|
||
<LoadingSpinner size="lg" color="blue" text="加载录音中..." />
|
||
</div>
|
||
) : (
|
||
<RecordingList recordings={recordings} />
|
||
)}
|
||
</div>
|
||
</main>
|
||
</div>
|
||
);
|
||
}
|