Commit 4481f62d authored by nanahira's avatar nanahira

add vaptcha

parents 2c3bc432 cd0209ef
Pipeline #28198 passed with stages
in 1 minute and 54 seconds
{ {
"en-US": { "en-US": {
"title":"MoeCube", "title": "MoeCube",
"Home":"Home", "Home": "Home",
"BBS":"BBS", "BBS": "BBS",
"DATABASE":"DataBase", "DATABASE": "DataBase",
"username": "User Name", "username": "User Name",
"email": "E-Mail", "email": "E-Mail",
"password": "Password", "password": "Password",
"user-info": "User Info", "user-info": "User Info",
"reset-info": "Reset User Info", "reset-info": "Reset User Info",
"Change-Avatar" :"Change Avatar", "Change-Avatar": "Change Avatar",
"upload":"upload", "Upload-Avatar": "Confirm Upload Avatar",
"Reselect-Avatar": "Reselect Avatar",
"upload": "upload",
"avatar": "Avatar", "avatar": "Avatar",
"nickname": "Nickname", "nickname": "Nickname",
"Nickname-Hint": "This nickname is only used in the forum.",
"reset-account-info": "Reset Account info", "reset-account-info": "Reset Account info",
"current_password": "Current Password", "current_password": "Current Password",
"password-again": "Input Password Again", "password-again": "Input Password Again",
...@@ -25,20 +28,20 @@ ...@@ -25,20 +28,20 @@
"sign-up": "Sign Up", "sign-up": "Sign Up",
"sign-in": "Sign In", "sign-in": "Sign In",
"sign-out": "Sign out", "sign-out": "Sign out",
"User-Center":"User Center", "User-Center": "User Center",
"Please-sign-in":"Please sign In", "Please-sign-in": "Please sign In",
"email-address-or-username": "E-Mail or Username", "email-address-or-username": "E-Mail or Username",
"register-now": "register-now!", "register-now": "register-now!",
"register":"register", "register": "register",
"forgot-password": "Forgot Password", "forgot-password": "Forgot Password",
"send-email": "Send Email", "send-email": "Send Email",
"reset-success": "reset success", "reset-success": "reset success",
"reset-fail": "reset fail", "reset-fail": "reset fail",
"reset-password2": "Reset Password", "reset-password2": "Reset Password",
"remember-me":"Remember me", "remember-me": "Remember me",
"Please-use-a-correct-E-Mail-address.": "Please use a correct E-Mail address.", "Please-use-a-correct-E-Mail-address.": "Please use a correct E-Mail address.",
"User-name-can-not-be-empty.": "User name can not be empty.", "User-name-can-not-be-empty.": "User name can not be empty.",
"You-can-not-use-this-username.": "You can not use this username.", "You-can-not-use-this-username.": "Username cannot contain special characters or space.",
"You-can-use-this-password.": "You can use this password.", "You-can-use-this-password.": "You can use this password.",
"Password-is-correct.": "Password is correct.", "Password-is-correct.": "Password is correct.",
"Incorrect-password.2": "Incorrect password.", "Incorrect-password.2": "Incorrect password.",
...@@ -58,54 +61,58 @@ ...@@ -58,54 +61,58 @@
"didnt receive verification email 2": "to resend it again.", "didnt receive verification email 2": "to resend it again.",
"A verification email has been sent to you.": "A verification email has been sent to you, please check your email to finish verification.", "A verification email has been sent to you.": "A verification email has been sent to you, please check your email to finish verification.",
"Your email has been updated.": "Your email has been updated. You will receive an verification email. Please check the mail to finish verification. ", "Your email has been updated.": "Your email has been updated. You will receive an verification email. Please check the mail to finish verification. ",
"Please input your account!": "Please input your email or username!",
"Please input your account!":"Please input your email or username!", "Please-input-your-Password!": "Please input your Password!",
"Please-input-your-Password!":"Please input your Password!", "verify-email": "Verify Email",
"account-info": "Account Info",
"verify-email":"Verify Email", "reset-username": "Reset Username",
"account-info":"Account Info", "Reset-Email": "Reset Email",
"reset-username":"Reset Username", "reset-password": "Reset Password",
"Reset-Email":"Reset Email", "old-password": "old password",
"reset-password":"Reset Password", "new-password": "new password",
"old-password":"old password", "Password-length-must-be-between-8-and-24-characters.": "Password length must be between 8 and 24 characters.",
"new-password":"new password", "email_exists": "email exists",
"Password-length-must-be-between-8-and-24-characters.":"Password length must be between 8 and 24 characters.",
"email_exists":"email exists",
"update_success": "Update Success!", "update_success": "Update Success!",
"A-verification-email-has-been-sent-to-you,please-check-the-mail-to-complete.":"A verification email has been sent to you, please check the mail to complete.", "A-verification-email-has-been-sent-to-you,please-check-the-mail-to-complete.": "A verification email has been sent to you, please check the mail to complete.",
"Your-are-almost-done!": "Your are almost done!",
"Your-are-almost-done!":"Your are almost done!", "Thank-you!-This-is-the-last-step.": "Thank you! This is the last step.",
"Thank-you!-This-is-the-last-step.":"Thank you! This is the last step.", "Please click the following button to confirm your email address": "Please click the following button to confirm your email address",
"Please click the following button to confirm your email address":"Please click the following button to confirm your email address", "Finish-Verification": "Finish Verification",
"Finish-Verification":"Finish Verification", "After-verification,-you-can-sign-in-to-MoeCube-with-this-email-address.": "After verification, you can sign in to MoeCube with this email address.",
"After-verification,-you-can-sign-in-to-MoeCube-with-this-email-address.":"After verification, you can sign in to MoeCube with this email address.", "Welcome-to-MoeCube!": "Welcome to MoeCube!",
"Welcome-to-MoeCube!":"Welcome to MoeCube!",
"i_password_error": "Incorrect password. ", "i_password_error": "Incorrect password. ",
"i_user_unexists":"User does not exisit.", "i_user_unexists": "User does not exisit.",
"i_email_exists":"email is exists", "i_email_exists": "email is exists",
"i_username_exists":"username is exists", "i_username_exists": "username is exists",
"i_not_found":"user unexists", "i_username_exists_or_invalid": "username is exists or invalid",
"i_key_time_out":"url is time out", "i_not_found": "user unexists",
"i_key_invalid":"url is invalid", "i_key_time_out": "url is time out",
"i_key_invalid": "url is invalid",
"没毛用":"防逗号报错,上线删" "LogoutNow": "Logout now",
"LoggingOutIn": "Logging out in",
"Seconds": "seconds",
"TemporaryPrompt": "You can change your username on the first week of Jan, Apr, Jul, Oct.",
"ChangeSuccess": "Change successful, please logout to apply the change.",
"EmailChangeSuccess":"Please check the email to continue.",
"没毛用": "防逗号报错,上线删"
}, },
"zh-CN": { "zh-CN": {
"title":"萌立方", "title": "萌立方",
"Home":"主页", "Home": "主页",
"BBS":"社区", "BBS": "社区",
"DATABASE":"数据库", "DATABASE": "数据库",
"username": "用户名", "username": "用户名",
"email": "邮箱", "email": "邮箱",
"password": "密码", "password": "密码",
"user-info": "用户信息", "user-info": "用户信息",
"reset-info": "修改信息", "reset-info": "修改信息",
"Change-Avatar" :"修改头像", "Change-Avatar": "修改头像",
"upload":"上传", "Upload-Avatar": "确认上传头像",
"Reselect-Avatar": "重新选择头像",
"upload": "上传",
"avatar": "头像", "avatar": "头像",
"nickname": "昵称", "nickname": "昵称",
"Nickname-Hint": "昵称只在论坛显示,如需修改游戏和聊天室里显示的名字,请修改用户名",
"reset-account-info": "修改账户信息", "reset-account-info": "修改账户信息",
"current_password": "原密码", "current_password": "原密码",
"password-again": "再次输入密码", "password-again": "再次输入密码",
...@@ -118,20 +125,20 @@ ...@@ -118,20 +125,20 @@
"sign-up": "注册", "sign-up": "注册",
"sign-in": "登录", "sign-in": "登录",
"sign-out": "登出", "sign-out": "登出",
"User-Center":"用户中心", "User-Center": "用户中心",
"Please-sign-in":"您尚未登录,请先登录", "Please-sign-in": "您尚未登录,请先登录",
"email-address-or-username": "邮箱或用户名", "email-address-or-username": "邮箱或用户名",
"register-now": "现在注册", "register-now": "现在注册",
"register":"注册", "register": "注册",
"forgot-password": "忘记密码", "forgot-password": "忘记密码",
"send-email": "发送邮件", "send-email": "发送邮件",
"reset-success": "修改成功。请重新登录MC平台使更改生效,否则有可能无法进入游戏", "reset-success": "修改成功。请重新登录MC平台使更改生效,否则有可能无法进入游戏",
"reset-fail": "修改失败", "reset-fail": "修改失败",
"reset-password2": "重置密码", "reset-password2": "重置密码",
"remember-me":"记住我", "remember-me": "记住我",
"Please-use-a-correct-E-Mail-address.": "请填写正确的邮箱地址", "Please-use-a-correct-E-Mail-address.": "请填写正确的邮箱地址",
"User-name-can-not-be-empty.": "用户名不能为空", "User-name-can-not-be-empty.": "用户名不能为空",
"You-can-not-use-this-username.": "用户名不合法", "You-can-not-use-this-username.": "用户名不能带标点符号或空格",
"You-can-use-this-password.": "密码可以使用", "You-can-use-this-password.": "密码可以使用",
"Password-is-correct.": "密码一致", "Password-is-correct.": "密码一致",
"Incorrect-password.2": "密码不一致", "Incorrect-password.2": "密码不一致",
...@@ -153,39 +160,39 @@ ...@@ -153,39 +160,39 @@
"didnt receive verification email 2": "获取验证邮件。", "didnt receive verification email 2": "获取验证邮件。",
"A verification email has been sent to you.": "已经向您发送了一封验证邮件,请您查看Email完成验证。", "A verification email has been sent to you.": "已经向您发送了一封验证邮件,请您查看Email完成验证。",
"Your email has been updated.": "邮箱已经更新,您将会收到一封验证邮件,请您查看Email完成验证。", "Your email has been updated.": "邮箱已经更新,您将会收到一封验证邮件,请您查看Email完成验证。",
"Please input your account!": "请填写你的邮箱或用户名!",
"Please input your account!":"请填写你的邮箱或用户名!", "Please-input-your-Password!": "请填写你的密码!",
"Please-input-your-Password!":"请填写你的密码!", "verify-email": "验证邮箱",
"account-info": "账户信息",
"verify-email":"验证邮箱", "reset-username": "修改用户名",
"account-info":"账户信息", "Reset-Email": "修改邮箱",
"reset-username":"修改用户名", "reset-password": "修改密码",
"Reset-Email":"修改邮箱", "old-password": "原密码",
"reset-password":"修改密码", "new-password": "新密码",
"old-password":"原密码", "Password-length-must-be-between-8-and-24-characters.": "密码必须为8-24位",
"new-password":"新密码", "email_exists": "邮箱已存在",
"Password-length-must-be-between-8-and-24-characters.":"密码必须为8-24位",
"email_exists":"邮箱已存在",
"update_success": "修改成功。请重新登录MC平台使更改生效,否则有可能无法进入游戏", "update_success": "修改成功。请重新登录MC平台使更改生效,否则有可能无法进入游戏",
"A-verification-email-has-been-sent-to-you,please-check-the-mail-to-complete.":"一封验证邮件已经发送给您,请查看邮件完成修改。", "A-verification-email-has-been-sent-to-you,please-check-the-mail-to-complete.": "一封验证邮件已经发送给您,请查看邮件完成修改。",
"Your-are-almost-done!": "即将完成邮箱验证",
"Your-are-almost-done!":"即将完成邮箱验证", "Thank-you!-This-is-the-last-step.": "恭喜,这是最后一步啦。",
"Thank-you!-This-is-the-last-step.":"恭喜,这是最后一步啦。", "Please click the following button to confirm your email address": "请点击以下按钮确认在萌立方使用您的邮箱地址",
"Please click the following button to confirm your email address":"请点击以下按钮确认在萌立方使用您的邮箱地址", "Finish-Verification": "完成邮箱验证",
"Finish-Verification":"完成邮箱验证", "After-verification,-you-can-sign-in-to-MoeCube-with-this-email-address.": "验证完成后,您就可以使用邮箱在萌立方客户端登录啦。",
"After-verification,-you-can-sign-in-to-MoeCube-with-this-email-address.":"验证完成后,您就可以使用邮箱在萌立方客户端登录啦。", "Welcome-to-MoeCube!": "欢迎加入萌立方这个大家庭!",
"Welcome-to-MoeCube!":"欢迎加入萌立方这个大家庭!",
"i_password_error": "密码错误", "i_password_error": "密码错误",
"i_user_unexists":"用户不存在", "i_user_unexists": "用户不存在",
"i_email_exists":"邮箱已存在", "i_email_exists": "邮箱已存在",
"i_username_exists":"用户名已存在", "i_username_exists": "用户名已存在",
"i_not_found":"用户不存在", "i_username_exists_or_invalid": "用户名已存在或格式有误",
"i_key_time_out":"此链接已过期", "i_not_found": "用户不存在",
"i_key_invalid":"此链接已失效", "i_key_time_out": "此链接已过期",
"i_key_invalid": "此链接已失效",
"LogoutNow": "提前退出",
"没毛用":"防逗号报错,上线删" "LoggingOutIn": "即将在",
"Seconds": "秒后退出",
"TemporaryPrompt": "改名在1,4,7,10月的第一周开启。改名后所有战绩将清空。",
"ChangeSuccess": "修改成功,请重新登录生效。",
"EmailChangeSuccess":"请查看邮件完成修改。",
"没毛用": "防逗号报错,上线删"
} }
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="index.css"/> <link rel="stylesheet" href="index.css"/>
<link rel="icon" href="https://moecube.com/favicon.ico"> <link rel="icon" href="/favicon.ico">
<script src="https://v-cn.vaptcha.com/v3.js"></script> <script src="https://v-cn.vaptcha.com/v3.js"></script>
</head> </head>
<body> <body>
......
import { Form, Input } from 'antd'; import { Button, Form, Input } from 'antd';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SubmitButton from './SubmitButton'; import SubmitButton from './SubmitButton';
...@@ -11,13 +11,15 @@ const formItemLayout = { ...@@ -11,13 +11,15 @@ const formItemLayout = {
class EmailForm extends React.Component { class EmailForm extends React.Component {
state = {
countdown: 0,
inCountdown: false, // Whether the countdown is active
};
// static contextTypes = { // static contextTypes = {
// intl: PropTypes.object.isRequired, // intl: PropTypes.object.isRequired,
// }; // };
onSubmit = (e) => { onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props; const { form, dispatch, user: { id } } = this.props;
if (e) { if (e) {
e.preventDefault(); e.preventDefault();
} }
...@@ -28,17 +30,48 @@ class EmailForm extends React.Component { ...@@ -28,17 +30,48 @@ class EmailForm extends React.Component {
const { email, password } = values; const { email, password } = values;
dispatch({ type: 'user/updateEmail', payload: { email, password, user_id: id } }); dispatch({ type: 'user/updateEmail', payload: { email, password, user_id: id } });
this.setState({ countdown: 5, inCountdown: true });
this.countdownTimer = setInterval(this.handleCountdown, 1000);
} }
}); });
}; };
handleCountdown = () => {
// 倒计时减1
this.setState(prevState => ({ countdown: prevState.countdown - 1 }));
if (this.state.countdown === 0) {
// 清除倒计时
clearInterval(this.countdownTimer);
// 设置倒计时状态为false
this.setState({ inCountdown: false });
// 倒计时结束后调用退出
this.handleLogout();
}
};
handleLogout = () => {
clearInterval(this.countdownTimer);
window.localStorage.removeItem('token');
if (window.ygopro) {
window.ygopro.logoutUser('YGOMobile萌卡已登出');
}
const url = new URL(window.location.href);
const redirect = url.searchParams.get('redirect') || '/';
window.location.href = redirect;
};
handleLogoutNow = () => {
this.setState({ countdown: 0 }, () => {
this.handleLogout();
});
};
render() { render() {
const { form, dispatch, user, checkEmail, isEmailExists, messages } = this.props; const { form, dispatch, user, checkEmail, isEmailExists, messages } = this.props;
const { getFieldDecorator } = form; const { getFieldDecorator } = form;
const { id, email } = user; const { id, email } = user;
// const { intl: { messages } } = this.context; // const { intl: { messages } } = this.context;
const logoutNowText = this.props.messages.LogoutNow;
const loggingOutInText = this.props.messages.LoggingOutIn;
const secondsText = this.props.messages.Seconds;
const ChangeSuccessText = this.props.messages.EmailChangeSuccess;
const emailProps = { const emailProps = {
fromItem: { fromItem: {
label: messages.email, label: messages.email,
...@@ -74,8 +107,25 @@ class EmailForm extends React.Component { ...@@ -74,8 +107,25 @@ class EmailForm extends React.Component {
type: 'password', type: 'password',
}, },
}; };
const { inCountdown, countdown } = this.state;
return ( return (
<div>
{inCountdown ? (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100vh' }}>
<div style={{ flex: 9 / 10, textAlign: 'center' }}>
<h3>{ChangeSuccessText}</h3>
<h3>
{loggingOutInText}
<span style={{ color: '#4da9ee', fontSize: '2em' }}>&nbsp;{`${countdown}`}</span>
<span>&nbsp;{secondsText}</span>
</h3>
<br/>
<Button type="link" onClick={this.handleLogoutNow}>
{logoutNowText}
</Button>
</div>
</div>
) : (
<Form onSubmit={this.onSubmit}> <Form onSubmit={this.onSubmit}>
<FormItem {...emailProps.fromItem}> <FormItem {...emailProps.fromItem}>
{getFieldDecorator('email', { ...emailProps.decorator })( {getFieldDecorator('email', { ...emailProps.decorator })(
...@@ -96,6 +146,8 @@ class EmailForm extends React.Component { ...@@ -96,6 +146,8 @@ class EmailForm extends React.Component {
<SubmitButton /> <SubmitButton />
</FormItem> </FormItem>
</Form> </Form>
)}
</div>
); );
} }
} }
......
import { Form, Input } from 'antd'; import { Form, Input, Button } from 'antd';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SubmitButton from './SubmitButton'; import SubmitButton from './SubmitButton';
const FormItem = Form.Item; const FormItem = Form.Item;
const formItemLayout = { const formItemLayout = {
labelCol: { span: 4 }, labelCol: { span: 4 },
wrapperCol: { span: 15 }, wrapperCol: { span: 15 },
...@@ -14,7 +12,10 @@ const formItemLayout = { ...@@ -14,7 +12,10 @@ const formItemLayout = {
class EmailForm extends React.Component { class EmailForm extends React.Component {
state = {
countdown: 0,
inCountdown: false, // 是否处于倒计时状态
};
onSubmit = (e) => { onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props; const { form, dispatch, user: { id } } = this.props;
...@@ -28,13 +29,47 @@ class EmailForm extends React.Component { ...@@ -28,13 +29,47 @@ class EmailForm extends React.Component {
const { new_password, password } = values; const { new_password, password } = values;
dispatch({ type: 'user/updateAccount', payload: { new_password, password, user_id: id } }); dispatch({ type: 'user/updateAccount', payload: { new_password, password, user_id: id } });
// 设置倒计时状态为5秒
this.setState({ countdown: 5, inCountdown: true });
// 启动倒计时
this.countdownTimer = setInterval(this.handleCountdown, 1000);
} }
}); });
}; };
handleCountdown = () => {
// 倒计时减1
this.setState(prevState => ({ countdown: prevState.countdown - 1 }));
if (this.state.countdown === 0) {
// 清除倒计时
clearInterval(this.countdownTimer);
// 设置倒计时状态为false
this.setState({ inCountdown: false });
// 倒计时结束后调用退出
this.handleLogout();
}
};
handleLogout = () => {
clearInterval(this.countdownTimer);
window.localStorage.removeItem('token');
if (window.ygopro) {
window.ygopro.logoutUser('YGOMobile萌卡已登出');
}
const url = new URL(window.location.href);
const redirect = url.searchParams.get('redirect') || '/';
window.location.href = redirect;
};
handleLogoutNow = () => {
this.setState({ countdown: 0 }, () => {
this.handleLogout();
});
};
checkPassword = (rule, value, callback) => { checkPassword = (rule, value, callback) => {
const { form, messages } = this.props; const { form, messages } = this.props;
//const { intl: { messages } } = this.context; // const { intl: { messages } } = this.context;
if (value && value !== form.getFieldValue('new_password')) { if (value && value !== form.getFieldValue('new_password')) {
callback(messages['Incorrect-password.2']); callback(messages['Incorrect-password.2']);
} else { } else {
...@@ -54,7 +89,10 @@ class EmailForm extends React.Component { ...@@ -54,7 +89,10 @@ class EmailForm extends React.Component {
render() { render() {
const { form, messages } = this.props; const { form, messages } = this.props;
const { getFieldDecorator } = form; const { getFieldDecorator } = form;
const logoutNowText = this.props.messages.LogoutNow;
const loggingOutInText = this.props.messages.LoggingOutIn;
const secondsText = this.props.messages.Seconds;
const ChangeSuccessText = this.props.messages.ChangeSuccess;
const passwordProps = { const passwordProps = {
fromItem: { fromItem: {
label: messages['old-password'], label: messages['old-password'],
...@@ -100,8 +138,25 @@ class EmailForm extends React.Component { ...@@ -100,8 +138,25 @@ class EmailForm extends React.Component {
type: 'password', type: 'password',
}, },
}; };
const { inCountdown, countdown } = this.state;
return ( return (
<div>
{inCountdown ? (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100vh' }}>
<div style={{ flex: 9 / 10, textAlign: 'center' }}>
<h3>{ChangeSuccessText}</h3>
<h3>
{loggingOutInText}
<span style={{ color: '#4da9ee', fontSize: '2em' }}>&nbsp;{`${countdown}`}</span>
<span>&nbsp;{secondsText}</span>
</h3>
<br/>
<Button type="link" onClick={this.handleLogoutNow}>
{logoutNowText}
</Button>
</div>
</div>
) : (
<Form onSubmit={this.onSubmit}> <Form onSubmit={this.onSubmit}>
<FormItem {...passwordProps.fromItem} label={messages['old-password']}> <FormItem {...passwordProps.fromItem} label={messages['old-password']}>
{getFieldDecorator('password')( {getFieldDecorator('password')(
...@@ -125,6 +180,8 @@ class EmailForm extends React.Component { ...@@ -125,6 +180,8 @@ class EmailForm extends React.Component {
<SubmitButton /> <SubmitButton />
</FormItem> </FormItem>
</Form> </Form>
)}
</div>
); );
} }
} }
...@@ -135,6 +192,7 @@ function mapStateToProps(state) { ...@@ -135,6 +192,7 @@ function mapStateToProps(state) {
user: { user }, user: { user },
common: { messages }, common: { messages },
} = state; } = state;
return { return {
messages, messages,
user, user,
......
import { Form, Input } from 'antd'; import { Button, Form, Input } from 'antd';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SubmitButton from './SubmitButton'; import SubmitButton from './SubmitButton';
...@@ -11,7 +11,10 @@ const formItemLayout = { ...@@ -11,7 +11,10 @@ const formItemLayout = {
class EmailForm extends React.Component { class EmailForm extends React.Component {
state = {
countdown: 0,
inCountdown: false, // Whether the countdown is active
};
onSubmit = (e) => { onSubmit = (e) => {
const { form, dispatch, user: { id } } = this.props; const { form, dispatch, user: { id } } = this.props;
...@@ -21,25 +24,74 @@ class EmailForm extends React.Component { ...@@ -21,25 +24,74 @@ class EmailForm extends React.Component {
form.validateFieldsAndScroll((err, values) => { form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
console.log('Received values of form: ', values); console.log('Received values of form: ', values);
const { username, password } = values; const { username, password } = values;
dispatch({ type: 'user/updateAccount', payload: { username, password, user_id: id } }); dispatch({ type: 'user/updateAccount', payload: { username, password, user_id: id } });
this.setState({ countdown: 5, inCountdown: true });
this.countdownTimer = setInterval(this.handleCountdown, 1000);
}
});
};
handleCountdown = () => {
// 倒计时减1
this.setState(prevState => ({ countdown: prevState.countdown - 1 }));
if (this.state.countdown === 0) {
// 清除倒计时
clearInterval(this.countdownTimer);
// 设置倒计时状态为false
this.setState({ inCountdown: false });
// 倒计时结束后调用退出
this.handleLogout();
} }
};
handleLogout = () => {
clearInterval(this.countdownTimer);
window.localStorage.removeItem('token');
if (window.ygopro) {
window.ygopro.logoutUser('YGOMobile萌卡已登出');
}
const url = new URL(window.location.href);
const redirect = url.searchParams.get('redirect') || '/';
window.location.href = redirect;
};
handleLogoutNow = () => {
this.setState({ countdown: 0 }, () => {
this.handleLogout();
}); });
}; };
checkPassword = (rule, value, callback) => {
const { form, messages } = this.props;
// const { intl: { messages } } = this.context;
if (value && value !== form.getFieldValue('new_password')) {
callback(messages['Incorrect-password.2']);
} else {
callback();
}
};
checkConfirm = (rule, value, callback) => {
const form = this.props.form;
if (value) {
form.validateFields(['confirm'], { force: true });
}
callback();
};
render() { render() {
const { form, dispatch, user, checkUsername, isUserNameExists, messages } = this.props; const { form, dispatch, user, checkUsername, isUserNameExists, messages } = this.props;
const { getFieldDecorator } = form; const { getFieldDecorator } = form;
const { id, username } = user; const { id, username } = user;
const logoutNowText = this.props.messages.LogoutNow;
const loggingOutInText = this.props.messages.LoggingOutIn;
const secondsText = this.props.messages.Seconds;
const temporaryPromptText = this.props.messages.TemporaryPrompt;
const ChangeSuccessText = this.props.messages.ChangeSuccess;
const usernameProps = { const usernameProps = {
fromItem: { fromItem: {
label: messages.username, label: messages.username,
hasFeedback: true, hasFeedback: true,
validateStatus: checkUsername, validateStatus: checkUsername,
extra: isUserNameExists ? 'username exists' : '', extra: isUserNameExists ? messages.i_username_exists_or_invalid : '',
...formItemLayout, ...formItemLayout,
}, },
decorator: { decorator: {
...@@ -70,15 +122,32 @@ class EmailForm extends React.Component { ...@@ -70,15 +122,32 @@ class EmailForm extends React.Component {
type: 'password', type: 'password',
}, },
}; };
const { inCountdown, countdown } = this.state;
return ( return (
<div>
{inCountdown ? (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100vh' }}>
<div style={{ flex: 9 / 10, textAlign: 'center' }}>
<h3>{ChangeSuccessText}</h3>
<h3>
{loggingOutInText}
<span style={{ color: '#4da9ee', fontSize: '2em' }}>&nbsp;{`${countdown}`}</span>
<span>&nbsp;{secondsText}</span>
</h3>
<br/>
<Button type="link" onClick={this.handleLogoutNow}>
{logoutNowText}
</Button>
</div>
</div>
) : (
<Form onSubmit={this.onSubmit}> <Form onSubmit={this.onSubmit}>
<FormItem {...usernameProps.fromItem}> <FormItem {...usernameProps.fromItem}>
{getFieldDecorator('username', { ...usernameProps.decorator })( {getFieldDecorator('username', { ...usernameProps.decorator })(
<Input {...usernameProps.input} disabled/>, <Input {...usernameProps.input} />,
)} )}
{ {
<div class="alert alert-warning" role="alert">改名已经关闭。改名将在1月,4月,7月和10月的第一周开启。</div> <div className="alert alert-warning" role="alert">{temporaryPromptText}</div>
} }
</FormItem> </FormItem>
...@@ -90,14 +159,15 @@ class EmailForm extends React.Component { ...@@ -90,14 +159,15 @@ class EmailForm extends React.Component {
</FormItem> </FormItem>
<FormItem> <FormItem>
<SubmitButton disabled/> <SubmitButton/>
</FormItem> </FormItem>
</Form> </Form>
)}
</div>
); );
} }
} }
function mapStateToProps(state) { function mapStateToProps(state) {
const { const {
user: { user }, user: { user },
......
...@@ -11,6 +11,9 @@ function mutatedUserAvatar(avatar) { ...@@ -11,6 +11,9 @@ function mutatedUserAvatar(avatar) {
if (!avatar) { if (!avatar) {
return avatar; return avatar;
} }
if (avatar.includes('default_avatar')) {
return defaultAvatar;
}
return `https://sapi.moecube.com:444/avatar/url/${avatar.split('/').pop()}/40/avatar.png`; return `https://sapi.moecube.com:444/avatar/url/${avatar.split('/').pop()}/40/avatar.png`;
} }
......
...@@ -24,6 +24,9 @@ export default { ...@@ -24,6 +24,9 @@ export default {
signOut(state) { signOut(state) {
console.log('sign out'); console.log('sign out');
localStorage.removeItem('token'); localStorage.removeItem('token');
if (window.ygopro) {
window.ygopro.logoutUser("YGOMobile萌卡登出");
}
location.href = '/'; location.href = '/';
return state; return state;
}, },
......
...@@ -214,6 +214,9 @@ export default { ...@@ -214,6 +214,9 @@ export default {
} }
if (pathname === '/logout') { if (pathname === '/logout') {
localStorage.removeItem('token'); localStorage.removeItem('token');
if (window.ygopro) {
window.ygopro.logoutUser("YGOMobile 萌卡登出");
}
location.href = query.redirect; location.href = query.redirect;
} }
}); });
......
...@@ -9,6 +9,8 @@ import Format from '../components/Format'; ...@@ -9,6 +9,8 @@ import Format from '../components/Format';
import logo from '../assets/MoeCube.png'; import logo from '../assets/MoeCube.png';
import UserPanel from '../components/UserPanel'; import UserPanel from '../components/UserPanel';
import './Index.less';
const languageMap = { const languageMap = {
'zh-CN': '中文', 'zh-CN': '中文',
'en-US': 'English', 'en-US': 'English',
...@@ -151,10 +153,10 @@ function Index({ children, messages, dispatch, client, language }) { ...@@ -151,10 +153,10 @@ function Index({ children, messages, dispatch, client, language }) {
); );
return ( return (
<div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: '100%' }}> <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: '100%' }}>
<DocumentTitle title={messages.title || 'Moe Cube'}/> <DocumentTitle title={messages.title || 'MoeCube'}/>
{client !== 'electron' && {client !== 'electron' &&
<Header style={{ display: 'flex', alignItems: 'center' }}> <Header style={{ display: 'flex', alignItems: 'center' }} className="mc-header">
<Link to="/" style={{ marginTop: '20px' }}> <Link to="/" style={{ marginTop: '20px' }}>
<img alt="logo" src={logo} style={{ width: '140px', height: '44px' }}/> <img alt="logo" src={logo} style={{ width: '140px', height: '44px' }}/>
</Link> </Link>
...@@ -182,7 +184,7 @@ function Index({ children, messages, dispatch, client, language }) { ...@@ -182,7 +184,7 @@ function Index({ children, messages, dispatch, client, language }) {
</Menu.Item> </Menu.Item>
</Menu> </Menu>
<div style={{ position: 'absolute', right: '40px' }}> <div className="mc-userpanel">
<UserPanel /> <UserPanel />
</div> </div>
</Header> </Header>
...@@ -202,7 +204,7 @@ function Index({ children, messages, dispatch, client, language }) { ...@@ -202,7 +204,7 @@ function Index({ children, messages, dispatch, client, language }) {
{languageMap[language]} <Icon type="down" className="flag"/> {languageMap[language]} <Icon type="down" className="flag"/>
</a> </a>
</Dropdown></div> </Dropdown></div>
<div>© MoeCube 2017-2022 all right reserved.</div> <div>© MoeCube 2017-2023 all right reserved.</div>
</Footer> </Footer>
</div> </div>
); );
......
.particles { .particles {
position: fixed; position: fixed;
top: 0; top: 0;
...@@ -7,3 +6,20 @@ ...@@ -7,3 +6,20 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
:global {
.mc-userpanel {
position: absolute;
right: 40px;
}
@media (max-width: 768px) {
.mc-header {
padding: 0 10px;
}
.mc-userpanel {
right: 10px;
}
}
}
\ No newline at end of file
...@@ -4,6 +4,9 @@ import React from 'react'; ...@@ -4,6 +4,9 @@ import React from 'react';
class Logout extends React.Component { class Logout extends React.Component {
componentDidMount() { componentDidMount() {
window.localStorage.removeItem('token'); window.localStorage.removeItem('token');
if (window.ygopro) {
window.ygopro.logoutUser("YGOMobile萌卡已登出");
}
const url = new URL(window.location.href); const url = new URL(window.location.href);
const redirect = url.searchParams.get('redirect') || '/'; const redirect = url.searchParams.get('redirect') || '/';
window.location.href = redirect; window.location.href = redirect;
......
...@@ -107,28 +107,31 @@ class Profiles extends React.Component { ...@@ -107,28 +107,31 @@ class Profiles extends React.Component {
<Form onSubmit={this.onUpdateSubmit}> <Form onSubmit={this.onUpdateSubmit}>
<FormItem style={{ display: 'flex', justifyContent: 'center' }}> <FormItem style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ display: isUpload ? 'flex' : 'none', flexDirection: 'column'}}> <div style={{ display: 'flex', flexDirection: 'column' }}>
<Cropper <Cropper
ref={(cropper) => { ref={(cropper) => {
this.cropper = cropper; this.cropper = cropper;
}} }}
src={imageUrl || defaultAvatar} src={imageUrl || defaultAvatar}
className="cropper-image" className="cropper-image"
style={{ height: '20vw', width: '20vw' }} style={{ height: '300px', width: '300px', display: isUpload ? 'block' : 'none' }}
aspectRatio={1 / 1} aspectRatio={1 / 1}
autoCropArea={1}
guides guides
/> />
<br/> <img
<Button type="primary" onClick={this.handleUpload}> alt="avatar"
<Icon type="upload"/> <Format id="upload"/> style={{ height: '300px', width: '300px', display: !isUpload ? 'block' : 'none' }}
src={avatar || imageUrl || defaultAvatar}
/>
<Button type="primary" onClick={this.handleUpload} style={{ display: isUpload ? 'inline-block' : 'none', marginTop: '2em' }}>
<Icon type="check"/> <Format id="Upload-Avatar"/>
</Button> </Button>
</div> <Button type="default" style={{ marginTop: '2em' }}>
<div style={{ display: !isUpload ? 'flex' : 'none', flexDirection: 'column' }}>
<img alt="avatar" style={{ height: '20vw', width: '20vw' }} src={avatar || imageUrl || defaultAvatar}/>
<Button style={{ padding: '4px 0' }}>
<label style={{ display: 'flex', flex: 1, justifyContent: 'center', alignItems: 'center' }}> <label style={{ display: 'flex', flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Icon type="plus"/><Format id="Change-Avatar"/> <Icon type="plus" style={{ marginRight: '0.5em' }} />
{(!isUpload) && <Format id="Change-Avatar"/>}
{isUpload && <Format id="Reselect-Avatar"/>}
<input <input
type="file" onChange={this.onGetFile} ref={(file) => { type="file" onChange={this.onGetFile} ref={(file) => {
this.file = file; this.file = file;
...@@ -143,6 +146,9 @@ class Profiles extends React.Component { ...@@ -143,6 +146,9 @@ class Profiles extends React.Component {
{getFieldDecorator('name', { ...nameProps.decorator })( {getFieldDecorator('name', { ...nameProps.decorator })(
<Input {...nameProps.input} />, <Input {...nameProps.input} />,
)} )}
{
<div className="alert alert-warning" role="alert"><Format id="Nickname-Hint"/></div>
}
</FormItem> </FormItem>
<FormItem> <FormItem>
......
...@@ -74,7 +74,7 @@ class Register extends React.Component { ...@@ -74,7 +74,7 @@ class Register extends React.Component {
const usernameProps = { const usernameProps = {
hasFeedback: true, hasFeedback: true,
validateStatus: checkUsername, validateStatus: checkUsername,
extra: isUserNameExists ? 'username exists or invalid ' : '', extra: isUserNameExists ? messages.i_username_exists : '',
}; };
const usernameInputProps = { const usernameInputProps = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment