Initial commit

This commit is contained in:
theshy
2025-07-31 17:05:07 +08:00
parent 8fab3b19cc
commit 24f21144ab
91 changed files with 16311 additions and 159 deletions

159
app/dashboard/page.tsx Normal file
View File

@ -0,0 +1,159 @@
"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>
);
}