diff --git a/.gitignore b/.gitignore
index f90f665..f37e688 100644
--- a/.gitignore
+++ b/.gitignore
@@ -141,3 +141,8 @@ vite.config.ts.timestamp-*
generate-token.js
**/Login.jsx
+b a c k e n d / p r i s m a / p r i s m a / d e v . d b
+
+ * . db
+
+
\ No newline at end of file
diff --git a/frontend/src/librarian/LibrarianDashboard.jsx b/frontend/src/librarian/LibrarianDashboard.jsx
index eb50723..81fd63f 100644
--- a/frontend/src/librarian/LibrarianDashboard.jsx
+++ b/frontend/src/librarian/LibrarianDashboard.jsx
@@ -101,7 +101,7 @@ export default function LibrarianDashboard({ librarian, onLogout }) {
onClick={() => setActiveTab('home')}
className="mb-4 bg-gray-200 text-gray-800 px-4 py-2 rounded-lg hover:bg-gray-300 transition flex items-center gap-2"
>
- ← 返回仪表盘
+ ← 返回
diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx
new file mode 100644
index 0000000..f5d725a
--- /dev/null
+++ b/frontend/src/pages/Login.jsx
@@ -0,0 +1,56 @@
+import { useState } from 'react';
+
+function Login({ onLogin }) {
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [error, setError] = useState('');
+ const [loading, setLoading] = useState(false);
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ setError('');
+ setLoading(true);
+
+ try {
+ const res = await fetch('http://localhost:3001/readers/login', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ email, password })
+ });
+
+ const data = await res.json();
+
+ if (res.ok && data.token) {
+ localStorage.setItem('token', data.token);
+ localStorage.setItem('user', JSON.stringify(data.user));
+ if (onLogin) onLogin(data.user);
+ window.location.href = '/';
+ } else {
+ setError(data.message || 'Login failed');
+ }
+ } catch (err) {
+ setError('Cannot connect to server');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+ );
+}
+
+export default Login;
\ No newline at end of file