邀请码、端口修改
Change-Id: Idc325c5f970ade6c750cd09d3d3c32b803dd17e3
diff --git a/src/pages/AuthPage/AuthPage.css b/src/pages/AuthPage/AuthPage.css
index 98e5532..6e8b965 100644
--- a/src/pages/AuthPage/AuthPage.css
+++ b/src/pages/AuthPage/AuthPage.css
@@ -1,109 +1,27 @@
-/* .auth-container {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- min-height: 100vh;
- font-family: Arial, sans-serif;
- background: #333;
- padding: 0 2rem;
-}
-
-.auth-container img {
- margin-left: 250px;
-}
-
-.auth-form-section {
- 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;
-}
-
-.form-group {
- margin-bottom: 1.2rem;
- display: flex;
- flex-direction: column;
-}
-
-label {
- display: block;
- font-size: 0.9rem;
- margin-bottom: 0.5rem;
- color: #4A3B34;
-}
-
-.form-input {
- width: 100%;
- padding: 0.8rem;
- border: 1px solid #ddd;
- border-radius: 5px;
- font-size: 0.9rem;
- box-sizing: border-box;
-}
-
-.auth-button {
- padding: 0.8rem 8.4rem;
- background: #BA929A;
- color: #4A3B34;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- font-size: 0.9rem;
- display: inline-block;
-}
-
-.verify-button {
- padding: 0.5rem 1rem;
- background: #BA929A;
- color: #4A3B34;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- font-size: 0.8rem;
- display: inline-block;
-}
-
-.link-button {
- background: none;
- border: none;
- color: #4A3B34;
- cursor: pointer;
- font-size: 0.8rem;
- padding: 0;
-}
-
-.forgot-password {
- position: absolute;
- right: 10px;
- bottom: 5px;
- font-size: 12px;
- background: none;
- border: none;
- color: #4A3B34;
- cursor: pointer;
- text-decoration: underline;
-}
-
-.register-link, .login-link {
- text-align: center;
- font-size: 0.8rem;
- margin-top: 1rem;
-} */
-
-
.auth-container {
display: flex;
align-items: center;
- justify-content: flex-end; /* 使卡片靠右 */
+ /* justify-content: flex-end; */
+ justify-content: space-between;
min-height: 100vh;
font-family: Arial, sans-serif;
- background: #333;
+ background: #5F4437;
/* background: linear-gradient(180deg, #5F4437, #823c3c) */
padding: 0 2rem; /* 添加左右内边距 */
}
+
+ .logo-container {
+ flex: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 2rem;
+ }
+
+ .site-logo {
+ width: 300px; /* 设置固定宽度 */
+ height: auto; /* 高度自适应,保持比例 */
+ }
.auth-card {
width: 100%;
diff --git a/src/pages/AuthPage/AuthPage.jsx b/src/pages/AuthPage/AuthPage.jsx
index e7f8f52..fe1b42b 100644
--- a/src/pages/AuthPage/AuthPage.jsx
+++ b/src/pages/AuthPage/AuthPage.jsx
@@ -1,8 +1,7 @@
import { useState } from "react";
import { Link } from "wouter";
import "./AuthPage.css";
-import CryptoJS from "crypto-js";
-
+import logo from '../../assets/logo.png';
function AuthPage() {
const [activeTab, setActiveTab] = useState("login");
@@ -29,17 +28,13 @@
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 = "请输入用户名或邮箱";
+ newErrors.username = "请输入用户名";
}
if (!loginData.password) {
newErrors.password = "请输入密码";
@@ -109,8 +104,6 @@
return;
}
- const hashedPassword = hashPassword(registerData.password);
-
try {
const response = await fetch("/echo/user/register", {
method: 'POST',
@@ -120,8 +113,8 @@
body: JSON.stringify({
username: registerData.username,
email: registerData.email,
- password: hashedPassword,
- role: "user", // 默认角色,可根据实际情况调整
+ password: registerData.password, // 原始密码
+ role: "user",
inviteCode: registerData.inviteCode,
}),
});
@@ -144,6 +137,7 @@
};
+
// Update login form data
const updateLoginData = (field, value) => {
setLoginData({
@@ -162,6 +156,10 @@
return (
<div className="auth-container">
+ <div className="logo-container">
+ <img src={logo} alt="Logo" className="site-logo" />
+ </div>
+
<div className="auth-card">
<div className="auth-header">
<div className={`auth-tab ${activeTab === "login" ? "active" : ""}`} onClick={() => setActiveTab("login")}>
@@ -178,13 +176,13 @@
<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>
+ <label htmlFor="login-username">用户名</label>
<input
type="text"
id="login-username"
value={loginData.username}
onChange={(e) => updateLoginData("username", e.target.value)}
- placeholder="请输入用户名或邮箱"
+ placeholder="请输入用户名"
required
/>
{errors.login.username && <div className="error-message">{errors.login.username}</div>}
@@ -205,13 +203,13 @@
<div className="form-group-inline">
<div className="checkbox-container">
- <input
+ {/* <input
type="checkbox"
id="remember-me"
checked={loginData.rememberMe}
onChange={(e) => updateLoginData("rememberMe", e.target.checked)}
- />
- <label htmlFor="remember-me">记住我</label>
+ /> */}
+ {/* <label htmlFor="remember-me">记住我</label> */}
</div>
<Link to="/forgot-password" className="forgot-password">
忘记密码?
diff --git a/src/pages/UserCenter/UserInvite.css b/src/pages/UserCenter/UserInvite.css
new file mode 100644
index 0000000..8250e0b
--- /dev/null
+++ b/src/pages/UserCenter/UserInvite.css
@@ -0,0 +1,36 @@
+.user-invite-container {
+ padding: 24px;
+ background: #fff;
+ border-radius: 12px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+ max-width: 500px;
+ margin: 0 auto;
+ text-align: center;
+}
+
+.invite-button {
+ padding: 10px 20px;
+ background-color: #4a90e2;
+ color: white;
+ font-size: 16px;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ margin-top: 12px;
+}
+
+.invite-button:disabled {
+ background-color: #cccccc;
+ cursor: not-allowed;
+}
+
+.invite-code {
+ margin-top: 20px;
+ font-size: 18px;
+ color: #333;
+}
+
+.invite-code span {
+ font-weight: bold;
+ color: #4a90e2;
+}
diff --git a/src/pages/UserCenter/UserInvite.jsx b/src/pages/UserCenter/UserInvite.jsx
new file mode 100644
index 0000000..aa6e559
--- /dev/null
+++ b/src/pages/UserCenter/UserInvite.jsx
@@ -0,0 +1,98 @@
+// import React, { useState } from 'react';
+// import './UserInvite.css';
+// import axios from 'axios';
+// import { useUser } from '../../context/UserContext'; // 根据实际路径调整
+
+// const UserInvite = () => {
+// const { user } = useUser();
+// const [inviteCode, setInviteCode] = useState('');
+// const [loading, setLoading] = useState(false);
+
+// const handleGenerateInvite = async () => {
+// if (!user?.userId) {
+// alert('未获取到用户信息,无法生成邀请码');
+// return;
+// }
+
+// setLoading(true);
+// try {
+// const response = await axios.get('/echo/user/getInviteCode', {
+// params: { user_id: user.userId },
+// });
+// setInviteCode(response.data.invite_code);
+// } catch (error) {
+// console.error('生成邀请码失败:', error);
+// alert('生成邀请码失败,请稍后再试');
+// }
+// setLoading(false);
+// };
+
+// return (
+// <div className="user-invite-container">
+// <h2>邀请新用户</h2>
+// <button className="invite-button" onClick={handleGenerateInvite} disabled={loading}>
+// {loading ? '生成中...' : '生成邀请码'}
+// </button>
+// {inviteCode && (
+// <div className="invite-code">
+// 邀请码:<span>{inviteCode}</span>
+// </div>
+// )}
+// </div>
+// );
+// };
+
+// export default UserInvite;
+
+import React, { useState } from 'react';
+import './UserInvite.css';
+import axios from 'axios';
+import { useUser } from '../../context/UserContext';
+
+const UserInvite = () => {
+ const { user } = useUser();
+ const [inviteCode, setInviteCode] = useState('');
+ const [loading, setLoading] = useState(false);
+
+ const handleGenerateInvite = async () => {
+ if (!user?.userId) {
+ alert('未获取到用户信息,无法生成邀请码');
+ return;
+ }
+
+ setLoading(true);
+ try {
+ const response = await axios.post('/echo/user/getInviteCode', {
+ user_id: user.userId,
+ });
+
+ const data = response.data;
+
+ if (data.status === 'success') {
+ setInviteCode(data.invite_code);
+ } else {
+ alert(`生成失败:${data.message}`);
+ }
+ } catch (error) {
+ console.error('生成邀请码失败:', error);
+ alert('生成邀请码失败,请稍后再试');
+ }
+ setLoading(false);
+ };
+
+ return (
+ <div className="user-invite-container">
+ <h2>邀请新用户</h2>
+ <button className="invite-button" onClick={handleGenerateInvite} disabled={loading}>
+ {loading ? '生成中...' : '生成邀请码'}
+ </button>
+ {inviteCode && (
+ <div className="invite-code">
+ 邀请码:<span>{inviteCode}</span>
+ </div>
+ )}
+ </div>
+ );
+};
+
+export default UserInvite;
diff --git a/src/pages/UserCenter/UserNav.jsx b/src/pages/UserCenter/UserNav.jsx
index cc343b1..64dd375 100644
--- a/src/pages/UserCenter/UserNav.jsx
+++ b/src/pages/UserCenter/UserNav.jsx
@@ -13,6 +13,7 @@
{ to: '/user/groups', label: '我的群组' },
{ to: '/user/collections', label: '我的收藏' },
{ to: '/user/newbie-tasks', label: '新手考核' },
+ { to: '/user/invite', label: '邀请新用户' },
];
// 判断路径是否是当前活动页面
@@ -36,37 +37,3 @@
};
export default UserNav;
-
-// import React from 'react';
-// import './UserNav.css';
-
-// const UserNav = ({ activeKey, onSelect }) => {
-// const navLinks = [
-// { key: 'profile', label: '个人资料' },
-// // { key: 'dynamics', label: '我的动态' },
-// // { key: 'friends', label: '我的好友' },
-// // { key: 'groups', label: '我的群组' },
-// // { key: 'collections', label: '我的收藏' },
-// { key: 'newbieTasks', label: '新手考核' },
-// ];
-
-// return (
-// <div className="user-nav-container">
-// <nav className="user-nav">
-// {navLinks.map(({ key, label }) => (
-// <div
-// key={key}
-// className={`user-nav-item ${activeKey === key ? 'active' : ''}`}
-// onClick={() => onSelect(key)}
-// style={{ cursor: 'pointer' }}
-// >
-// {label}
-// </div>
-// ))}
-// </nav>
-// </div>
-// );
-// };
-
-// export default UserNav;
-