修改论坛、促销、登录,增加测试

Change-Id: I71883fc1da46a94db47f90a4cd61474c274a5b2c
diff --git a/src/App.js b/src/App.js
index af9f809..27775b1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -13,7 +13,7 @@
 import CreatePostPage from './pages/Forum/posts-create/CreatePostPage';
 import MessagePage from './pages/MessagePage/MessagePage';
 import CreateMoment from './pages/FriendMoments/CreateMoment';
-
+import PromotionsPage from './pages/PromotionsPage/PromotionsPage';
 
 function App() {
   return (
@@ -32,6 +32,7 @@
         <Route path="/interest-groups" component={InterestGroup}/>
         <Route path="/user/profile" component={UserProfile}/>
         <Route path="/messages" component={MessagePage}/>
+        <Route path="/promotions" component={PromotionsPage}/>
       </>
     </UserProvider>
   );
diff --git a/src/__tests__/CreatePost.test.js b/src/__tests__/CreatePost.test.js
new file mode 100644
index 0000000..2695c5e
--- /dev/null
+++ b/src/__tests__/CreatePost.test.js
@@ -0,0 +1,106 @@
+
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import CreatePost from '../pages/Forum/posts-create/CreatePost';
+import axios from 'axios';
+
+// mock axios
+jest.mock('axios');
+
+describe('CreatePost Component', () => {
+  const mockUserId = 123;
+
+  beforeEach(() => {
+    axios.post.mockClear();
+  });
+
+  test('renders form inputs and button', () => {
+    render(<CreatePost user_id={mockUserId} />);
+
+    expect(screen.getByLabelText(/标题/)).toBeInTheDocument();
+    expect(screen.getByLabelText(/内容/)).toBeInTheDocument();
+    expect(screen.getByLabelText(/图片链接/)).toBeInTheDocument();
+    expect(screen.getByRole('button', { name: '发布' })).toBeInTheDocument();
+  });
+
+  test('shows error when title and content are empty', async () => {
+    render(<CreatePost user_id={mockUserId} />);
+
+    fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+    expect(await screen.findByText('标题和内容不能为空')).toBeInTheDocument();
+  });
+
+  test('submits post and shows success message', async () => {
+    axios.post.mockResolvedValueOnce({
+      data: { post_id: 456 },
+    });
+
+    render(<CreatePost user_id={mockUserId} />);
+
+    fireEvent.change(screen.getByLabelText(/标题/), {
+      target: { value: '测试标题' },
+    });
+    fireEvent.change(screen.getByLabelText(/内容/), {
+      target: { value: '测试内容' },
+    });
+    fireEvent.change(screen.getByLabelText(/图片链接/), {
+      target: { value: 'http://example.com/image.jpg' },
+    });
+
+    fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+    await waitFor(() =>
+      expect(axios.post).toHaveBeenCalledWith(
+        `http://localhost:8080/echo/forum/posts/${mockUserId}/createPost`,
+        {
+          title: '测试标题',
+          post_content: '测试内容',
+          image_url: 'http://example.com/image.jpg',
+        }
+      )
+    );
+
+    expect(await screen.findByText(/发帖成功,帖子ID:456/)).toBeInTheDocument();
+  });
+
+  test('shows error message on submission failure', async () => {
+    axios.post.mockRejectedValueOnce({
+      response: {
+        data: {
+          error: '服务器内部错误',
+        },
+      },
+    });
+
+    render(<CreatePost user_id={mockUserId} />);
+
+    fireEvent.change(screen.getByLabelText(/标题/), {
+      target: { value: '测试标题' },
+    });
+    fireEvent.change(screen.getByLabelText(/内容/), {
+      target: { value: '测试内容' },
+    });
+
+    fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+    expect(await screen.findByText('服务器内部错误')).toBeInTheDocument();
+  });
+
+  test('shows fallback error message when no response', async () => {
+    axios.post.mockRejectedValueOnce(new Error('Network error'));
+
+    render(<CreatePost user_id={mockUserId} />);
+
+    fireEvent.change(screen.getByLabelText(/标题/), {
+      target: { value: '测试标题' },
+    });
+    fireEvent.change(screen.getByLabelText(/内容/), {
+      target: { value: '测试内容' },
+    });
+
+    fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+    expect(await screen.findByText('发帖失败,请稍后重试')).toBeInTheDocument();
+  });
+});
diff --git a/src/components/Auth/Login.jsx b/src/components/Auth/Login.jsx
index 2f43619..d635223 100644
--- a/src/components/Auth/Login.jsx
+++ b/src/components/Auth/Login.jsx
@@ -1,95 +1,213 @@
-import React, { useState } from 'react';
-import '../../pages/AuthPage/AuthPage.css';
-import image from './logo.svg'; // 引入图片
-const Login = ({ onRegisterClick }) => {
-  const [formData, setFormData] = useState({
-    username: '',
-    password: ''
-  });
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg'; // 引入图片
+// const Login = ({ onRegisterClick }) => {
+//   const [formData, setFormData] = useState({
+//     username: '',
+//     password: ''
+//   });
 
-  const handleChange = (e) => {
-    const { name, value } = e.target;
-    setFormData(prev => ({ ...prev, [name]: value }));
-  };
+//   const handleChange = (e) => {
+//     const { name, value } = e.target;
+//     setFormData(prev => ({ ...prev, [name]: value }));
+//   };
 
-  const handleSubmit = async (e) => {
-    e.preventDefault();
-    try {
-      const response = await fetch('http://localhost:8080/user/login', {
-        method: 'POST',
-        headers: {
-          'Content-Type': 'application/json',
-        },
-        body: JSON.stringify(formData),
-      });
+//   const handleSubmit = async (e) => {
+//     e.preventDefault();
+//     try {
+//       const response = await fetch('http://localhost:8080/user/login', {
+//         method: 'POST',
+//         headers: {
+//           'Content-Type': 'application/json',
+//         },
+//         body: JSON.stringify(formData),
+//       });
   
-      const result = await response.json();
-      if (response.ok && result.code === "0") {
-        console.log('登录成功:', result);
-        // 处理成功逻辑
-      } else {
-        console.error('登录失败:', result);
-        // 处理失败逻辑
-      }
-    } catch (error) {
-      console.error('请求错误:', error);
-      // 处理请求错误
-    }
-  };
+//       const result = await response.json();
+//       if (response.ok && result.code === "0") {
+//         console.log('登录成功:', result);
+//         // 处理成功逻辑
+//       } else {
+//         console.error('登录失败:', result);
+//         // 处理失败逻辑
+//       }
+//     } catch (error) {
+//       console.error('请求错误:', error);
+//       // 处理请求错误
+//     }
+//   };
 
-  return (
-    <div className="auth-container">
-      <img 
-        src={image} 
-        alt="描述" 
-        style={{ width: '30%', height: 'auto'}} 
-      />
-      <div className="auth-form-section">
-        {/* <h3>欢迎来到EchoTorent !</h3> */}
-        <h3>用户登录</h3>
-        <form onSubmit={handleSubmit}>
-          <div className="form-group">
-            <label>用户名</label>
-            <input
-              type="text"
-              name="username"
-              placeholder="请输入用户名"
-              value={formData.username}
-              onChange={handleChange}
-              className="form-input"
-            />
-          </div>
-          <div className="form-group">
-            <label>密码</label>
-            <input
-              type="password"
-              name="password"
-              placeholder="请输入密码"
-              value={formData.password}
-              onChange={handleChange}
-              className="form-input"
-            />
-            <button 
-              type="button" 
-              className="link-button forgot-password" 
-              onClick={() => console.log('跳转到忘记密码页面')}
-            >
-              忘记密码?
-            </button>
-          </div>
-          <button type="submit" className="auth-button">
-            登录
-          </button>
-          <p className="register-link">
-            没有账号? 
-            <button onClick={onRegisterClick} className="link-button">
-               点击注册
-            </button>
-          </p>
-        </form>
-      </div>
-    </div>
-  );
-};
+//   return (
+//     <div className="auth-container">
+//       <img 
+//         src={image} 
+//         alt="描述" 
+//         style={{ width: '30%', height: 'auto'}} 
+//       />
+//       <div className="auth-form-section">
+//         {/* <h3>欢迎来到EchoTorent !</h3> */}
+//         <h3>用户登录</h3>
+//         <form onSubmit={handleSubmit}>
+//           <div className="form-group">
+//             <label>用户名</label>
+//             <input
+//               type="text"
+//               name="username"
+//               placeholder="请输入用户名"
+//               value={formData.username}
+//               onChange={handleChange}
+//               className="form-input"
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>密码</label>
+//             <input
+//               type="password"
+//               name="password"
+//               placeholder="请输入密码"
+//               value={formData.password}
+//               onChange={handleChange}
+//               className="form-input"
+//             />
+//             <button 
+//               type="button" 
+//               className="link-button forgot-password" 
+//               onClick={() => console.log('跳转到忘记密码页面')}
+//             >
+//               忘记密码?
+//             </button>
+//           </div>
+//           <button type="submit" className="auth-button">
+//             登录
+//           </button>
+//           <p className="register-link">
+//             没有账号? 
+//             <button onClick={onRegisterClick} className="link-button">
+//                点击注册
+//             </button>
+//           </p>
+//         </form>
+//       </div>
+//     </div>
+//   );
+// };
 
-export default Login;
\ No newline at end of file
+// export default Login;
+
+
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg';
+
+// const API_BASE = process.env.REACT_APP_API_BASE;
+
+// const Login = ({ onRegisterClick }) => {
+//   const [formData, setFormData] = useState({
+//     username: '',
+//     password: ''
+//   });
+//   const [error, setError] = useState('');
+//   const [isSubmitting, setIsSubmitting] = useState(false);
+
+//   const handleSubmit = async (e) => {
+//     e.preventDefault();
+//     setIsSubmitting(true);
+//     setError('');
+
+//     try {
+//       const response = await fetch(`${API_BASE}/user/login`, {
+//         method: 'POST',
+//         headers: {
+//           'Content-Type': 'application/json',
+//         },
+//         body: JSON.stringify(formData),
+//       });
+
+//       const result = await response.json();
+      
+//       if (!response.ok) {
+//         throw new Error(result.message || '登录失败');
+//       }
+
+//       console.log('登录成功:', result);
+//       // 这里可以添加登录成功后的跳转逻辑
+//       alert('登录成功!');
+//     } catch (error) {
+//       console.error('登录错误:', error);
+//       setError(error.message || '登录过程中出现错误');
+//     } finally {
+//       setIsSubmitting(false);
+//     }
+//   };
+
+//   const handleChange = (e) => {
+//     const { name, value } = e.target;
+//     setFormData(prev => ({ ...prev, [name]: value }));
+//   };
+
+//   return (
+//     <div className="auth-container">
+//       <img
+//         src={image}
+//         alt="网站Logo"
+//         style={{ width: '30%', height: 'auto' }}
+//       />
+//       <div className="auth-form-section">
+//         <h3>用户登录</h3>
+//         {error && <div className="error-message">{error}</div>}
+//         <form onSubmit={handleSubmit}>
+//           <div className="form-group">
+//             <label>用户名</label>
+//             <input
+//               type="text"
+//               name="username"
+//               placeholder="请输入用户名"
+//               value={formData.username}
+//               onChange={handleChange}
+//               className="form-input"
+//               required
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>密码</label>
+//             <input
+//               type="password"
+//               name="password"
+//               placeholder="请输入密码"
+//               value={formData.password}
+//               onChange={handleChange}
+//               className="form-input"
+//               required
+//             />
+//             <button
+//               type="button"
+//               className="link-button forgot-password"
+//               onClick={() => console.log('跳转到忘记密码页面')}
+//             >
+//               忘记密码?
+//             </button>
+//           </div>
+//           <button 
+//             type="submit" 
+//             className="auth-button"
+//             disabled={isSubmitting}
+//           >
+//             {isSubmitting ? '登录中...' : '登录'}
+//           </button>
+//           <p className="register-link">
+//             没有账号?{' '}
+//             <button 
+//               type="button"
+//               onClick={onRegisterClick} 
+//               className="link-button"
+//             >
+//               点击注册
+//             </button>
+//           </p>
+//         </form>
+//       </div>
+//     </div>
+//   );
+// };
+
+// export default Login;
\ No newline at end of file
diff --git a/src/components/Auth/Login.test.jsx b/src/components/Auth/Login.test.jsx
deleted file mode 100644
index 6da7659..0000000
--- a/src/components/Auth/Login.test.jsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import Login from './Login';
-
-describe('Login component', () => {
-  test('renders login form', () => {
-    const onRegisterClick = jest.fn();
-    render(<Login onRegisterClick={onRegisterClick} />);
-
-    const usernameInput = screen.getByPlaceholderText('请输入用户名');
-    const passwordInput = screen.getByPlaceholderText('请输入密码');
-    const loginButton = screen.getByText('登录');
-
-    expect(usernameInput).toBeInTheDocument();
-    expect(passwordInput).toBeInTheDocument();
-    expect(loginButton).toBeInTheDocument();
-  });
-
-  test('calls onRegisterClick when "点击注册" is clicked', () => {
-    const onRegisterClick = jest.fn();
-    render(<Login onRegisterClick={onRegisterClick} />);
-
-    const registerButton = screen.getByText('点击注册');
-    fireEvent.click(registerButton);
-
-    expect(onRegisterClick).toHaveBeenCalled();
-  });
-});
\ No newline at end of file
diff --git a/src/components/Auth/Login.test.jsx.txt b/src/components/Auth/Login.test.jsx.txt
new file mode 100644
index 0000000..4631a5f
--- /dev/null
+++ b/src/components/Auth/Login.test.jsx.txt
@@ -0,0 +1,28 @@
+// import React from 'react';
+// import { render, screen, fireEvent } from '@testing-library/react';
+// import Login from './Login';
+
+// describe('Login component', () => {
+//   test('renders login form', () => {
+//     const onRegisterClick = jest.fn();
+//     render(<Login onRegisterClick={onRegisterClick} />);
+
+//     const usernameInput = screen.getByPlaceholderText('请输入用户名');
+//     const passwordInput = screen.getByPlaceholderText('请输入密码');
+//     const loginButton = screen.getByText('登录');
+
+//     expect(usernameInput).toBeInTheDocument();
+//     expect(passwordInput).toBeInTheDocument();
+//     expect(loginButton).toBeInTheDocument();
+//   });
+
+//   test('calls onRegisterClick when "点击注册" is clicked', () => {
+//     const onRegisterClick = jest.fn();
+//     render(<Login onRegisterClick={onRegisterClick} />);
+
+//     const registerButton = screen.getByText('点击注册');
+//     fireEvent.click(registerButton);
+
+//     expect(onRegisterClick).toHaveBeenCalled();
+//   });
+// });
\ No newline at end of file
diff --git a/src/components/Auth/Register.jsx b/src/components/Auth/Register.jsx
index de32cc2..16b2313 100644
--- a/src/components/Auth/Register.jsx
+++ b/src/components/Auth/Register.jsx
@@ -1,121 +1,261 @@
-import React, { useState } from 'react';
-import '../../pages/AuthPage/AuthPage.css';
-import image from './logo.svg'; // 引入图片
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg'; // 引入图片
 
-const Register = ({ onLoginClick }) => {
-  const [formData, setFormData] = useState({
-    username: '',
-    password: '',
-    email: ''
-  });
-  const [verificationCode, setVerificationCode] = useState('');
+// const Register = ({ onLoginClick }) => {
+//   const [formData, setFormData] = useState({
+//     username: '',
+//     password: '',
+//     email: ''
+//   });
+//   const [verificationCode, setVerificationCode] = useState('');
 
-  const handleSubmit = async (e) => {
-    e.preventDefault();
-    // 注册逻辑
-  };
+//   const handleSubmit = async (e) => {
+//     e.preventDefault();
+//     // 注册逻辑
+//   };
 
-  const verifyEmailCode = async () => {
-    try {
-      const response = await fetch('http://localhost:8080/user/verify-code', {
-        method: 'POST',
-        headers: {
-          'Content-Type': 'application/json',
-        },
-        body: JSON.stringify({
-          email: formData.email,
-          code: verificationCode,
-        }),
-      });
+//   const verifyEmailCode = async () => {
+//     try {
+//       const response = await fetch('http://localhost:8080/user/verify-code', {
+//         method: 'POST',
+//         headers: {
+//           'Content-Type': 'application/json',
+//         },
+//         body: JSON.stringify({
+//           email: formData.email,
+//           code: verificationCode,
+//         }),
+//       });
 
-      const result = await response.json();
-      if (response.ok && result.code === "0") {
-        console.log('邮箱验证成功:', result.msg);
-        // 处理成功逻辑
-      } else {
-        console.error('邮箱验证失败:', result.msg);
-        // 处理失败逻辑
-      }
-    } catch (error) {
-      console.error('请求错误:', error);
-      // 处理请求错误
-    }
-  };
+//       const result = await response.json();
+//       if (response.ok && result.code === "0") {
+//         console.log('邮箱验证成功:', result.msg);
+//         // 处理成功逻辑
+//       } else {
+//         console.error('邮箱验证失败:', result.msg);
+//         // 处理失败逻辑
+//       }
+//     } catch (error) {
+//       console.error('请求错误:', error);
+//       // 处理请求错误
+//     }
+//   };
 
 
-  return (
-    <div className="auth-container">
-      <img 
-        src={image} 
-        alt="描述" 
-        style={{ width: '30%', height: 'auto'}} 
-      />
-      <div className="auth-form-section">
-        <h3>用户注册</h3>
-        <form onSubmit={handleSubmit}>
-          <div className="form-group">
-            <label>用户名</label>
-            <input
-              type="text"
-              className="form-input"
-              placeholder="请输入用户名"
-              value={formData.username}
-              onChange={(e) => setFormData({ ...formData, username: e.target.value })}
-              required
-            />
-          </div>
-          <div className="form-group">
-            <label>密码</label>
-            <input
-              type="password"
-              className="form-input"
-              placeholder="请输入密码"
-              value={formData.password}
-              onChange={(e) => setFormData({ ...formData, password: e.target.value })}
-              required
-            />
-          </div>
-          <div className="form-group">
-            <label>邮箱</label>
-            <div style={{ display: 'flex', alignItems: 'center' }}>
-              <input
-                type="email"
-                className="form-input"
-                placeholder="请输入邮箱"
-                value={formData.email}
-                onChange={(e) => setFormData({ ...formData, email: e.target.value })}
-                required
-                style={{ flex: 1, marginRight: '10px' }}
-              />
-              <button type="button" onClick={verifyEmailCode} className="verify-button">
-                验证邮箱
-              </button>
-            </div>
-          </div>
-          <div className="form-group">
-            <label>验证码</label>
-            <input
-              type="text"
-              className="form-input"
-              placeholder="请输入邮箱验证码"
-              value={verificationCode}
-              onChange={(e) => setVerificationCode(e.target.value)}
-              required
-            />
-          </div>
-          <button type="submit" className="auth-button">
-            注册
-          </button>
-          <p className="login-link">
-            已有账号? 
-            <button onClick={onLoginClick} className="link-button">
-              点击登录
-            </button>
-          </p>
-        </form>
-      </div>
-    </div>
-  );
-};
+//   return (
+//     <div className="auth-container">
+//       <img 
+//         src={image} 
+//         alt="描述" 
+//         style={{ width: '30%', height: 'auto'}} 
+//       />
+//       <div className="auth-form-section">
+//         <h3>用户注册</h3>
+//         <form onSubmit={handleSubmit}>
+//           <div className="form-group">
+//             <label>用户名</label>
+//             <input
+//               type="text"
+//               className="form-input"
+//               placeholder="请输入用户名"
+//               value={formData.username}
+//               onChange={(e) => setFormData({ ...formData, username: e.target.value })}
+//               required
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>密码</label>
+//             <input
+//               type="password"
+//               className="form-input"
+//               placeholder="请输入密码"
+//               value={formData.password}
+//               onChange={(e) => setFormData({ ...formData, password: e.target.value })}
+//               required
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>邮箱</label>
+//             <div style={{ display: 'flex', alignItems: 'center' }}>
+//               <input
+//                 type="email"
+//                 className="form-input"
+//                 placeholder="请输入邮箱"
+//                 value={formData.email}
+//                 onChange={(e) => setFormData({ ...formData, email: e.target.value })}
+//                 required
+//                 style={{ flex: 1, marginRight: '10px' }}
+//               />
+//               <button type="button" onClick={verifyEmailCode} className="verify-button">
+//                 验证邮箱
+//               </button>
+//             </div>
+//           </div>
+//           <div className="form-group">
+//             <label>验证码</label>
+//             <input
+//               type="text"
+//               className="form-input"
+//               placeholder="请输入邮箱验证码"
+//               value={verificationCode}
+//               onChange={(e) => setVerificationCode(e.target.value)}
+//               required
+//             />
+//           </div>
+//           <button type="submit" className="auth-button">
+//             注册
+//           </button>
+//           <p className="login-link">
+//             已有账号? 
+//             <button onClick={onLoginClick} className="link-button">
+//               点击登录
+//             </button>
+//           </p>
+//         </form>
+//       </div>
+//     </div>
+//   );
+// };
 
-export default Register;
\ No newline at end of file
+// export default Register;
+
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg';
+
+// const API_BASE = process.env.REACT_APP_API_BASE || '/echo';
+
+// const Register = ({ onLoginClick }) => {
+//   const [formData, setFormData] = useState({
+//     username: '',
+//     email: '',
+//     password: '',
+//     role: 'user',
+//     inviteCode: ''
+//   });
+//   const [error, setError] = useState('');
+//   const [isSubmitting, setIsSubmitting] = useState(false);
+
+//   const handleSubmit = async (e) => {
+//     e.preventDefault();
+//     setIsSubmitting(true);
+//     setError('');
+
+//     try {
+//       const response = await fetch(`${API_BASE}/user/register`, {
+//         method: 'POST',
+//         headers: {
+//           'Content-Type': 'application/json',
+//         },
+//         body: JSON.stringify(formData),
+//       });
+
+//       const result = await response.json();
+      
+//       if (!response.ok) {
+//         throw new Error(result.message || '注册失败');
+//       }
+
+//       console.log('注册成功:', result);
+//       // 这里可以添加注册成功后的跳转逻辑
+//       alert('注册成功!');
+//     } catch (error) {
+//       console.error('注册错误:', error);
+//       setError(error.message || '注册过程中出现错误');
+//     } finally {
+//       setIsSubmitting(false);
+//     }
+//   };
+
+//   const handleChange = (e) => {
+//     const { name, value } = e.target;
+//     setFormData(prev => ({ ...prev, [name]: value }));
+//   };
+
+//   return (
+//     <div className="auth-container">
+//       <img
+//         src={image}
+//         alt="网站Logo"
+//         style={{ width: '30%', height: 'auto' }}
+//       />
+//       <div className="auth-form-section">
+//         <h3>用户注册</h3>
+//         {error && <div className="error-message">{error}</div>}
+//         <form onSubmit={handleSubmit}>
+//           <div className="form-group">
+//             <label>用户名</label>
+//             <input
+//               type="text"
+//               name="username"
+//               className="form-input"
+//               placeholder="请输入用户名"
+//               value={formData.username}
+//               onChange={handleChange}
+//               required
+//               minLength="3"
+//               maxLength="20"
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>邮箱</label>
+//             <input
+//               type="email"
+//               name="email"
+//               className="form-input"
+//               placeholder="请输入邮箱"
+//               value={formData.email}
+//               onChange={handleChange}
+//               required
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>密码</label>
+//             <input
+//               type="password"
+//               name="password"
+//               className="form-input"
+//               placeholder="请输入密码"
+//               value={formData.password}
+//               onChange={handleChange}
+//               required
+//               minLength="6"
+//             />
+//           </div>
+//           <div className="form-group">
+//             <label>邀请码</label>
+//             <input
+//               type="text"
+//               name="inviteCode"
+//               className="form-input"
+//               placeholder="请输入邀请码"
+//               value={formData.inviteCode}
+//               onChange={handleChange}
+//               required
+//             />
+//           </div>
+//           <button 
+//             type="submit" 
+//             className="auth-button"
+//             disabled={isSubmitting}
+//           >
+//             {isSubmitting ? '注册中...' : '注册'}
+//           </button>
+//           <p className="login-link">
+//             已有账号?{' '}
+//             <button 
+//               type="button"
+//               onClick={onLoginClick} 
+//               className="link-button"
+//             >
+//               点击登录
+//             </button>
+//           </p>
+//         </form>
+//       </div>
+//     </div>
+//   );
+// };
+
+// export default Register;
\ No newline at end of file
diff --git a/src/components/Auth/Register.test.jsx b/src/components/Auth/Register.test.jsx
deleted file mode 100644
index 969e464..0000000
--- a/src/components/Auth/Register.test.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import Register from './Register';
-
-describe('Register component', () => {
-  test('renders register form', () => {
-    const onLoginClick = jest.fn();
-    render(<Register onLoginClick={onLoginClick} />);
-
-    const usernameInput = screen.getByPlaceholderText('请输入用户名');
-    const passwordInput = screen.getByPlaceholderText('请输入密码');
-    const emailInput = screen.getByPlaceholderText('请输入邮箱');
-    const verifyButton = screen.getByText('验证邮箱');
-    const registerButton = screen.getByText('注册');
-
-    expect(usernameInput).toBeInTheDocument();
-    expect(passwordInput).toBeInTheDocument();
-    expect(emailInput).toBeInTheDocument();
-    expect(verifyButton).toBeInTheDocument();
-    expect(registerButton).toBeInTheDocument();
-  });
-
-  test('calls onLoginClick when "点击登录" is clicked', () => {
-    const onLoginClick = jest.fn();
-    render(<Register onLoginClick={onLoginClick} />);
-
-    const loginButton = screen.getByText('点击登录');
-    fireEvent.click(loginButton);
-
-    expect(onLoginClick).toHaveBeenCalled();
-  });
-});
\ No newline at end of file
diff --git a/src/components/Auth/Register.test.jsx.txt b/src/components/Auth/Register.test.jsx.txt
new file mode 100644
index 0000000..356fadd
--- /dev/null
+++ b/src/components/Auth/Register.test.jsx.txt
@@ -0,0 +1,32 @@
+// import React from 'react';
+// import { render, screen, fireEvent } from '@testing-library/react';
+// import Register from './Register';
+
+// describe('Register component', () => {
+//   test('renders register form', () => {
+//     const onLoginClick = jest.fn();
+//     render(<Register onLoginClick={onLoginClick} />);
+
+//     const usernameInput = screen.getByPlaceholderText('请输入用户名');
+//     const passwordInput = screen.getByPlaceholderText('请输入密码');
+//     const emailInput = screen.getByPlaceholderText('请输入邮箱');
+//     const verifyButton = screen.getByText('验证邮箱');
+//     const registerButton = screen.getByText('注册');
+
+//     expect(usernameInput).toBeInTheDocument();
+//     expect(passwordInput).toBeInTheDocument();
+//     expect(emailInput).toBeInTheDocument();
+//     expect(verifyButton).toBeInTheDocument();
+//     expect(registerButton).toBeInTheDocument();
+//   });
+
+//   test('calls onLoginClick when "点击登录" is clicked', () => {
+//     const onLoginClick = jest.fn();
+//     render(<Register onLoginClick={onLoginClick} />);
+
+//     const loginButton = screen.getByText('点击登录');
+//     fireEvent.click(loginButton);
+
+//     expect(onLoginClick).toHaveBeenCalled();
+//   });
+// });
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.css b/src/pages/AuthPage/AuthPage.css
index cb9e470..98e5532 100644
--- a/src/pages/AuthPage/AuthPage.css
+++ b/src/pages/AuthPage/AuthPage.css
@@ -1,11 +1,11 @@
-.auth-container {
+/* .auth-container {
   display: flex;
   align-items: center;
-  justify-content: flex-end; /* 使卡片靠右 */
+  justify-content: flex-end;
   min-height: 100vh;
   font-family: Arial, sans-serif;
-  background: linear-gradient(180deg, #5F4437, #823c3c);
-  padding: 0 2rem; /* 添加左右内边距 */
+  background: #333;
+  padding: 0 2rem;
 }
 
 .auth-container img {
@@ -13,13 +13,13 @@
 }
 
 .auth-form-section {
-  background: #E4D8C9; /* 米白色 */
+  background: #E4D8C9;
   padding: 2rem;
   border-radius: 10px;
   box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
   width: 300px;
   margin: 0 auto;
-  max-width: 400px; /* 限制卡片最大宽度 */
+  max-width: 400px;
 }
 
 .form-group {
@@ -32,7 +32,7 @@
   display: block;
   font-size: 0.9rem;
   margin-bottom: 0.5rem;
-  color: #4A3B34; /* 棕色 */
+  color: #4A3B34;
 }
 
 .form-input {
@@ -46,8 +46,8 @@
 
 .auth-button {
   padding: 0.8rem 8.4rem;
-  background: #BA929A; /* 粉色 */
-  color: #4A3B34; /* 棕色 */
+  background: #BA929A;
+  color: #4A3B34;
   border: none;
   border-radius: 5px;
   cursor: pointer;
@@ -56,21 +56,20 @@
 }
 
 .verify-button {
-  padding: 0.5rem 1rem; /* 更小的内边距 */
-  background: #BA929A; /* 粉色 */
-  color: #4A3B34; /* 棕色 */
+  padding: 0.5rem 1rem;
+  background: #BA929A;
+  color: #4A3B34;
   border: none;
   border-radius: 5px;
   cursor: pointer;
-  font-size: 0.8rem; /* 更小的字体 */
+  font-size: 0.8rem;
   display: inline-block;
 }
 
 .link-button {
   background: none;
   border: none;
-  color: #4A3B34; /* 棕色 */
-  /* text-decoration: underline; */
+  color: #4A3B34;
   cursor: pointer;
   font-size: 0.8rem;
   padding: 0;
@@ -78,19 +77,251 @@
 
 .forgot-password {
   position: absolute;
-  right: 10px; /* 让按钮靠右 */
-  bottom: 5px; /* 调整到底部 */
+  right: 10px;
+  bottom: 5px;
   font-size: 12px;
   background: none;
   border: none;
-  color: #4A3B34; /* 颜色与 "点击注册" 一致 */
+  color: #4A3B34;
   cursor: pointer;
   text-decoration: underline;
 }
 
-
 .register-link, .login-link {
   text-align: center;
   font-size: 0.8rem;
   margin-top: 1rem;
-}
\ No newline at end of file
+} */
+
+
+  .auth-container {
+  display: flex;
+  align-items: center;
+  justify-content: flex-end; /* 使卡片靠右 */
+  min-height: 100vh;
+  font-family: Arial, sans-serif;
+  background: #333; 
+  /* background: linear-gradient(180deg, #5F4437, #823c3c) */
+  padding: 0 2rem; /* 添加左右内边距 */
+}
+  
+  .auth-card {
+    width: 100%;
+    max-width: 480px;
+    background-color: #E4D8C9;
+    border-radius: 8px;
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+    overflow: hidden;
+  }
+  
+  .auth-header {
+    display: flex;
+    border-bottom: 1px solid #eee;
+  }
+  
+  .auth-tab {
+    flex: 1;
+    padding: 16px;
+    text-align: center;
+    font-size: 18px;
+    font-weight: 500;
+    cursor: pointer;
+    transition: all 0.3s ease;
+  }
+  
+  .auth-tab.active {
+    color: #BA929A;
+    border-bottom: 2px solid #BA929A;
+  }
+  
+  .auth-tab:not(.active) {
+    color: #888;
+  }
+  
+  .auth-tab:hover:not(.active) {
+    background-color: #f9f9f9;
+  }
+  
+  .auth-content {
+    padding: 30px;
+  }
+  
+  .auth-form {
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+  }
+  
+  .form-group {
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+  }
+  
+  .form-group label {
+    font-weight: 500;
+    color: #333;
+    text-align: left;
+    align-self: flex-start;
+  }
+  
+  .form-group input[type="text"],
+  .form-group input[type="email"],
+  .form-group input[type="password"] {
+    padding: 12px 16px;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    font-size: 16px;
+    transition: border-color 0.3s;
+  }
+  
+  .form-group input:focus {
+    border-color: #BA929A;
+    outline: none;
+  }
+  
+  .form-group-inline {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+  
+  .checkbox-container {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
+  
+  .checkbox-container input[type="checkbox"] {
+    width: 18px;
+    height: 18px;
+    cursor: pointer;
+  }
+  
+  .forgot-password {
+    color: #BA929A;
+    text-decoration: none;
+    font-size: 14px;
+  }
+  
+  .forgot-password:hover {
+    text-decoration: underline;
+  }
+  
+  .auth-button {
+    background-color: #BA929A;
+    color: white;
+    border: none;
+    border-radius: 4px;
+    padding: 14px;
+    font-size: 16px;
+    font-weight: 500;
+    cursor: pointer;
+    transition: background-color 0.3s;
+  }
+  
+  .auth-button:hover {
+    background-color: #BA929A;
+  }
+  
+  .social-login {
+    margin-top: 20px;
+    text-align: center;
+  }
+  
+  .social-login p {
+    color: #666;
+    margin-bottom: 15px;
+    position: relative;
+  }
+  
+  .social-login p::before,
+  .social-login p::after {
+    content: "";
+    position: absolute;
+    top: 50%;
+    width: 30%;
+    height: 1px;
+    background-color: #ddd;
+  }
+  
+  .social-login p::before {
+    left: 0;
+  }
+  
+  .social-login p::after {
+    right: 0;
+  }
+  
+  .social-icons {
+    display: flex;
+    justify-content: center;
+    gap: 20px;
+  }
+  
+  .social-icon {
+    width: 40px;
+    height: 40px;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: white;
+    font-size: 12px;
+    cursor: pointer;
+  }
+  
+  .social-icon.wechat {
+    background-color: #07c160;
+  }
+  
+  .social-icon.weibo {
+    background-color: #e6162d;
+  }
+  
+  .social-icon.qq {
+    background-color: #12b7f5;
+  }
+  
+  .terms-container {
+    flex-direction: column;
+    align-items: flex-start;
+  }
+  
+  .terms-link {
+    color: #BA929A;
+    text-decoration: none;
+  }
+  
+  .terms-link:hover {
+    text-decoration: underline;
+  }
+  
+  .error-message {
+    color: #e53e3e;
+    font-size: 14px;
+    margin-top: 4px;
+  }
+  
+  /* Responsive adjustments */
+  @media (max-width: 576px) {
+    .auth-card {
+      box-shadow: none;
+      border-radius: 0;
+    }
+  
+    .auth-content {
+      padding: 20px;
+    }
+  
+    .form-group-inline {
+      flex-direction: column;
+      align-items: flex-start;
+      gap: 10px;
+    }
+  
+    .social-icons {
+      flex-wrap: wrap;
+    }
+  }
+  
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.jsx b/src/pages/AuthPage/AuthPage.jsx
index 4238214..bfc8e43 100644
--- a/src/pages/AuthPage/AuthPage.jsx
+++ b/src/pages/AuthPage/AuthPage.jsx
@@ -1,19 +1,342 @@
-import React, { useState } from 'react';
-import Login from '../../components/Auth/Login';
-import Register from '../../components/Auth/Register';
+// import React, { useState } from 'react';
+// import Login from '../../components/Auth/Login';
+// import Register from '../../components/Auth/Register';
 
-const AuthPage = () => {
-  const [isRegister, setIsRegister] = useState(false);
+// const AuthPage = () => {
+//   const [isRegister, setIsRegister] = useState(false);
+
+//   return (
+//     <div>
+//       {isRegister ? (
+//         <Register onLoginClick={() => setIsRegister(false)} />
+//       ) : (
+//         <Login onRegisterClick={() => setIsRegister(true)} />
+//       )}
+//     </div>
+//   );
+// };
+
+// export default AuthPage;
+
+
+
+import { useState } from "react";
+import { Link } from "wouter";
+import "./AuthPage.css";
+import CryptoJS from "crypto-js";
+
+const API_BASE = process.env.REACT_APP_API_BASE;
+function AuthPage() {
+  const [activeTab, setActiveTab] = useState("login");
+
+  // Login form state
+  const [loginData, setLoginData] = useState({
+    username: "",
+    password: "",
+    rememberMe: false,
+  });
+
+  // Register form state
+  const [registerData, setRegisterData] = useState({
+    username: "",
+    email: "",
+    password: "",
+    confirmPassword: "",
+    inviteCode: "",
+    agreeTerms: false,
+  });
+
+  // Form errors
+  const [errors, setErrors] = useState({
+    login: {},
+    register: {},
+  });
+
+  const hashPassword = (password) => {
+    return CryptoJS.SHA256(password).toString(CryptoJS.enc.Hex);
+  };
+
+  // Handle login form submission
+  const handleLogin = async (e) => {
+    e.preventDefault();
+
+    // 客户端验证
+    const newErrors = {};
+    if (!loginData.username) {
+      newErrors.username = "请输入用户名或邮箱";
+    }
+    if (!loginData.password) {
+      newErrors.password = "请输入密码";
+    }
+
+    if (Object.keys(newErrors).length > 0) {
+      setErrors((prev) => ({ ...prev, login: newErrors }));
+      return;
+    }
+
+    // 加密密码
+    const hashedPassword = hashPassword(loginData.password);
+
+    try {
+      const response = await fetch(`${API_BASE}/echo/user/login`, {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          username: loginData.username,
+          password: hashedPassword,
+        }),
+      });
+
+      if (!response.ok) {
+        throw new Error('登录失败');
+      }
+
+      const data = await response.json();
+      
+      if (data.code !== 0 || !data.result) {
+        throw new Error(data.msg || '登录失败');
+      }
+
+      console.log('登录成功:', data);
+      localStorage.setItem('token', data.rows.token);
+      localStorage.setItem('userId', data.rows.userId);
+      window.location.href = '/';
+    } catch (error) {
+      console.error('登录错误:', error.message);
+      setErrors((prev) => ({
+        ...prev,
+        login: { message: error.message },
+      }));
+      throw error;
+    }
+  };
+
+  // Handle register form submission
+  const handleRegister = async (e) => {
+    e.preventDefault();
+
+    // 客户端验证
+    const newErrors = {};
+    if (!registerData.username) {
+      newErrors.username = "请输入用户名";
+    }
+    if (!registerData.email) {
+      newErrors.email = "请输入邮箱";
+    } else if (!/\S+@\S+\.\S+/.test(registerData.email)) {
+      newErrors.email = "邮箱格式不正确";
+    }
+    if (!registerData.password) {
+      newErrors.password = "请输入密码";
+    } else if (registerData.password.length < 6) {
+      newErrors.password = "密码长度至少为6位";
+    }
+    if (registerData.password !== registerData.confirmPassword) {
+      newErrors.confirmPassword = "两次输入的密码不一致";
+    }
+    if (!registerData.agreeTerms) {
+      newErrors.agreeTerms = "请同意用户协议和隐私政策";
+    }
+
+    if (Object.keys(newErrors).length > 0) {
+      setErrors({ ...errors, register: newErrors });
+      return;
+    }
+
+    // 加密密码
+    const hashedPassword = hashPassword(registerData.password);
+
+    try {
+      const response = await fetch(`${API_BASE}/echo/user/register`, {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          username: registerData.username,
+          email: registerData.email,
+          password: hashedPassword, 
+          inviteCode: registerData.inviteCode,
+        }),
+      });
+
+      if (!response.ok) {
+        throw new Error('注册失败');
+      }
+
+      const data = await response.json();
+      if (data.code !== 0 || !data.result) {
+        throw new Error(data.msg || '注册失败');
+      }
+
+      console.log('注册成功:', data);
+      setActiveTab('login');
+      alert('注册成功,请登录!');
+    } catch (error) {
+      console.error('注册错误:', error.message);
+      setErrors((prev) => ({
+        ...prev,
+        register: { message: error.message },
+      }));
+    }
+  };
+
+  // Update login form data
+  const updateLoginData = (field, value) => {
+    setLoginData({
+      ...loginData,
+      [field]: value,
+    });
+  };
+
+  // Update register form data
+  const updateRegisterData = (field, value) => {
+    setRegisterData({
+      ...registerData,
+      [field]: value,
+    });
+  };
 
   return (
-    <div>
-      {isRegister ? (
-        <Register onLoginClick={() => setIsRegister(false)} />
-      ) : (
-        <Login onRegisterClick={() => setIsRegister(true)} />
-      )}
+    <div className="auth-container">
+      <div className="auth-card">
+        <div className="auth-header">
+          <div className={`auth-tab ${activeTab === "login" ? "active" : ""}`} onClick={() => setActiveTab("login")}>
+            登录
+          </div>
+          <div className={`auth-tab ${activeTab === "register" ? "active" : ""}`} onClick={() => setActiveTab("register")}>
+            注册
+          </div>
+        </div>
+
+        <div className="auth-content">
+          {activeTab === "login" ? (
+            <form className="auth-form" onSubmit={handleLogin}>
+              {errors.login.message && <div className="error-message">{errors.login.message}</div>}
+              <div className="form-group">
+                <label htmlFor="login-username">用户名/邮箱</label>
+                <input
+                  type="text"
+                  id="login-username"
+                  value={loginData.username}
+                  onChange={(e) => updateLoginData("username", e.target.value)}
+                  placeholder="请输入用户名或邮箱"
+                  required
+                />
+                {errors.login.username && <div className="error-message">{errors.login.username}</div>}
+              </div>
+
+              <div className="form-group">
+                <label htmlFor="login-password">密码</label>
+                <input
+                  type="password"
+                  id="login-password"
+                  value={loginData.password}
+                  onChange={(e) => updateLoginData("password", e.target.value)}
+                  placeholder="请输入密码"
+                  required
+                />
+                {errors.login.password && <div className="error-message">{errors.login.password}</div>}
+              </div>
+
+              <div className="form-group-inline">
+                <div className="checkbox-container">
+                  <input
+                    type="checkbox"
+                    id="remember-me"
+                    checked={loginData.rememberMe}
+                    onChange={(e) => updateLoginData("rememberMe", e.target.checked)}
+                  />
+                  <label htmlFor="remember-me">记住我</label>
+                </div>
+                <Link to="/forgot-password" className="forgot-password">
+                  忘记密码?
+                </Link>
+              </div>
+
+              <button type="submit" className="auth-button">
+                登录
+              </button>
+            </form>
+          ) : (
+            <form className="auth-form" onSubmit={handleRegister}>
+              {errors.register.message && <div className="error-message">{errors.register.message}</div>}
+              <div className="form-group">
+                <label htmlFor="register-username">用户名</label>
+                <input
+                  type="text"
+                  id="register-username"
+                  value={registerData.username}
+                  onChange={(e) => updateRegisterData("username", e.target.value)}
+                  placeholder="请输入用户名"
+                  required
+                />
+                {errors.register.username && <div className="error-message">{errors.register.username}</div>}
+              </div>
+
+              <div className="form-group">
+                <label htmlFor="register-email">邮箱</label>
+                <input
+                  type="email"
+                  id="register-email"
+                  value={registerData.email}
+                  onChange={(e) => updateRegisterData("email", e.target.value)}
+                  placeholder="请输入邮箱"
+                  required
+                />
+                {errors.register.email && <div className="error-message">{errors.register.email}</div>}
+              </div>
+
+              <div className="form-group">
+                <label htmlFor="register-password">密码</label>
+                <input
+                  type="password"
+                  id="register-password"
+                  value={registerData.password}
+                  onChange={(e) => updateRegisterData("password", e.target.value)}
+                  placeholder="请输入密码"
+                  required
+                />
+                {errors.register.password && <div className="error-message">{errors.register.password}</div>}
+              </div>
+
+              <div className="form-group">
+                <label htmlFor="register-confirm-password">确认密码</label>
+                <input
+                  type="password"
+                  id="register-confirm-password"
+                  value={registerData.confirmPassword}
+                  onChange={(e) => updateRegisterData("confirmPassword", e.target.value)}
+                  placeholder="请再次输入密码"
+                  required
+                />
+                {errors.register.confirmPassword && (
+                  <div className="error-message">{errors.register.confirmPassword}</div>
+                )}
+              </div>
+
+              <div className="form-group">
+                <label htmlFor="register-inviteCode">邀请码</label>
+                <input
+                  type="text"
+                  id="register-inviteCode"
+                  value={registerData.inviteCode}
+                  onChange={(e) => updateRegisterData("inviteCode", e.target.value)}
+                  placeholder="请输入邀请码"
+                />
+                {errors.register.inviteCode && <div className="error-message">{errors.register.inviteCode}</div>}
+              </div>
+
+              <button type="submit" className="auth-button">
+                注册
+              </button>
+            </form>
+          )}
+        </div>
+      </div>
     </div>
   );
-};
+}
 
 export default AuthPage;
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.test.jsx b/src/pages/AuthPage/AuthPage.test.jsx
deleted file mode 100644
index e398536..0000000
--- a/src/pages/AuthPage/AuthPage.test.jsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import AuthPage from './AuthPage';
-
-describe('AuthPage component', () => {
-  test('switches between login and register forms', () => {
-    render(<AuthPage />);
-
-    const registerButton = screen.getByText('点击注册');
-    fireEvent.click(registerButton);
-
-    const usernameInput = screen.getByPlaceholderText('请输入用户名');
-    const passwordInput = screen.getByPlaceholderText('请输入密码');
-    const emailInput = screen.getByPlaceholderText('请输入邮箱');
-
-    expect(usernameInput).toBeInTheDocument();
-    expect(passwordInput).toBeInTheDocument();
-    expect(emailInput).toBeInTheDocument();
-
-    const loginButton = screen.getByText('点击登录');
-    fireEvent.click(loginButton);
-
-    const loginUsernameInput = screen.getByPlaceholderText('请输入用户名');
-    const loginPasswordInput = screen.getByPlaceholderText('请输入密码');
-    const loginSubmitButton = screen.getByText('登录');
-
-    expect(loginUsernameInput).toBeInTheDocument();
-    expect(loginPasswordInput).toBeInTheDocument();
-    expect(loginSubmitButton).toBeInTheDocument();
-  });
-});
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.test.jsx.txt b/src/pages/AuthPage/AuthPage.test.jsx.txt
new file mode 100644
index 0000000..a622c13
--- /dev/null
+++ b/src/pages/AuthPage/AuthPage.test.jsx.txt
@@ -0,0 +1,31 @@
+// import React from 'react';
+// import { render, screen, fireEvent } from '@testing-library/react';
+// import AuthPage from './AuthPage';
+
+// describe('AuthPage component', () => {
+//   test('switches between login and register forms', () => {
+//     render(<AuthPage />);
+
+//     const registerButton = screen.getByText('点击注册');
+//     fireEvent.click(registerButton);
+
+//     const usernameInput = screen.getByPlaceholderText('请输入用户名');
+//     const passwordInput = screen.getByPlaceholderText('请输入密码');
+//     const emailInput = screen.getByPlaceholderText('请输入邮箱');
+
+//     expect(usernameInput).toBeInTheDocument();
+//     expect(passwordInput).toBeInTheDocument();
+//     expect(emailInput).toBeInTheDocument();
+
+//     const loginButton = screen.getByText('点击登录');
+//     fireEvent.click(loginButton);
+
+//     const loginUsernameInput = screen.getByPlaceholderText('请输入用户名');
+//     const loginPasswordInput = screen.getByPlaceholderText('请输入密码');
+//     const loginSubmitButton = screen.getByText('登录');
+
+//     expect(loginUsernameInput).toBeInTheDocument();
+//     expect(loginPasswordInput).toBeInTheDocument();
+//     expect(loginSubmitButton).toBeInTheDocument();
+//   });
+// });
\ No newline at end of file
diff --git a/src/pages/Forum/posts-create/CreatePost.jsx b/src/pages/Forum/posts-create/CreatePost.jsx
index e38c29a..b8e8c2a 100644
--- a/src/pages/Forum/posts-create/CreatePost.jsx
+++ b/src/pages/Forum/posts-create/CreatePost.jsx
@@ -1,89 +1,78 @@
-// // src/pages/Forum/CreatePost.jsx
 // import React, { useState } from 'react';
 // import axios from 'axios';
+// import './CreatePost.css'; // 如果你打算加样式
 
 // const API_BASE = process.env.REACT_APP_API_BASE;
 
-// const CreatePost = ({ userId }) => {
+// const CreatePost = ({ user_id }) => {
 //   const [title, setTitle] = useState('');
 //   const [content, setContent] = useState('');
-//   const [imgUrl, setImageUrl] = useState('');
-//   const [isAnonymous, setIsAnonymous] = useState(false);
+//   const [imageUrl, setImageUrl] = useState('');
+//   const [message, setMessage] = useState('');
+//   const [error, setError] = useState('');
 
 //   const handleSubmit = async (e) => {
 //     e.preventDefault();
+//     setMessage('');
+//     setError('');
+
+//     if (!title.trim() || !content.trim()) {
+//       setError('标题和内容不能为空');
+//       return;
+//     }
 
 //     try {
-//       const postData = {
+//       const res = await axios.post(`${API_BASE}/echo/forum/posts/${user_id}/createPost`, {
 //         title,
-//         postContent: content,
-//         postType: isAnonymous,
-//       };
+//         post_content: content,
+//         image_url: imageUrl
+//       });
 
-//       if (imgUrl.trim()) {
-//         postData.imgUrl = imgUrl;
-//       }
-
-//       const response = await axios.post(
-//         `${API_BASE}/echo/forum/posts/${userId}/createPost`,
-//         postData
-//       );
-      
-
-//       if (response.status === 201) {
-//         alert('帖子创建成功!');
-//         setTitle('');
-//         setContent('');
-//         setImageUrl('');
-//         setIsAnonymous(false);
-//       }
-//     } catch (error) {
-//       console.error('帖子创建失败:', error.response?.data || error.message);
-//       alert('创建失败,请重试');
-//     }    
+//       setMessage(`发帖成功,帖子ID:${res.data.post_id}`);
+//       setTitle('');
+//       setContent('');
+//       setImageUrl('');
+//     } catch (err) {
+//       console.error(err);
+//       setError(err.response?.data?.error || '发帖失败,请稍后重试');
+//     }
 //   };
 
 //   return (
-//     <div className="create-post">
-//       <h2>创建新帖子</h2>
-//       <form onSubmit={handleSubmit}>
-//         <div>
+//     <div className="create-post-container">
+//       <h2>发表新帖子</h2>
+//       <form onSubmit={handleSubmit} className="create-post-form">
+//         <div className="form-group">
 //           <label>标题:</label>
 //           <input
 //             type="text"
 //             value={title}
 //             onChange={(e) => setTitle(e.target.value)}
-//             required
+//             placeholder="输入帖子标题"
 //           />
 //         </div>
-//         <div>
+//         <div className="form-group">
 //           <label>内容:</label>
 //           <textarea
 //             value={content}
 //             onChange={(e) => setContent(e.target.value)}
-//             required
+//             placeholder="输入帖子内容"
 //           />
 //         </div>
-//         <div>
-//           <label>图片 URL(可选):</label>
+//         <div className="form-group">
+//           <label>图片链接(可选):</label>
 //           <input
 //             type="text"
-//             value={imgUrl}
+//             value={imageUrl}
 //             onChange={(e) => setImageUrl(e.target.value)}
+//             placeholder="例如:https://example.com/img.jpg"
 //           />
 //         </div>
-//         <div>
-//           <label>
-//             <input
-//               type="checkbox"
-//               checked={isAnonymous}
-//               onChange={(e) => setIsAnonymous(e.target.checked)}
-//             />
-//             匿名发布
-//           </label>
-//         </div>
 //         <button type="submit">发布</button>
 //       </form>
+
+//       {message && <p className="success-text">{message}</p>}
+//       {error && <p className="error-text">{error}</p>}
 //     </div>
 //   );
 // };
@@ -96,7 +85,7 @@
 
 const API_BASE = process.env.REACT_APP_API_BASE;
 
-const CreatePost = ({ userId }) => {
+const CreatePost = ({ user_id }) => {
   const [title, setTitle] = useState('');
   const [content, setContent] = useState('');
   const [imageUrl, setImageUrl] = useState('');
@@ -114,7 +103,7 @@
     }
 
     try {
-      const res = await axios.post(`${API_BASE}/echo/forum/posts/${userId}/createPost`, {
+      const res = await axios.post(`${API_BASE}/echo/forum/posts/${user_id}/createPost`, {
         title,
         post_content: content,
         image_url: imageUrl
@@ -135,8 +124,10 @@
       <h2>发表新帖子</h2>
       <form onSubmit={handleSubmit} className="create-post-form">
         <div className="form-group">
-          <label>标题:</label>
+          {/* 这里加上htmlFor,并给input加id */}
+          <label htmlFor="title">标题:</label>
           <input
+            id="title"  // 加id
             type="text"
             value={title}
             onChange={(e) => setTitle(e.target.value)}
@@ -144,16 +135,20 @@
           />
         </div>
         <div className="form-group">
-          <label>内容:</label>
+          {/* 同理,内容 */}
+          <label htmlFor="content">内容:</label>
           <textarea
+            id="content"  // 加id
             value={content}
             onChange={(e) => setContent(e.target.value)}
             placeholder="输入帖子内容"
           />
         </div>
         <div className="form-group">
-          <label>图片链接(可选):</label>
+          {/* 图片链接 */}
+          <label htmlFor="imageUrl">图片链接(可选):</label>
           <input
+            id="imageUrl"  // 加id
             type="text"
             value={imageUrl}
             onChange={(e) => setImageUrl(e.target.value)}
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.css b/src/pages/Forum/posts-detail/PostDetailPage.css
index 780492b..570b65f 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.css
+++ b/src/pages/Forum/posts-detail/PostDetailPage.css
@@ -1,5 +1,5 @@
    .post-detail-page {
-    background: linear-gradient(180deg, #5F4437, #823c3c);
+    background: #333;
     font-family: 'Helvetica Neue', sans-serif;
     color: #333;
   }
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.jsx b/src/pages/Forum/posts-detail/PostDetailPage.jsx
index 01e1648..c58ed33 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.jsx
+++ b/src/pages/Forum/posts-detail/PostDetailPage.jsx
@@ -1,7 +1,288 @@
+// import React, { useEffect, useState } from 'react';
+// import { useParams } from 'wouter';
+// import { GoodTwo, Star } from '@icon-park/react';
+// import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost } from './api'; // 引入你的 API 函数
+// import './PostDetailPage.css';
+// import { useUser } from '../../../context/UserContext'; // 注意路径
+// import Header from '../../../components/Header';
+
+// const PostDetailPage = () => {
+//   const { postId } = useParams(); // 获取帖子ID
+//   const [postDetail, setPostDetail] = useState(null);
+//   const [comments, setComments] = useState([]);
+//   const [loading, setLoading] = useState(true);
+//   const [errorMsg, setErrorMsg] = useState('');
+//   const [newComment, setNewComment] = useState(''); // 新评论内容
+//   const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名
+//   const [isLiked, setIsLiked] = useState(false); // 是否已点赞
+//   const [isCollected, setIsCollected] = useState(false); // 是否已收藏
+//   const [replyToCommentId, setReplyToCommentId] = useState(null); // 回复的评论ID
+
+//   // 获取当前用户ID(假设从上下文中获取)
+//   const { user } = useUser(); // 你需要从用户上下文获取用户 ID
+
+//   useEffect(() => {
+//     const fetchPostDetail = async () => {
+//       setLoading(true);
+//       setErrorMsg('');
+//       try {
+//         // 获取帖子详情
+//         const postData = await getPostDetail(postId);
+//         setPostDetail(postData);
+
+//         // 获取帖子评论
+//         const commentsData = await getPostComments(postId);
+//         setComments(commentsData);
+
+//         // 设置是否已经点赞
+//         if (postData.likedByUser) {
+//           setIsLiked(true);
+//         } else {
+//           setIsLiked(false);
+//         }
+
+//         // 设置是否已经收藏
+//         if (postData.collectedByUser) {
+//           setIsCollected(true);
+//         } else {
+//           setIsCollected(false);
+//         }
+//       } catch (err) {
+//         console.error('加载失败:', err);
+//         setErrorMsg('加载失败,请稍后重试');
+//       } finally {
+//         setLoading(false);
+//       }
+//     };
+
+//     fetchPostDetail();
+//   }, [postId]);
+
+//   // 点赞功能
+//   const toggleLike = async () => {
+//     if (!user) {
+//       alert('请先登录');
+//       return;
+//     }
+
+//     try {
+//       if (isLiked) {
+//         // 取消点赞
+//         await unlikePost(postId, user.id);
+//         setIsLiked(false);
+//         setPostDetail((prev) => ({
+//           ...prev,
+//           postLikeNum: prev.postLikeNum - 1,
+//         }));
+//       } else {
+//         // 点赞
+//         await likePost(postId, user.id);
+//         setIsLiked(true);
+//         setPostDetail((prev) => ({
+//           ...prev,
+//           postLikeNum: prev.postLikeNum + 1,
+//         }));
+//       }
+//     } catch (err) {
+//       console.error('点赞失败:', err);
+//       alert('点赞失败,请稍后再试');
+//     }
+//   };
+
+//   // 收藏功能
+//   const toggleCollect = async () => {
+//     if (!user) {
+//       alert('请先登录');
+//       return;
+//     }
+
+//     try {
+//       const action = isCollected ? 'cancel' : 'collect';
+//       // 调用收藏 API
+//       await collectPost(postId, user.id, action);
+//       setIsCollected(!isCollected);
+//       setPostDetail((prev) => ({
+//         ...prev,
+//         postCollectNum: isCollected ? prev.postCollectNum - 1 : prev.postCollectNum + 1,
+//       }));
+//     } catch (err) {
+//       console.error('收藏失败:', err);
+//       alert('收藏失败,请稍后再试');
+//     }
+//   };
+
+//   // 添加评论
+//   const handleAddComment = async () => {
+//     if (!newComment.trim()) {
+//       alert('评论内容不能为空');
+//       return;
+//     }
+
+//     try {
+//       // 调用 API 添加评论,若为回复评论则传递父评论ID(com_comment_id)
+//       const commentData = await addCommentToPost(postId, user.id, newComment, isAnonymous, replyToCommentId);
+//       // 更新评论列表
+//       setComments((prev) => [
+//         ...prev,
+//         {
+//           commentId: commentData.commentId,
+//           post_id: postId,
+//           userId: user.id,
+//           content: newComment,
+//           isAnonymous,
+//           commentTime: new Date().toISOString(),
+//           comCommentId: replyToCommentId, // 回复评论时传递父评论ID
+//         },
+//       ]);
+//       // 清空评论框和回复状态
+//       setNewComment('');
+//       setReplyToCommentId(null);
+//     } catch (err) {
+//       console.error('评论添加失败:', err);
+//       alert('评论失败,请稍后再试');
+//     }
+//   };
+
+//   // 回复评论
+//   const handleReply = (commentId) => {
+//     setReplyToCommentId(commentId); // 设置父评论ID为当前评论的ID
+//   };
+
+//   return (
+//     <div className="post-detail-page">
+//       <Header />
+//       {loading ? (
+//         <p>加载中...</p>
+//       ) : errorMsg ? (
+//         <p className="error-text">{errorMsg}</p>
+//       ) : postDetail ? (
+//         <div className="post-detail">
+//           <h1>{postDetail.title}</h1>
+//           <div className="post-meta">
+//             <span className="post-user">用户ID: {postDetail.user_id}</span>
+//             <span className="post-time">
+//             发布时间:{new Date(postDetail.postTime).toLocaleString()}
+//             </span>
+//           </div>
+//           <div className="post-content">
+//             <p>{postDetail.postContent}</p>
+//             {Array.isArray(postDetail.imgUrl) ? (
+//               <div className="post-images">
+//                 {postDetail.imgUrl.map((url, idx) => (
+//                   <img key={idx} src={url} alt={`图片${idx}`} />
+//                 ))}
+//               </div>
+//             ) : (
+//               postDetail.imgUrl && (
+//                 <img className="post-image" src={postDetail.imgUrl} alt="帖子图片" />
+//               )
+//             )}
+
+//           </div>
+
+//           {/* 点赞和收藏 */}
+//           <div className="post-actions">
+//             <button
+//               className="icon-btn"
+//               onClick={toggleLike} // 点赞操作
+//             >
+//               <GoodTwo
+//                 theme="outline"
+//                 size="20"
+//                 fill={isLiked ? '#f00' : '#ccc'} // 如果已点赞,显示红色
+//               />
+//               <span>{postDetail.postLikeNum}</span>
+//             </button>
+//             <button
+//               className="icon-btn"
+//               onClick={toggleCollect} // 收藏操作
+//             >
+//               <Star
+//                 theme="outline"
+//                 size="20"
+//                 fill={isCollected ? '#ffd700' : '#ccc'} // 如果已收藏,显示金色
+//               />
+//               <span>{postDetail.postCollectNum}</span>
+//             </button>
+//           </div>
+          
+//           <hr className="divider" />
+//           {/* 评论部分 */}
+//           <h3>评论区</h3>
+//           <div className="comments-section">
+//             {comments.length ? (
+//               comments.map((comment) => (
+//                 <div key={comment.commentId} className="comment">
+//                   <div className="comment-header">
+//                     <span className="comment-user">用户 ID: {comment.userId}</span>
+//                     <button className="reply-btn" onClick={() => handleReply(comment.commentId)}>回复</button>
+//                   </div>
+//                   <p className="comment-content">{comment.content}</p>
+//                   <div className="comment-time">
+//                     {new Date(comment.commentTime).toLocaleString()}
+//                   </div>
+
+//                   {/* 回复框,只有在当前评论是正在回复的评论时显示 */}
+//                   {replyToCommentId === comment.commentId && (
+//                     <div className="reply-form">
+//                       <textarea
+//                         placeholder="输入你的回复..."
+//                         value={newComment}
+//                         onChange={(e) => setNewComment(e.target.value)}
+//                       />
+//                       <div className="comment-options">
+//                         <label>
+//                           <input
+//                             type="checkbox"
+//                             checked={isAnonymous}
+//                             onChange={() => setIsAnonymous(!isAnonymous)}
+//                           />
+//                           匿名评论
+//                         </label>
+//                         <button onClick={handleAddComment}>发布回复</button>
+//                       </div>
+//                     </div>
+//                   )}
+//                 </div>
+//               ))
+//             ) : (
+//               <p>暂无评论</p>
+//             )}
+
+//             {/* 添加评论表单 */}
+//             <div className="add-comment-form">
+//               <textarea
+//                 placeholder="输入你的评论..."
+//                 value={newComment}
+//                 onChange={(e) => setNewComment(e.target.value)}
+//               />
+//               <div className="comment-options">
+//                 <label>
+//                   <input
+//                     type="checkbox"
+//                     checked={isAnonymous}
+//                     onChange={() => setIsAnonymous(!isAnonymous)}
+//                   />
+//                   匿名评论
+//                 </label>
+//                 <button onClick={handleAddComment}>发布评论</button>
+//               </div>
+//             </div>
+//           </div>
+//         </div>
+//       ) : (
+//         <p>帖子不存在</p>
+//       )}
+//     </div>
+//   );
+// };
+
+// export default PostDetailPage;
+
 import React, { useEffect, useState } from 'react';
 import { useParams } from 'wouter';
 import { GoodTwo, Star } from '@icon-park/react';
-import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost } from './api'; // 引入你的 API 函数
+import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost, uncollectPost } from './api'; // 引入你的 API 函数
 import './PostDetailPage.css';
 import { useUser } from '../../../context/UserContext'; // 注意路径
 import Header from '../../../components/Header';
@@ -13,7 +294,7 @@
   const [loading, setLoading] = useState(true);
   const [errorMsg, setErrorMsg] = useState('');
   const [newComment, setNewComment] = useState(''); // 新评论内容
-  const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名
+  // const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名
   const [isLiked, setIsLiked] = useState(false); // 是否已点赞
   const [isCollected, setIsCollected] = useState(false); // 是否已收藏
   const [replyToCommentId, setReplyToCommentId] = useState(null); // 回复的评论ID
@@ -89,27 +370,36 @@
     }
   };
 
-  // 收藏功能
-  const toggleCollect = async () => {
+// 收藏功能
+const toggleCollect = async () => {
     if (!user) {
-      alert('请先登录');
-      return;
+        alert('请先登录');
+        return;
     }
 
     try {
-      const action = isCollected ? 'cancel' : 'collect';
-      // 调用收藏 API
-      await collectPost(postId, user.id, action);
-      setIsCollected(!isCollected);
-      setPostDetail((prev) => ({
-        ...prev,
-        postCollectNum: isCollected ? prev.postCollectNum - 1 : prev.postCollectNum + 1,
-      }));
+        if (isCollected) {
+            // 取消收藏 - 使用原有的collectPost函数,传递action: "cancel"
+            await collectPost(postId, user.id, "cancel");
+            setIsCollected(false);
+            setPostDetail((prev) => ({
+                ...prev,
+                postCollectNum: prev.postCollectNum - 1,
+            }));
+        } else {
+            // 收藏
+            await collectPost(postId, user.id, "collect");
+            setIsCollected(true);
+            setPostDetail((prev) => ({
+                ...prev,
+                postCollectNum: prev.postCollectNum + 1,
+            }));
+        }
     } catch (err) {
-      console.error('收藏失败:', err);
-      alert('收藏失败,请稍后再试');
+        console.error('收藏操作失败:', err);
+        alert('收藏操作失败,请稍后再试');
     }
-  };
+};
 
   // 添加评论
   const handleAddComment = async () => {
@@ -120,7 +410,7 @@
 
     try {
       // 调用 API 添加评论,若为回复评论则传递父评论ID(com_comment_id)
-      const commentData = await addCommentToPost(postId, user.id, newComment, isAnonymous, replyToCommentId);
+      const commentData = await addCommentToPost(postId, user.id, newComment, replyToCommentId);
       // 更新评论列表
       setComments((prev) => [
         ...prev,
@@ -129,7 +419,7 @@
           post_id: postId,
           userId: user.id,
           content: newComment,
-          isAnonymous,
+          // isAnonymous,
           commentTime: new Date().toISOString(),
           comCommentId: replyToCommentId, // 回复评论时传递父评论ID
         },
@@ -231,14 +521,14 @@
                         onChange={(e) => setNewComment(e.target.value)}
                       />
                       <div className="comment-options">
-                        <label>
-                          <input
-                            type="checkbox"
-                            checked={isAnonymous}
-                            onChange={() => setIsAnonymous(!isAnonymous)}
-                          />
-                          匿名评论
-                        </label>
+                        {/* <label> */}
+                          {/* <input */}
+                            {/* type="checkbox" */}
+                            {/* checked={isAnonymous} */}
+                            {/* onChange={() => setIsAnonymous(!isAnonymous)} */}
+                          {/* /> */}
+                          {/* 匿名评论 */}
+                        {/* </label> */}
                         <button onClick={handleAddComment}>发布回复</button>
                       </div>
                     </div>
@@ -257,14 +547,14 @@
                 onChange={(e) => setNewComment(e.target.value)}
               />
               <div className="comment-options">
-                <label>
+                {/* <label>
                   <input
                     type="checkbox"
                     checked={isAnonymous}
                     onChange={() => setIsAnonymous(!isAnonymous)}
                   />
                   匿名评论
-                </label>
+                </label> */}
                 <button onClick={handleAddComment}>发布评论</button>
               </div>
             </div>
@@ -277,4 +567,4 @@
   );
 };
 
-export default PostDetailPage;
+export default PostDetailPage;
\ No newline at end of file
diff --git a/src/pages/Forum/posts-detail/api.js b/src/pages/Forum/posts-detail/api.js
index d05f148..27c3a18 100644
--- a/src/pages/Forum/posts-detail/api.js
+++ b/src/pages/Forum/posts-detail/api.js
@@ -2,22 +2,23 @@
 
 const API_BASE = process.env.REACT_APP_API_BASE;
 
+
 // 获取帖子详情
-export const getPostDetail = async (postId) => {
-    const response = await axios.get(`${API_BASE}/echo/forum/posts/${postId}/getPost`);
+export const getPostDetail = async (post_id) => {
+    const response = await axios.get(`${API_BASE}/echo/forum/posts/${post_id}/getPost`);
     return response.data;
 };
 
 // 获取帖子评论
-export const getPostComments = async (postId) => {
-    const response = await axios.get(`${API_BASE}/echo/forum/posts/${postId}/getAllComments`);
+export const getPostComments = async (post_id) => {
+    const response = await axios.get(`${API_BASE}/echo/forum/posts/${post_id}/getAllComments`);
     return response.data;
 };
 
 // 点赞帖子
-export const likePost = async (postId, userId) => {
+export const likePost = async (post_id, userId) => {
     try {
-        const response = await axios.post(`${API_BASE}/echo/forum/posts/${postId}/like`, {
+        const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/like`, {
             user_id: userId,  // 用户 ID
         });
         return response.data;
@@ -27,15 +28,15 @@
 };
 
 // 取消点赞帖子
-export const unlikePost = async (postId) => {
-    const response = await axios.delete(`${API_BASE}/echo/forum/posts/${postId}/unlike`);
+export const unlikePost = async (post_id) => {
+    const response = await axios.delete(`${API_BASE}/echo/forum/posts/${post_id}/unlike`);
     return response.data;
 };
 
 // 添加评论
-export const addCommentToPost = async (postId, userId, content, isAnonymous, comCommentId = null) => {
+export const addCommentToPost = async (post_id, userId, content, isAnonymous, comCommentId = null) => {
     try {
-        const response = await axios.post(`${API_BASE}/echo/forum/posts/${postId}/comments`, {
+        const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/comments`, {
             content,
             user_id: userId,
             is_anonymous: isAnonymous,
@@ -60,9 +61,9 @@
 };
 
 // 收藏帖子
-export const collectPost = async (postId, userId, action) => {
+export const collectPost = async (post_id, userId, action) => {
     try {
-        const response = await axios.post(`${API_BASE}/echo/forum/posts/${postId}/collect`, {
+        const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/collect`, {
             user_id: userId,
             action: action,  // "collect" 或 "cancel"
         });
@@ -72,6 +73,14 @@
     }
 };
 
+// // 取消收藏帖子
+// export const uncollectPost = async (post_id, userId) => {
+//     const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/uncollect`, {
+//         user_id: userId,  // 用户 ID
+//     });
+//     return response.data;
+// };
+
 // 获取用户信息
 export const getUserInfo = async (userId) => {
     const response = await axios.get(`${API_BASE}/user/${userId}/info`);
diff --git a/src/pages/Forum/posts-main/ForumPage.css b/src/pages/Forum/posts-main/ForumPage.css
index 8a7ae4c..5fd64a2 100644
--- a/src/pages/Forum/posts-main/ForumPage.css
+++ b/src/pages/Forum/posts-main/ForumPage.css
@@ -2,7 +2,7 @@
     color: #fff;
     /* background-color: #5F4437; */
     /* background: linear-gradient(180deg, #5F4437, #9c737b); */
-    background: linear-gradient(180deg, #5F4437, #823c3c);
+    background: #333;
     /* background-color: #5F4437; */
     min-height: 100vh;
     font-family: Arial, sans-serif;
diff --git a/src/pages/Forum/posts-main/components/CreatePostButton.jsx b/src/pages/Forum/posts-main/components/CreatePostButton.jsx
index 0390ee7..4f7d7b1 100644
--- a/src/pages/Forum/posts-main/components/CreatePostButton.jsx
+++ b/src/pages/Forum/posts-main/components/CreatePostButton.jsx
@@ -4,7 +4,7 @@
 import './CreatePostButton.css';
 
 const API_BASE = process.env.REACT_APP_API_BASE;
-const USER_ID = 456;
+const user_id = 456;
 
 const CreatePostButton = () => {
   const [showModal, setShowModal] = useState(false);
@@ -49,7 +49,7 @@
 
     try {
       await axios.post(
-        `${API_BASE}/echo/forum/posts/${USER_ID}/createPost`,
+        `${API_BASE}/echo/forum/posts/${user_id}/createPost`,
         {
           title: title.trim(),
           post_content: content.trim(),
diff --git a/src/pages/Forum/posts-main/components/PostList.jsx b/src/pages/Forum/posts-main/components/PostList.jsx
index 3eba6f8..707ff15 100644
--- a/src/pages/Forum/posts-main/components/PostList.jsx
+++ b/src/pages/Forum/posts-main/components/PostList.jsx
@@ -1,175 +1,8 @@
-// import React, { useEffect, useState } from 'react';
-// import axios from 'axios';
-// import { Link } from 'wouter';
-// import { GoodTwo, Comment, Star } from '@icon-park/react';
-// import { likePost, unlikePost, collectPost } from '../../posts-detail/api'; 
-// import './PostList.css';
-
-// const API_BASE = process.env.REACT_APP_API_BASE;
-
-// const PostList = ({ search }) => {
-//   const [posts, setPosts] = useState([]);
-//   const [page, setPage] = useState(1);
-//   const [total, setTotal] = useState(0);
-//   const [loading, setLoading] = useState(true);
-//   const [errorMsg, setErrorMsg] = useState('');
-
-//   const size = 10;  // 每页条数
-//   const totalPages = Math.ceil(total / size);
-
-//   useEffect(() => {
-//     const fetchPosts = async () => {
-//       setLoading(true);
-//       setErrorMsg('');
-//       try {
-//         const res = await axios.get(`${API_BASE}/echo/forum/posts`, {
-//           params: { 
-//             page: page,
-//             pageSize: size,
-//             sortBy: 'createdAt',  // 按时间排序
-//             order: 'desc'         // 按降序排序
-//           }
-//         });
-
-//         const postsData = res.data.posts || [];
-//         const userIds = [...new Set(postsData.map(p => p.user_id))];
-
-//         // 获取用户信息
-//         const profiles = await Promise.all(userIds.map(async id => {
-//           try {
-//             const r = await axios.get(`${API_BASE}/echo/user/profile`, {
-//               params: { user_id: id }
-//             });
-//             return { id, profile: r.data };
-//           } catch {
-//             return { id, profile: { nickname: '未知用户', avatar_url: 'default-avatar.png' } };
-//           }
-//         }));
-
-//         const userMap = {};
-//         profiles.forEach(({ id, profile }) => { userMap[id] = profile; });
-
-//         // 更新帖子数据
-//         const postsWithProfiles = postsData
-//           .filter(post => post.title.includes(search))
-//           .map(post => ({
-//             ...post,
-//             userProfile: userMap[post.user_id] || {}
-//           }));
-
-//         setPosts(postsWithProfiles);
-//         setTotal(res.data.total || 0);
-//       } catch (err) {
-//         console.error('加载失败:', err);
-//         setErrorMsg('加载失败,请稍后重试');
-//       } finally {
-//         setLoading(false);
-//       }
-//     };
-
-//     fetchPosts();
-//   }, [page, search]);
-
-//   // 点赞/取消点赞操作
-//   const toggleLike = async (postId, liked, userId) => {
-//     try {
-//       if (liked) {
-//         await unlikePost(postId);  // 取消点赞
-//       } else {
-//         await likePost(postId, userId);  // 点赞
-//       }
-
-//       setPosts(posts =>
-//         posts.map(post =>
-//           post.id === postId
-//             ? { ...post, liked: !liked, likeCount: liked ? post.likeCount - 1 : post.likeCount + 1 }
-//             : post
-//         )
-//       );
-//     } catch (err) {
-//       console.error('点赞失败:', err);
-//     }
-//   };
-
-//   // 收藏/取消收藏操作
-//   const toggleCollect = async (postId, collected, userId) => {
-//     try {
-//       const action = collected ? 'cancel' : 'collect';
-//       await collectPost(postId, userId, action);
-
-//       setPosts(posts =>
-//         posts.map(post =>
-//           post.id === postId
-//             ? { ...post, collected: !collected, collectCount: collected ? post.collectCount - 1 : post.collectCount + 1 }
-//             : post
-//         )
-//       );
-//     } catch (err) {
-//       console.error('收藏失败:', err);
-//     }
-//   };
-
-//   return (
-//     <div className="post-list">
-//       {loading ? <p>加载中...</p> :
-//         errorMsg ? <p className="error-text">{errorMsg}</p> :
-//           posts.length === 0 ? <p>暂无帖子。</p> :
-//             posts.map(post => (
-//               <Link
-//                 key={post.id}
-//                 href={`/forum/post/${post.id}`}
-//                 className="post-card"
-//                 style={{ backgroundColor: '#e9ded2' }}
-//               >
-//                 <div className="user-info">
-//                   <img className="avatar" src={post.userProfile.avatar_url} alt="头像" />
-//                   <span className="nickname" style={{ color: '#755e50' }}>{post.userProfile.nickname}</span>
-//                 </div>
-//                 {post.cover_image_url && (
-//                   <img className="cover-image" src={post.cover_image_url} alt="封面" />
-//                 )}
-//                 <h3 style={{ color: '#000000' }}>{post.title}</h3>
-//                 <div className="post-meta">
-//                   <span>发布时间:{new Date(post.createdAt).toLocaleString()}</span>
-//                   <div className="post-actions">
-//                     {/* 点赞按钮 */}
-//                     <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleLike(post.id, post.liked, post.user_id); }}>
-//                       <GoodTwo theme="outline" size="24" fill={post.liked ? '#f00' : '#fff'} />
-//                       <span>{post.likeCount}</span>
-//                     </button>
-  
-//                     {/* 收藏按钮 */}
-//                     <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleCollect(post.id, post.collected, post.user_id); }}>
-//                       <Star theme="outline" size="24" fill={post.collected ? '#ffd700' : '#fff'} />
-//                       <span>{post.collectCount}</span>
-//                     </button>
-  
-//                     <Link href={`/forum/post/${post.id}`} className="icon-btn" onClick={(e) => e.stopPropagation()}>
-//                       <Comment theme="outline" size="24" fill="#fff" />
-//                       <span>{post.commentCount}</span>
-//                     </Link>
-//                   </div>
-//                 </div>
-//               </Link>
-//             ))
-//       }
-  
-//       <div className="pagination">
-//         <button disabled={page === 1} onClick={() => setPage(page - 1)}>上一页</button>
-//         <span>第 {page} 页 / 共 {totalPages} 页</span>
-//         <button disabled={page === totalPages} onClick={() => setPage(page + 1)}>下一页</button>
-//       </div>
-//     </div>
-//   );
-// };
-
-// export default PostList;
-
 import React, { useEffect, useState } from 'react';
 import axios from 'axios';
 import { Link } from 'wouter';
-import { GoodTwo, Comment, Star } from '@icon-park/react';
-import { likePost, unlikePost, collectPost } from '../../posts-detail/api';
+import { GoodTwo, Comment, Star, Delete } from '@icon-park/react';
+import { likePost, unlikePost } from '../../posts-detail/api';
 import './PostList.css';
 
 const API_BASE = process.env.REACT_APP_API_BASE;
@@ -200,10 +33,8 @@
 
         const postsData = res.data.posts || [];
 
-        // 收集所有 user_id
         const userIds = [...new Set(postsData.map(post => post.user_id))];
 
-        // 批量请求用户资料
         const profiles = await Promise.all(userIds.map(async id => {
           try {
             const r = await axios.get(`${API_BASE}/echo/user/profile`, {
@@ -215,13 +46,11 @@
           }
         }));
 
-        // 创建 user_id -> profile 映射
         const userMap = {};
         profiles.forEach(({ id, profile }) => {
           userMap[id] = profile;
         });
 
-        // 过滤并补充 profile
         const postsWithProfiles = postsData
           .filter(post => post.title.toLowerCase().includes(search.toLowerCase()))
           .map(post => ({
@@ -265,10 +94,20 @@
     }
   };
 
+  // 收藏帖子
   const toggleCollect = async (postId, collected, userId) => {
     try {
-      const action = collected ? 'cancel' : 'collect';
-      await collectPost(postId, userId, action);
+      if (collected) {
+        // 取消收藏
+        await axios.get(`${API_BASE}/echo/forum/posts/${postId}/uncollect`, {
+          data: { user_id: userId }
+        });
+      } else {
+        // 收藏帖子
+        await axios.post(`${API_BASE}/echo/forum/posts/${postId}/collect`, {
+          user_id: userId
+        });
+      }
 
       setPosts(posts =>
         posts.map(post =>
@@ -278,7 +117,27 @@
         )
       );
     } catch (err) {
-      console.error('收藏失败:', err);
+      console.error('收藏操作失败:', err);
+    }
+  };
+
+  // 删除帖子
+  const handleDeletePost = async (postId) => {
+    if (window.confirm('确定要删除这篇帖子吗?')) {
+      try {
+        await axios.delete(`${API_BASE}/echo/forum/posts/${postId}/deletePost`);
+        
+        // 从列表中移除已删除的帖子
+        setPosts(posts => posts.filter(post => post.postNo !== postId));
+        
+        // 如果删除后当前页没有帖子了,尝试加载上一页
+        if (posts.length === 1 && page > 1) {
+          setPage(page - 1);
+        }
+      } catch (err) {
+        console.error('删除帖子失败:', err);
+        alert('删除帖子失败,请稍后再试');
+      }
     }
   };
 
@@ -288,9 +147,8 @@
         errorMsg ? <p className="error-text">{errorMsg}</p> :
           posts.length === 0 ? <p>暂无帖子。</p> :
             posts.map(post => (
-              <Link
+              <div
                 key={post.postNo}
-                href={`/forum/post/${post.postNo}`}
                 className="post-card"
                 style={{ backgroundColor: '#e9ded2' }}
               >
@@ -305,23 +163,30 @@
                 <div className="post-meta">
                   <span>发布时间:{new Date(post.createdAt).toLocaleString()}</span>
                   <div className="post-actions">
-                    <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleLike(post.postNo, post.liked, post.user_id); }}>
+                    <button className="icon-btn" onClick={() => toggleLike(post.postNo, post.liked, post.user_id)}>
                       <GoodTwo theme="outline" size="24" fill={post.liked ? '#f00' : '#fff'} />
                       <span>{post.likeCount}</span>
                     </button>
 
-                    <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleCollect(post.postNo, post.collected, post.user_id); }}>
+                    <button className="icon-btn" onClick={() => toggleCollect(post.postNo, post.collected, post.user_id)}>
                       <Star theme="outline" size="24" fill={post.collected ? '#ffd700' : '#fff'} />
                       <span>{post.collectCount}</span>
                     </button>
 
-                    <Link href={`/forum/post/${post.postNo}`} className="icon-btn" onClick={(e) => e.stopPropagation()}>
+                    <div className="icon-btn">
                       <Comment theme="outline" size="24" fill="#fff" />
                       <span>{post.commentCount}</span>
-                    </Link>
+                    </div>
+                    
+                    <button className="icon-btn" onClick={() => handleDeletePost(post.postNo)}>
+                      <Delete theme="outline" size="24" fill="#333" />
+                    </button>
                   </div>
                 </div>
-              </Link>
+                <div className="detail-button-wrapper">
+                  <Link href={`/forum/post/${post.postNo}`} className="detail-button">查看详情</Link>
+                </div>
+              </div>
             ))
       }
 
@@ -334,4 +199,4 @@
   );
 };
 
-export default PostList;
+export default PostList;
\ No newline at end of file
diff --git a/src/pages/FriendMoments/FriendMoments.css b/src/pages/FriendMoments/FriendMoments.css
index a69d919..1059f10 100644
--- a/src/pages/FriendMoments/FriendMoments.css
+++ b/src/pages/FriendMoments/FriendMoments.css
@@ -1,6 +1,6 @@
 .friend-moments-container {
   margin: 0 auto;
-  background: linear-gradient(180deg, #5F4437, #823c3c);
+  background: #333;
   padding-bottom: 40px;
 }
 
diff --git a/src/pages/InterestGroup/InterestGroup.css b/src/pages/InterestGroup/InterestGroup.css
index 35d3c4d..91b21da 100644
--- a/src/pages/InterestGroup/InterestGroup.css
+++ b/src/pages/InterestGroup/InterestGroup.css
@@ -1,6 +1,6 @@
 /* 设置整个兴趣小组页面的背景色和布局 */
 .interest-group-container {
-  background: linear-gradient(180deg, #5F4437, #823c3c);
+  background: #333;
   width: 100%;
   height: 2000px;
 }
diff --git a/src/pages/PromotionsPage/PromotionsPage.css b/src/pages/PromotionsPage/PromotionsPage.css
new file mode 100644
index 0000000..6752c69
--- /dev/null
+++ b/src/pages/PromotionsPage/PromotionsPage.css
@@ -0,0 +1,206 @@
+.promotions-page {
+    padding: 20px;
+    font-family: Arial, sans-serif;
+}
+
+.promotions-container {
+    max-width: 1200px;
+    margin: 0 auto;
+    background-color: #fff;
+    border-radius: 8px;
+    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+    padding: 20px;
+}
+
+h1, h2, h3 {
+    color: #333;
+}
+
+.admin-actions {
+    margin-bottom: 20px;
+}
+
+.create-button, .submit-button, .delete-button {
+    background-color: #4CAF50;
+    color: white;
+    border: none;
+    padding: 10px 15px;
+    border-radius: 4px;
+    cursor: pointer;
+    font-size: 14px;
+    transition: background-color 0.3s;
+}
+
+.create-button:hover, .submit-button:hover {
+    background-color: #45a049;
+}
+
+.delete-button {
+    background-color: #f44336;
+    margin-top: 10px;
+}
+
+.delete-button:hover {
+    background-color: #d32f2f;
+}
+
+.create-promotion-form {
+    background-color: #f9f9f9;
+    padding: 20px;
+    border-radius: 8px;
+    margin-bottom: 20px;
+}
+
+.form-group {
+    margin-bottom: 15px;
+}
+
+.form-row {
+    display: flex;
+    gap: 20px;
+}
+
+.form-row .form-group {
+    flex: 1;
+}
+
+label {
+    display: block;
+    margin-bottom: 5px;
+    font-weight: bold;
+}
+
+input, select {
+    width: 100%;
+    padding: 8px;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    box-sizing: border-box;
+}
+
+.error-message {
+    color: #f44336;
+    margin-bottom: 15px;
+    padding: 10px;
+    background-color: #ffebee;
+    border-radius: 4px;
+}
+
+.promotions-grid {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    gap: 20px;
+}
+
+.promotions-list {
+    border-right: 1px solid #eee;
+    padding-right: 20px;
+}
+
+.promotion-items {
+    max-height: 600px;
+    overflow-y: auto;
+}
+
+.promotion-item {
+    background-color: #f9f9f9;
+    padding: 15px;
+    border-radius: 8px;
+    margin-bottom: 15px;
+    cursor: pointer;
+    transition: background-color 0.3s;
+}
+
+.promotion-item:hover {
+    background-color: #f0f0f0;
+}
+
+.promotion-item.active {
+    background-color: #e3f2fd;
+    border-left: 4px solid #2196F3;
+}
+
+.promotion-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 10px;
+}
+
+.promotion-type {
+    background-color: #2196F3;
+    color: white;
+    padding: 3px 8px;
+    border-radius: 12px;
+    font-size: 12px;
+}
+
+.promotion-dates {
+    color: #666;
+    font-size: 14px;
+    margin-bottom: 10px;
+}
+
+.promotion-coeffs {
+    display: flex;
+    gap: 15px;
+    font-weight: bold;
+}
+
+.promotion-coeffs span {
+    background-color: #e3f2fd;
+    padding: 3px 8px;
+    border-radius: 4px;
+}
+
+.promotion-details {
+    padding: 0 20px;
+}
+
+.detail-item {
+    margin-bottom: 15px;
+}
+
+.detail-item label {
+    font-weight: bold;
+    color: #555;
+}
+
+.detail-item span {
+    display: block;
+    margin-top: 5px;
+    padding: 8px;
+    background-color: #f5f5f5;
+    border-radius: 4px;
+}
+
+.no-promotions, .no-selection, .loading {
+    text-align: center;
+    padding: 40px;
+    color: #888;
+}
+
+.pagination {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    gap: 15px;
+    margin-top: 20px;
+}
+
+.pagination button {
+    padding: 5px 10px;
+    background-color: #f0f0f0;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    cursor: pointer;
+}
+
+.pagination button:disabled {
+    opacity: 0.5;
+    cursor: not-allowed;
+}
+
+.pagination span {
+    font-size: 14px;
+}
\ No newline at end of file
diff --git a/src/pages/PromotionsPage/PromotionsPage.jsx b/src/pages/PromotionsPage/PromotionsPage.jsx
new file mode 100644
index 0000000..bb50d72
--- /dev/null
+++ b/src/pages/PromotionsPage/PromotionsPage.jsx
@@ -0,0 +1,435 @@
+import React, { useState, useEffect } from 'react';
+import './PromotionsPage.css';
+
+const API_BASE = process.env.REACT_APP_API_BASE;
+function PromotionsPage() {
+  const [promotions, setPromotions] = useState([]);
+  const [currentPromotion, setCurrentPromotion] = useState(null);
+  const [isAdmin, setIsAdmin] = useState(false);
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState(null);
+  const [formData, setFormData] = useState({
+    name: '',
+    uploadCoeff: 1,
+    downloadCoeff: 1,
+    timeRange: 0,
+    criteria: 1,
+    pStartTime: '',
+    pEndTime: ''
+  });
+  const [isCreating, setIsCreating] = useState(false);
+  const [currentPage, setCurrentPage] = useState(1);
+  const [perPage] = useState(10);
+  const [totalPromotions, setTotalPromotions] = useState(0);
+
+  const getAuthHeaders = () => {
+    const token = localStorage.getItem('token');
+    return {
+      'Authorization': token ? `Bearer ${token}` : '',
+      'Content-Type': 'application/json'
+    };
+  };
+
+  const fetchPromotions = async (page = 1) => {
+    setIsLoading(true);
+    try {
+      const response = await fetch(`${API_BASE}/promotions/list?page=${page}&per_page=${perPage}`, {
+        headers: getAuthHeaders()
+      });
+
+      if (!response.ok) {
+        throw new Error('获取促销活动失败');
+      }
+
+      const data = await response.json();
+      if (data.code === 0 && data.result) {
+        setPromotions(data.rows || []);
+        setTotalPromotions(data.total || 0);
+      } else {
+        throw new Error(data.msg || '获取促销活动失败');
+      }
+    } catch (err) {
+      console.error('获取促销活动错误:', err);
+      setError(err.message);
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  const fetchPromotionDetails = async (promoId) => {
+    setIsLoading(true);
+    try {
+      const response = await fetch(`${API_BASE}/promotions/${promoId}`, {
+        headers: getAuthHeaders()
+      });
+
+      if (!response.ok) {
+        throw new Error('获取促销详情失败');
+      }
+
+      const data = await response.json();
+      if (data.code === 0 && data.result) {
+        setCurrentPromotion(data.rows);
+      } else {
+        throw new Error(data.msg || '获取促销详情失败');
+      }
+    } catch (err) {
+      console.error('获取促销详情错误:', err);
+      setError(err.message);
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  const createPromotion = async () => {
+    if (!formData.name || !formData.pStartTime || !formData.pEndTime) {
+      alert('请填写完整活动信息');
+      return;
+    }
+
+    if (new Date(formData.pStartTime) >= new Date(formData.pEndTime)) {
+      alert('活动时间设置不正确,请重新设定');
+      return;
+    }
+
+    setIsLoading(true);
+    try {
+      const response = await fetch('${API_BASE}/promotions/add', {
+        method: 'POST',
+        headers: getAuthHeaders(),
+        body: JSON.stringify(formData)
+      });
+
+      if (!response.ok) {
+        throw new Error('创建促销活动失败');
+      }
+
+      const data = await response.json();
+      if (data.code === 0 && data.result) {
+        alert(`活动创建成功!活动ID: ${data.msg}`);
+        setIsCreating(false);
+        setFormData({
+          name: '',
+          uploadCoeff: 1,
+          downloadCoeff: 1,
+          timeRange: 0,
+          criteria: 1,
+          pStartTime: '',
+          pEndTime: ''
+        });
+        fetchPromotions();
+      } else {
+        throw new Error(data.msg || '创建促销活动失败');
+      }
+    } catch (err) {
+      console.error('创建促销活动错误:', err);
+      alert(err.message);
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  const deletePromotion = async (promoId) => {
+    if (!window.confirm('确定要删除这个促销活动吗?')) {
+      return;
+    }
+
+    setIsLoading(true);
+    try {
+      const response = await fetch(`${API_BASE}/promotions/delete/${promoId}`, {
+        method: 'DELETE',
+        headers: getAuthHeaders()
+      });
+
+      if (!response.ok) {
+        throw new Error('删除促销活动失败');
+      }
+
+      const data = await response.json();
+      if (data.code === 0 && data.result) {
+        alert('促销活动删除成功');
+        fetchPromotions();
+        if (currentPromotion && currentPromotion.promoId === promoId) {
+          setCurrentPromotion(null);
+        }
+      } else {
+        throw new Error(data.msg || '删除促销活动失败');
+      }
+    } catch (err) {
+      console.error('删除促销活动错误:', err);
+      alert(err.message);
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  const checkAdminStatus = () => {
+    const role = localStorage.getItem('role');
+    setIsAdmin(role === 'admin');
+  };
+
+  useEffect(() => {
+    checkAdminStatus();
+    fetchPromotions();
+  }, []);
+
+  const handleInputChange = (e) => {
+    const { name, value } = e.target;
+    setFormData(prev => ({
+      ...prev,
+      [name]: name === 'uploadCoeff' || name === 'downloadCoeff' || name === 'timeRange' || name === 'criteria'
+          ? parseFloat(value)
+          : value
+    }));
+  };
+
+  const handlePageChange = (newPage) => {
+    setCurrentPage(newPage);
+    fetchPromotions(newPage);
+  };
+
+  const getPromotionType = (promo) => {
+    if (promo.downloadCoeff === 0 && promo.uploadCoeff > 1) {
+      return '免费';
+    } else if (promo.downloadCoeff < 1 && promo.uploadCoeff > 1) {
+      return '折扣+上传奖励';
+    } else if (promo.downloadCoeff < 1) {
+      return '折扣';
+    } else if (promo.uploadCoeff > 1) {
+      return '上传奖励';
+    }
+    return '普通';
+  };
+
+  return (
+      <div className="promotions-page">
+        <div className="promotions-container">
+          <h1>促销活动</h1>
+
+          {isAdmin && (
+              <div className="admin-actions">
+                <button
+                    className="create-button"
+                    onClick={() => setIsCreating(!isCreating)}
+                >
+                  {isCreating ? '取消创建' : '创建新活动'}
+                </button>
+              </div>
+          )}
+
+          {isCreating && isAdmin && (
+              <div className="create-promotion-form">
+                <h2>创建新促销活动</h2>
+                <div className="form-group">
+                  <label>活动名称</label>
+                  <input
+                      type="text"
+                      name="name"
+                      value={formData.name}
+                      onChange={handleInputChange}
+                      placeholder="例如: 春节特惠"
+                  />
+                </div>
+
+                <div className="form-row">
+                  <div className="form-group">
+                    <label>上传量系数</label>
+                    <input
+                        type="number"
+                        name="uploadCoeff"
+                        min="0"
+                        step="0.1"
+                        value={formData.uploadCoeff}
+                        onChange={handleInputChange}
+                    />
+                  </div>
+
+                  <div className="form-group">
+                    <label>下载量系数</label>
+                    <input
+                        type="number"
+                        name="downloadCoeff"
+                        min="0"
+                        step="0.1"
+                        value={formData.downloadCoeff}
+                        onChange={handleInputChange}
+                    />
+                  </div>
+                </div>
+
+                <div className="form-row">
+                  <div className="form-group">
+                    <label>资源时间范围</label>
+                    <select
+                        name="timeRange"
+                        value={formData.timeRange}
+                        onChange={handleInputChange}
+                    >
+                      <option value="0">全站资源</option>
+                      <option value="1">当天上传</option>
+                      <option value="2">最近两天</option>
+                      <option value="7">最近一周</option>
+                      <option value="30">最近一个月</option>
+                    </select>
+                  </div>
+
+                  <div className="form-group">
+                    <label>最低用户等级</label>
+                    <input
+                        type="number"
+                        name="criteria"
+                        min="1"
+                        value={formData.criteria}
+                        onChange={handleInputChange}
+                    />
+                  </div>
+                </div>
+
+                <div className="form-row">
+                  <div className="form-group">
+                    <label>开始时间</label>
+                    <input
+                        type="datetime-local"
+                        name="pStartTime"
+                        value={formData.pStartTime}
+                        onChange={handleInputChange}
+                    />
+                  </div>
+
+                  <div className="form-group">
+                    <label>结束时间</label>
+                    <input
+                        type="datetime-local"
+                        name="pEndTime"
+                        value={formData.pEndTime}
+                        onChange={handleInputChange}
+                    />
+                  </div>
+                </div>
+
+                <button
+                    className="submit-button"
+                    onClick={createPromotion}
+                    disabled={isLoading}
+                >
+                  {isLoading ? '创建中...' : '提交创建'}
+                </button>
+              </div>
+          )}
+
+          {error && <div className="error-message">{error}</div>}
+
+          <div className="promotions-grid">
+            {/* 促销活动列表 */}
+            <div className="promotions-list">
+              <h2>当前促销活动</h2>
+              {isLoading && promotions.length === 0 ? (
+                  <div className="loading">加载中...</div>
+              ) : promotions.length === 0 ? (
+                  <div className="no-promotions">暂无促销活动</div>
+              ) : (
+                  <div className="promotion-items">
+                    {promotions.map(promo => (
+                        <div
+                            key={promo.promoId}
+                            className={`promotion-item ${currentPromotion && currentPromotion.promoId === promo.promoId ? 'active' : ''}`}
+                            onClick={() => fetchPromotionDetails(promo.promoId)}
+                        >
+                          <div className="promotion-header">
+                            <h3>{promo.name}</h3>
+                            <span className="promotion-type">{getPromotionType(promo)}</span>
+                          </div>
+                          <div className="promotion-dates">
+                            {new Date(promo.pStartTime).toLocaleString()} - {new Date(promo.pEndTime).toLocaleString()}
+                          </div>
+                          <div className="promotion-coeffs">
+                            <span>上传: {promo.uploadCoeff}x</span>
+                            <span>下载: {promo.downloadCoeff}x</span>
+                          </div>
+                          {isAdmin && (
+                              <button
+                                  className="delete-button"
+                                  onClick={(e) => {
+                                    e.stopPropagation();
+                                    deletePromotion(promo.promoId);
+                                  }}
+                                  disabled={isLoading}
+                              >
+                                删除
+                              </button>
+                          )}
+                        </div>
+                    ))}
+                  </div>
+              )}
+
+              {totalPromotions > perPage && (
+                  <div className="pagination">
+                    <button
+                        disabled={currentPage === 1}
+                        onClick={() => handlePageChange(currentPage - 1)}
+                    >
+                      上一页
+                    </button>
+                    <span>第 {currentPage} 页</span>
+                    <button
+                        disabled={currentPage * perPage >= totalPromotions}
+                        onClick={() => handlePageChange(currentPage + 1)}
+                    >
+                      下一页
+                    </button>
+                  </div>
+              )}
+            </div>
+
+            {/* 促销活动详情 */}
+            <div className="promotion-details">
+              {currentPromotion ? (
+                  <>
+                    <h2>{currentPromotion.name}</h2>
+                    <div className="detail-item">
+                      <label>活动ID:</label>
+                      <span>{currentPromotion.promoId}</span>
+                    </div>
+                    <div className="detail-item">
+                      <label>活动时间:</label>
+                      <span>
+                    {new Date(currentPromotion.pStartTime).toLocaleString()} - {new Date(currentPromotion.pEndTime).toLocaleString()}
+                  </span>
+                    </div>
+                    <div className="detail-item">
+                      <label>促销类型:</label>
+                      <span>{getPromotionType(currentPromotion)}</span>
+                    </div>
+                    <div className="detail-item">
+                      <label>上传量系数:</label>
+                      <span>{currentPromotion.uploadCoeff}x</span>
+                    </div>
+                    <div className="detail-item">
+                      <label>下载量系数:</label>
+                      <span>{currentPromotion.downloadCoeff}x</span>
+                    </div>
+                    <div className="detail-item">
+                      <label>适用资源:</label>
+                      <span>
+                    {currentPromotion.timeRange === 0
+                        ? '全站资源'
+                        : `最近${currentPromotion.timeRange}天内上传的资源`}
+                  </span>
+                    </div>
+                    <div className="detail-item">
+                      <label>参与条件:</label>
+                      <span>用户等级 ≥ {currentPromotion.criteria}</span>
+                    </div>
+                  </>
+              ) : (
+                  <div className="no-selection">请从左侧选择一个促销活动查看详情</div>
+              )}
+            </div>
+          </div>
+        </div>
+      </div>
+  );
+}
+
+export default PromotionsPage;
\ No newline at end of file
diff --git a/src/pages/PublishSeed/PublishSeed.css b/src/pages/PublishSeed/PublishSeed.css
index 1cc4804..3c53352 100644
--- a/src/pages/PublishSeed/PublishSeed.css
+++ b/src/pages/PublishSeed/PublishSeed.css
@@ -70,7 +70,7 @@
 }
 
 .publish-seed-container {
-  background: linear-gradient(180deg, #5F4437, #823c3c);
+  background: #333;
   color: white;
   border-radius: 12px;
   box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.css b/src/pages/SeedList/SeedDetail/SeedDetail.css
index 641a4be..594cb8e 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.css
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.css
@@ -1,5 +1,5 @@
 .seed-detail-page {
-  background: linear-gradient(180deg, #5F4437, #823c3c);
+  background: #333;
   font-family: 'Helvetica Neue', sans-serif;
   color: #333;
 }
diff --git a/src/pages/SeedList/SeedList.css b/src/pages/SeedList/SeedList.css
index aff93c3..f53a9a3 100644
--- a/src/pages/SeedList/SeedList.css
+++ b/src/pages/SeedList/SeedList.css
@@ -1,6 +1,6 @@
       
       .seed-list-container {
-        background: linear-gradient(180deg, #5F4437, #823c3c);
+        background: #333;
       }
       
       /* 搜索、排序控件 */
diff --git a/src/pages/UserCenter/UserProfile.css b/src/pages/UserCenter/UserProfile.css
index bcb1a2d..b63c408 100644
--- a/src/pages/UserCenter/UserProfile.css
+++ b/src/pages/UserCenter/UserProfile.css
@@ -4,7 +4,7 @@
   font-family: Arial, sans-serif;
   display: flex;
   gap: 10%;
-  background: linear-gradient(180deg, #5F4437, #823c3c);
+  background: #333;
 }