diff --git a/frontend/src/App.js b/frontend/src/App.js
index 6bec285..4f6b890 100644
--- a/frontend/src/App.js
+++ b/frontend/src/App.js
@@ -10,6 +10,8 @@ import CitiesPage from './components/region/CitiesPage';
import CityDetailPage from './components/region/CityDetailPage';
import ArticleDetailPage from './components/article/ArticleDetailPage';
import ServiceDetailPage from './components/service/ServiceDetailPage';
+import LoginPage from './components/auth/LoginPage';
+import RegisterPage from './components/auth/RegisterPage';
const Container = styled.div`
max-width: 1200px;
@@ -46,6 +48,8 @@ function App() {
} />
} />
} />
+ } />
+ } />
} />
} />
diff --git a/frontend/src/components/auth/LoginPage.js b/frontend/src/components/auth/LoginPage.js
new file mode 100644
index 0000000..f112340
--- /dev/null
+++ b/frontend/src/components/auth/LoginPage.js
@@ -0,0 +1,143 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import { observer } from 'mobx-react-lite';
+import { useAuthStore } from '../../stores/AuthStore';
+import { useNavigate } from 'react-router-dom';
+
+const Container = styled.div`
+ max-width: 400px;
+ margin: 50px auto;
+ padding: 30px;
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+`;
+
+const Title = styled.h2`
+ text-align: center;
+ margin-bottom: 30px;
+ color: #333;
+`;
+
+const Form = styled.form`
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+`;
+
+const InputGroup = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+`;
+
+const Label = styled.label`
+ font-weight: 500;
+ color: #555;
+`;
+
+const Input = styled.input`
+ padding: 10px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 16px;
+
+ &:focus {
+ outline: none;
+ border-color: #667eea;
+ }
+`;
+
+const Button = styled.button`
+ padding: 12px;
+ background: #667eea;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ font-size: 16px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: background 0.2s;
+
+ &:hover {
+ background: #5568d3;
+ }
+
+ &:disabled {
+ background: #ccc;
+ cursor: not-allowed;
+ }
+`;
+
+const ErrorMessage = styled.div`
+ color: #dc3545;
+ font-size: 14px;
+ text-align: center;
+`;
+
+const Link = styled.a`
+ text-align: center;
+ color: #667eea;
+ text-decoration: none;
+ font-size: 14px;
+
+ &:hover {
+ text-decoration: underline;
+ }
+`;
+
+const LoginPage = observer(() => {
+ const authStore = useAuthStore();
+ const navigate = useNavigate();
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ const result = await authStore.login(email, password);
+ if (result.success) {
+ navigate('/');
+ }
+ };
+
+ return (
+
+ 登录
+
+
+ 没有账号?立即注册
+
+ );
+});
+
+export default LoginPage;
\ No newline at end of file
diff --git a/frontend/src/components/auth/RegisterPage.js b/frontend/src/components/auth/RegisterPage.js
new file mode 100644
index 0000000..3640a4a
--- /dev/null
+++ b/frontend/src/components/auth/RegisterPage.js
@@ -0,0 +1,161 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import { useNavigate } from 'react-router-dom';
+
+const Container = styled.div`
+ max-width: 400px;
+ margin: 50px auto;
+ padding: 30px;
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+`;
+
+const Title = styled.h2`
+ text-align: center;
+ margin-bottom: 30px;
+ color: #333;
+`;
+
+const Form = styled.form`
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+`;
+
+const InputGroup = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+`;
+
+const Label = styled.label`
+ font-weight: 500;
+ color: #555;
+`;
+
+const Input = styled.input`
+ padding: 10px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 16px;
+
+ &:focus {
+ outline: none;
+ border-color: #667eea;
+ }
+`;
+
+const Button = styled.button`
+ padding: 12px;
+ background: #667eea;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ font-size: 16px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: background 0.2s;
+
+ &:hover {
+ background: #5568d3;
+ }
+`;
+
+const Link = styled.a`
+ text-align: center;
+ color: #667eea;
+ text-decoration: none;
+ font-size: 14px;
+
+ &:hover {
+ text-decoration: underline;
+ }
+`;
+
+const RegisterPage = () => {
+ const navigate = useNavigate();
+ const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [confirmPassword, setConfirmPassword] = useState('');
+ const [error, setError] = useState('');
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ setError('');
+
+ if (password !== confirmPassword) {
+ setError('两次输入的密码不一致');
+ return;
+ }
+
+ // TODO: 调用注册 API
+ console.log('Register:', { username, email, password });
+
+ navigate('/login');
+ };
+
+ return (
+
+ 注册
+
+
+ 已有账号?立即登录
+
+ );
+};
+
+export default RegisterPage;
\ No newline at end of file