Files
phaten-audio/zh/docs/common/checklogin_form.md
2025-06-13 13:37:50 +08:00

604 lines
16 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.
<style>
.login-modal {
display: none !important;
position: fixed !important;
z-index: 100 !important;
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0,0,0,0.5) !important;
}
.login-modal[style*="block"] {
display: block !important;
}
.login-content {
background-color: #fefefe;
margin: 10% auto;
padding: 20px;
border: 1px solid #888;
width: 400px;
border-radius: 15px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.login-content h2 {
text-align: center;
margin-bottom: 15px;
color: #333;
font-size: 22px;
}
.login-form .login-type {
display: flex;
justify-content: center;
margin-bottom: 12px;
}
.login-form .login-type label {
margin: 0 15px;
cursor: pointer;
font-size: 15px;
display: flex;
align-items: center;
}
.login-form .login-type input[type="radio"] {
margin-right: 5px;
width: auto;
}
.login-form input {
width: 100%;
padding: 10px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 8px;
box-sizing: border-box;
font-size: 15px;
}
.login-form .code-container {
display: flex;
gap: 10px;
margin: 10px 0;
}
.login-form .hint-text {
font-size: 12px;
color: #666;
margin-top: 3px;
margin-bottom: 3px;
text-align: left;
}
.login-form .code-input {
flex: 3;
padding: 10px;
border: 1px solid #ddd;
border-radius: 8px;
box-sizing: border-box;
font-size: 15px;
}
.login-form .send-code-btn {
flex: 1;
min-width: 95px;
padding: 0 8px;
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s ease;
white-space: nowrap;
}
.login-form .send-code-btn:hover {
background-color: #2980b9;
}
.login-form .send-code-btn:disabled {
background-color: #95a5a6;
cursor: not-allowed;
}
.login-form button {
width: 100%;
padding: 10px;
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
margin-top: 12px;
font-size: 16px;
transition: background-color 0.3s ease;
}
.login-form button:hover {
background-color: #2980b9;
}
.close {
float: right;
cursor: pointer;
font-size: 24px;
color: #666;
transition: color 0.3s ease;
}
.close:hover {
color: #333;
}
/* 消息弹出框样式 */
.message-modal {
display: none;
position: fixed;
z-index: 1001;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.message-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 400px;
border-radius: 15px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
text-align: center;
}
.message-content h3 {
margin: 0 0 15px 0;
color: #333;
font-size: 18px;
}
.message-content p {
margin: 15px 0;
color: #666;
line-height: 1.5;
white-space: pre-line;
}
.message-content .success {
color: #27ae60;
}
.message-content .error {
color: #e74c3c;
}
.message-btn {
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
padding: 10px 20px;
cursor: pointer;
font-size: 14px;
margin-top: 10px;
transition: background-color 0.3s ease;
}
.message-btn:hover {
background-color: #2980b9;
}
.close-message {
float: right;
cursor: pointer;
font-size: 24px;
color: #666;
transition: color 0.3s ease;
}
.close-message:hover {
color: #333;
}
/* 下载按钮样式 */
.download-btn {
font-size: 12px !important;
padding: 6px 12px !important;
min-height: auto !important;
line-height: 1.2 !important;
}
.download-btn.loading {
pointer-events: none;
opacity: 0.7;
position: relative;
}
.download-btn.loading::after {
content: "";
position: absolute;
width: 12px;
height: 12px;
top: 50%;
left: 50%;
margin-left: -6px;
margin-top: -6px;
border: 2px solid #ffffff;
border-radius: 50%;
border-top-color: transparent;
animation: button-loading-spinner 1s ease infinite;
}
@keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}
</style>
<!-- 消息弹出框 -->
<div id="messageModal" class="message-modal">
<div class="message-content">
<span class="close-message">&times;</span>
<h3 id="messageTitle">提示</h3>
<p id="messageText"></p>
<button id="messageBtn" class="message-btn">确定</button>
</div>
</div>
<div id="loginModal" class="login-modal">
<div class="login-content">
<span class="close" onclick="closeLoginModal()">&times;</span>
<h2>飞腾云登录/注册</h2>
<form id="loginForm" class="login-form">
<input type="email" id="email" 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>
<div class="hint-text">(首次登录自动注册)</div>
<button type="submit">提交</button>
</form>
</div>
</div>
<script>
// 避免重复声明,使用立即执行函数创建作用域
(function() {
'use strict';
// 定义API的基础URL
const baseUrl = 'https://api.phaten-audio.com/api';
// 获取模态框元素
const modal = document.getElementById("loginModal");
const loginForm = document.getElementById("loginForm");
const sendCodeBtn = document.getElementById("sendCodeBtn");
const emailInput = document.getElementById("email");
let countdownTimer;
// 获取消息弹出框元素
const messageModal = document.getElementById("messageModal");
const messageTitle = document.getElementById("messageTitle");
const messageText = document.getElementById("messageText");
const messageBtn = document.getElementById("messageBtn");
const closeMessage = document.getElementsByClassName("close-message")[0];
// 显示自定义消息弹出框
function showMessage(title, text, type = 'info') {
messageTitle.textContent = title;
messageText.textContent = text;
// 根据类型设置样式
messageText.className = type === 'success' ? 'success' : (type === 'error' ? 'error' : '');
messageModal.style.display = "block";
}
// 关闭消息弹出框
function closeMessageModal() {
messageModal.style.display = "none";
}
// 绑定消息弹出框关闭事件
closeMessage.onclick = closeMessageModal;
messageBtn.onclick = closeMessageModal;
// 添加登录框关闭按钮
function closeLoginModal() {
console.log("用户关闭了登录模态框");
modal.style.display = "none";
// 清除待下载的URL因为用户取消了登录
const pendingUrl = sessionStorage.getItem('pendingDownloadUrl');
if (pendingUrl) {
console.log("清除待下载URL:", pendingUrl);
sessionStorage.removeItem('pendingDownloadUrl');
}
// 恢复下载按钮状态
const downloadBtn = document.getElementById('designDownloadBtn');
if (downloadBtn) {
downloadBtn.classList.remove('loading');
downloadBtn.innerHTML = '下载';
console.log("恢复下载按钮状态");
}
}
// 点击消息模态框外部关闭(只关闭消息框,不关闭登录框)
window.addEventListener('click', function(event) {
if (event.target == messageModal) {
closeMessageModal();
}
// 点击登录框外部也可以关闭
if (event.target == modal) {
closeLoginModal();
}
});
// 检查本地存储中是否有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;
}
}
// 检查登录状态
async function checkLogin(downloadUrl = null) {
// 获取触发按钮并添加loading状态
const downloadBtn = document.getElementById('designDownloadBtn');
if (downloadBtn) {
downloadBtn.classList.add('loading');
downloadBtn.innerHTML = '...';
}
try {
// 检查token是否有效
console.log("开始验证token...");
const token = getLocalToken();
console.log("本地token:", token);
const isLoggedIn = await validateToken();
console.log("验证结果 isLoggedIn:",isLoggedIn);
if (!isLoggedIn) {
// 如果未登录,保存下载链接并显示登录模态框
if (downloadUrl) {
sessionStorage.setItem('pendingDownloadUrl', downloadUrl);
if (modal) {
modal.style.display = "block";
} else {
console.error("modal元素未找到!");
}
}
} else {
// 如果已登录,直接进行下载
if (downloadUrl) {
if (downloadBtn) {
downloadBtn.innerHTML = '下载中...';
}
window.location.href = downloadUrl;
}
}
} catch (error) {
console.error("登录验证出错:", error);
} finally {
// 恢复按钮状态(如果没有跳转的话)
if (downloadBtn && !downloadBtn.innerHTML.includes('下载中')) {
setTimeout(() => {
downloadBtn.classList.remove('loading');
downloadBtn.innerHTML = '下载';
}, 500);
}
}
}
// 发送验证码
sendCodeBtn.onclick = function() {
const contactValue = emailInput.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 => {
if (data.success) {
showMessage('发送成功', '验证码已发送到您的邮箱!', 'success');
} else {
showMessage('发送失败', data.msg || '验证码发送失败,请稍后重试!', 'error');
resetCountdown();
}
})
.catch(error => {
console.error('Error:', error);
showMessage('网络错误', '验证码发送请求失败,请稍后重试!', 'error');
resetCountdown();
});
}
// 验证邮箱格式
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());
}
// 开始倒计时
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 = '发送验证码';
}
// 处理登录表单提交
loginForm.onsubmit = function(e) {
console.log("Form submitted");
e.preventDefault();
const verificationCode = document.getElementById("verificationCode").value;
const contactValue = emailInput.value;
// 发送AJAX请求
fetch(`${baseUrl}/fty/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: "1", // 固定为邮箱类型
username: contactValue,
code: verificationCode
})
})
.then(response => response.json())
.then(data => {
console.log("登录返回",data);
if (data.code==2000) {
// 保存token到本地存储
if (data.data.token) {
saveToken(data.data.token);
}
showMessage('登录成功', '登录成功!', 'success');
// 登录成功后关闭模态框
modal.style.display = "none";
resetCountdown();
// 检查是否有待下载的链接
const pendingDownloadUrl = sessionStorage.getItem('pendingDownloadUrl');
if (pendingDownloadUrl) {
sessionStorage.removeItem('pendingDownloadUrl');
// 延迟一下再跳转,让用户看到成功消息
setTimeout(() => {
if (downloadBtn) {
downloadBtn.innerHTML = '下载中...';
}
window.location.href = pendingDownloadUrl;
}, 1500);
}
} else {
showMessage('登录失败', data.msg || '登录失败,请检查邮箱和验证码!', 'error');
}
})
.catch(error => {
console.error('Error:', error);
showMessage('网络错误', '登录请求失败,请稍后重试!', 'error');
});
}
// ESC键关闭登录框
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
console.log("用户按ESC键关闭登录框");
closeLoginModal();
}
});
// 页面加载时自动验证token
document.addEventListener('DOMContentLoaded', async function() {
// 自动检查登录状态(但不自动弹出登录框)
await validateToken();
// 额外检查modal元素是否正确获取
console.log("页面加载完成modal元素:", modal);
});
// 将需要全局访问的函数暴露到window对象
window.checkLogin = checkLogin;
window.closeLoginModal = closeLoginModal;
})(); // 立即执行函数结束
</script>