Files
phaten-audio/zh/docs/login/index.md
PhatenIoT-yan 00f42eab80 update
2025-12-25 14:21:26 +08:00

735 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 登录注册
---
# 登录注册
<style>
/* 页面版本的登录注册样式 */
.login-page-container {
max-width: 500px;
margin: 2rem auto;
padding: 30px;
background-color: #fefefe;
border: 1px solid #ddd;
border-radius: 15px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.login-page-container h2 {
text-align: center;
margin-bottom: 25px;
color: #333;
font-size: 24px;
}
/* Tab 样式 */
.tab-container {
display: flex;
margin-bottom: 25px;
border-bottom: 1px solid #ddd;
}
.tab-button {
flex: 1;
padding: 15px;
background: none;
border: none;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;
border-bottom: 2px solid transparent;
}
.tab-button.active {
color: #3498db;
border-bottom-color: #3498db;
font-weight: bold;
}
.tab-button:hover {
color: #3498db;
background-color: #f8f9fa;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.login-form input {
width: 100%;
padding: 12px;
margin: 12px 0;
border: 1px solid #ddd;
border-radius: 8px;
box-sizing: border-box;
font-size: 15px;
}
.login-form .code-container {
display: flex;
gap: 10px;
margin: 12px 0;
}
.login-form .hint-text {
font-size: 12px;
color: #666;
margin-top: 3px;
margin-bottom: 8px;
text-align: left;
}
.login-form .code-input {
flex: 3;
padding: 12px;
border: 1px solid #ddd;
border-radius: 8px;
box-sizing: border-box;
font-size: 15px;
}
.login-form .send-code-btn {
flex: 1;
min-width: 100px;
padding: 12px 10px;
height: 47px;
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s ease;
white-space: nowrap;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.login-form .send-code-btn:hover {
background-color: #2980b9;
}
.login-form .send-code-btn:disabled {
background-color: #95a5a6;
cursor: not-allowed;
}
.login-form button[type="submit"] {
width: 100%;
padding: 12px;
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
margin-top: 15px;
font-size: 16px;
transition: background-color 0.3s ease;
}
.login-form button[type="submit"]:hover {
background-color: #2980b9;
}
/* 忘记密码链接样式 */
.forgot-password-link {
display: block;
text-align: center;
margin-top: 15px;
color: #3498db;
text-decoration: none;
font-size: 14px;
transition: color 0.3s ease;
}
.forgot-password-link:hover {
color: #2980b9;
text-decoration: underline;
}
/* 消息提示样式 */
.message-box {
display: none;
padding: 15px;
margin: 15px 0;
border-radius: 8px;
text-align: center;
}
.message-box.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message-box.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.message-box.info {
background-color: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
</style>
<div class="login-page-container">
<h2>飞腾云登录/注册</h2>
<!-- 消息提示框 -->
<div id="messageBox" class="message-box">
<span id="messageText"></span>
</div>
<!-- Tab 切换按钮 -->
<div class="tab-container">
<button class="tab-button active" onclick="switchTab('login')">登录</button>
<button class="tab-button" onclick="switchTab('register')">注册</button>
</div>
<!-- 登录表单 -->
<div id="loginTab" class="tab-content active">
<form id="loginForm" class="login-form">
<input type="email" id="loginEmail" placeholder="请输入邮箱" required>
<input type="password" id="loginPassword" placeholder="请输入密码" required>
<button type="submit">登录</button>
<a href="javascript:void(0)" class="forgot-password-link" onclick="switchTab('reset')">忘记密码?</a>
</form>
</div>
<!-- 注册表单 -->
<div id="registerTab" class="tab-content">
<form id="registerForm" class="login-form">
<input type="email" id="registerEmail" placeholder="请输入邮箱" required>
<div class="code-container">
<input type="text" id="verificationCode" class="code-input" placeholder="请输入验证码" required>
<button type="button" id="sendCodeBtn" class="send-code-btn">发送验证码</button>
</div>
<input type="password" id="registerPassword" placeholder="请输入密码" required>
<input type="password" id="confirmPassword" placeholder="请确认密码" required>
<button type="submit">注册</button>
</form>
</div>
<!-- 忘记密码表单 -->
<div id="resetTab" class="tab-content">
<form id="resetForm" class="login-form">
<input type="email" id="resetEmail" placeholder="请输入邮箱" required>
<div class="code-container">
<input type="text" id="resetVerificationCode" class="code-input" placeholder="请输入验证码" required>
<button type="button" id="sendResetCodeBtn" class="send-code-btn">发送验证码</button>
</div>
<input type="password" id="resetPassword" placeholder="请输入新密码" required>
<input type="password" id="resetConfirmPassword" placeholder="请确认新密码" required>
<button type="submit">重置密码</button>
<a href="javascript:void(0)" class="forgot-password-link" onclick="switchTab('login')">返回登录</a>
</form>
</div>
</div>
<script>
// 页面版本的登录注册功能
(function() {
'use strict';
// 定义API的基础URL
const baseUrl = 'https://api.phaten-audio.com/api';
//const baseUrl = 'http://localhost:8010/api';
// 获取表单元素
const loginForm = document.getElementById("loginForm");
const registerForm = document.getElementById("registerForm");
const resetForm = document.getElementById("resetForm");
const sendCodeBtn = document.getElementById("sendCodeBtn");
const sendResetCodeBtn = document.getElementById("sendResetCodeBtn");
const messageBox = document.getElementById("messageBox");
const messageText = document.getElementById("messageText");
let countdownTimer;
let resetCountdownTimer;
// Tab 切换功能
window.switchTab = function(tabName) {
// 获取tab容器
const tabContainer = document.querySelector('.tab-container');
// 隐藏所有tab内容
const tabContents = document.querySelectorAll('.tab-content');
tabContents.forEach(tab => tab.classList.remove('active'));
// 移除所有tab按钮的active状态
const tabButtons = document.querySelectorAll('.tab-button');
tabButtons.forEach(btn => btn.classList.remove('active'));
// 显示对应的tab内容和设置按钮active状态
if (tabName === 'login') {
// 显示tab容器
tabContainer.style.display = 'flex';
document.getElementById('loginTab').classList.add('active');
document.querySelectorAll('.tab-button')[0].classList.add('active');
} else if (tabName === 'register') {
// 显示tab容器
tabContainer.style.display = 'flex';
document.getElementById('registerTab').classList.add('active');
document.querySelectorAll('.tab-button')[1].classList.add('active');
} else if (tabName === 'reset') {
// 忘记密码面板时隐藏tab容器
tabContainer.style.display = 'none';
document.getElementById('resetTab').classList.add('active');
}
// 隐藏消息框
hideMessage();
}
// 显示消息
function showMessage(text, type = 'info') {
messageText.textContent = text;
messageBox.className = `message-box ${type}`;
messageBox.style.display = 'block';
// 3秒后自动隐藏成功和信息消息
if (type === 'success' || type === 'info') {
setTimeout(() => {
hideMessage();
}, 3000);
}
}
// 隐藏消息
function hideMessage() {
messageBox.style.display = 'none';
}
// 检查本地存储中是否有token
function getLocalToken() {
return localStorage.getItem('ftyToken');
}
// 保存token到本地存储
function saveToken(token) {
localStorage.setItem('ftyToken', token);
}
// 清除token
function clearToken() {
localStorage.removeItem('ftyToken');
}
// 验证token是否有效
async function validateToken() {
const token = getLocalToken();
console.log("validateToken函数被调用token:", token);
if (!token) {
console.log("没有token返回false");
return false;
}
try {
console.log("发送token验证请求...");
const response = await fetch(`${baseUrl}/fty/validateToken`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
console.log("token验证服务器响应:",data);
const isValid = data.data && data.data.valid === true;
console.log("token是否有效:", isValid);
// 如果token无效清除本地存储
if (!isValid) {
console.log("token无效清除本地存储");
clearToken();
}
return isValid;
} catch (error) {
console.error('Token validation error:', error);
console.log("token验证出错清除本地存储");
clearToken();
return false;
}
}
// 验证邮箱格式
function validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
// 发送注册验证码
sendCodeBtn.onclick = function() {
const contactValue = document.getElementById('registerEmail').value;
if (!validateEmail(contactValue)) {
showMessage('请输入有效的邮箱地址!', 'error');
return;
}
// 禁用按钮并开始倒计时
startCountdown();
// 发送AJAX请求获取验证码
fetch(`${baseUrl}/fty/sendCode`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: "1", // 固定为邮箱类型
username: contactValue
})
})
.then(response => response.json())
.then(data => {
console.log("验证码发送返回",data);
if (data.code==2000) {
showMessage('验证码已发送到您的邮箱!', 'success');
} else {
showMessage(data.msg || '验证码发送失败,请稍后重试!', 'error');
resetCountdown();
}
})
.catch(error => {
console.error('Error:', error);
showMessage('验证码发送请求失败,请稍后重试!', 'error');
resetCountdown();
});
}
// 发送重置密码验证码
sendResetCodeBtn.onclick = function() {
const contactValue = document.getElementById('resetEmail').value;
if (!validateEmail(contactValue)) {
showMessage('请输入有效的邮箱地址!', 'error');
return;
}
// 禁用按钮并开始倒计时
startResetCountdown();
// 发送AJAX请求获取验证码
fetch(`${baseUrl}/fty/sendCode`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: "1", // 固定为邮箱类型
username: contactValue
})
})
.then(response => response.json())
.then(data => {
console.log("重置密码验证码发送返回",data);
if (data.code==2000) {
showMessage('验证码已发送到您的邮箱!', 'success');
} else {
showMessage(data.msg || '验证码发送失败,请稍后重试!', 'error');
resetResetCountdown();
}
})
.catch(error => {
console.error('Error:', error);
showMessage('验证码发送请求失败,请稍后重试!', 'error');
resetResetCountdown();
});
}
// 开始注册验证码倒计时
function startCountdown() {
let countdown = 60;
sendCodeBtn.disabled = true;
sendCodeBtn.textContent = `${countdown}秒后重试`;
countdownTimer = setInterval(() => {
countdown--;
sendCodeBtn.textContent = `${countdown}秒后重试`;
if (countdown <= 0) {
resetCountdown();
}
}, 1000);
}
// 重置注册验证码倒计时
function resetCountdown() {
clearInterval(countdownTimer);
sendCodeBtn.disabled = false;
sendCodeBtn.textContent = '发送验证码';
}
// 开始重置密码验证码倒计时
function startResetCountdown() {
let countdown = 60;
sendResetCodeBtn.disabled = true;
sendResetCodeBtn.textContent = `${countdown}秒后重试`;
resetCountdownTimer = setInterval(() => {
countdown--;
sendResetCodeBtn.textContent = `${countdown}秒后重试`;
if (countdown <= 0) {
resetResetCountdown();
}
}, 1000);
}
// 重置重置密码验证码倒计时
function resetResetCountdown() {
clearInterval(resetCountdownTimer);
sendResetCodeBtn.disabled = false;
sendResetCodeBtn.textContent = '发送验证码';
}
// 处理登录表单提交
loginForm.onsubmit = function(e) {
console.log("Login form submitted");
e.preventDefault();
const email = document.getElementById("loginEmail").value;
const password = document.getElementById("loginPassword").value;
if (!validateEmail(email)) {
showMessage('请输入有效的邮箱地址!', 'error');
return;
}
if (!password) {
showMessage('请输入密码!', 'error');
return;
}
// 显示加载状态
const submitBtn = loginForm.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.textContent = '登录中...';
submitBtn.disabled = true;
// 发送AJAX请求
fetch(`${baseUrl}/fty/userLogin`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: email,
type: 1,
password: password
})
})
.then(response => response.json())
.then(data => {
console.log("登录返回",data);
if (data.code==2000) {
// 保存token到本地存储
if (data.data.token) {
saveToken(data.data.token);
}
showMessage('登录成功!正在跳转...', 'success');
// 延迟跳转到首页
setTimeout(() => {
window.location.href = '/';
}, 1500);
} else {
showMessage(data.msg || '登录失败,请检查邮箱和密码!', 'error');
}
})
.catch(error => {
console.error('Error:', error);
showMessage('登录请求失败,请稍后重试!', 'error');
})
.finally(() => {
// 恢复按钮状态
submitBtn.textContent = originalText;
submitBtn.disabled = false;
});
}
// 处理注册表单提交
registerForm.onsubmit = function(e) {
console.log("Register form submitted");
e.preventDefault();
const email = document.getElementById("registerEmail").value;
const verificationCode = document.getElementById("verificationCode").value;
const password = document.getElementById("registerPassword").value;
const confirmPassword = document.getElementById("confirmPassword").value;
if (!validateEmail(email)) {
showMessage('请输入有效的邮箱地址!', 'error');
return;
}
if (!verificationCode) {
showMessage('请输入验证码!', 'error');
return;
}
if (!password) {
showMessage('请输入密码!', 'error');
return;
}
if (password !== confirmPassword) {
showMessage('两次输入的密码不一致!', 'error');
return;
}
// 显示加载状态
const submitBtn = registerForm.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.textContent = '注册中...';
submitBtn.disabled = true;
// 发送AJAX请求
fetch(`${baseUrl}/fty/userRegister`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 1, // 固定为邮箱类型
username: email,
code: verificationCode,
password: password,
confirm_password:confirmPassword
})
})
.then(response => response.json())
.then(data => {
console.log("注册返回",data);
if (data.code==2000) {
// 保存token到本地存储
if (data.data.token) {
saveToken(data.data.token);
}
showMessage('注册成功!正在跳转...', 'success');
resetCountdown();
// 延迟跳转到首页
setTimeout(() => {
window.location.href = '/';
}, 1500);
} else {
showMessage( '注册失败,请检查输入信息!', data.msg,'error');
}
})
.catch(error => {
console.error('Error:', error);
var msg = error.message || error.toString() || error;
showMessage('注册失败',msg, 'error');
})
.finally(() => {
// 恢复按钮状态
submitBtn.textContent = originalText;
submitBtn.disabled = false;
});
}
// 处理忘记密码表单提交
resetForm.onsubmit = function(e) {
console.log("Reset password form submitted");
e.preventDefault();
const email = document.getElementById("resetEmail").value;
const verificationCode = document.getElementById("resetVerificationCode").value;
const password = document.getElementById("resetPassword").value;
const confirmPassword = document.getElementById("resetConfirmPassword").value;
if (!validateEmail(email)) {
showMessage('请输入有效的邮箱地址!', 'error');
return;
}
if (!verificationCode) {
showMessage('请输入验证码!', 'error');
return;
}
if (!password) {
showMessage('请输入新密码!', 'error');
return;
}
if (password !== confirmPassword) {
showMessage('两次输入的密码不一致!', 'error');
return;
}
// 显示加载状态
const submitBtn = resetForm.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.textContent = '重置中...';
submitBtn.disabled = true;
// 发送AJAX请求
fetch(`${baseUrl}/fty/resetpwd`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 1, // 固定为邮箱类型
username: email,
code: verificationCode,
password: password,
confirm_password: confirmPassword
})
})
.then(response => response.json())
.then(data => {
console.log("重置密码返回",data);
if (data.code==2000) {
showMessage('密码重置成功!请使用新密码登录', 'success');
resetResetCountdown();
// 延迟切换到登录标签
setTimeout(() => {
switchTab('login');
// 清空重置表单
resetForm.reset();
}, 1500);
} else {
showMessage(data.msg || '密码重置失败,请检查输入信息!', 'error');
}
})
.catch(error => {
console.error('Error:', error);
showMessage('密码重置请求失败,请稍后重试!', 'error');
})
.finally(() => {
// 恢复按钮状态
submitBtn.textContent = originalText;
submitBtn.disabled = false;
});
}
// 页面加载时检查登录状态
document.addEventListener('DOMContentLoaded', async function() {
const isLoggedIn = await validateToken();
if (isLoggedIn) {
showMessage('您已经登录,正在跳转到首页...', 'info');
setTimeout(() => {
window.location.href = '/';
}, 2000);
}
});
})(); // 立即执行函数结束
</script>