Files
zydi-user/center.js
T
2025-01-12 05:13:22 +00:00

812 lines
35 KiB
JavaScript

function i18n(key) {
return lang[selectedLang][key] || key;
}
// 显示用户中心特定部分
async function showUserCenterSection(section) {
try {
const userInfo = await fetchUserInfo();
if (!userInfo) {
alert(lang[selectedLang].pleaseLogin);
window.location.href = 'login.html'; // 重定向到登录页面
return;
}
// 检查邮箱验证状态
const emailVerified = userInfo.email_verified === 'True' || userInfo.email_verified === true;
console.log('Email Verified:', emailVerified); // 打印邮箱验证状态
if (!emailVerified && section !== 'profile') {
alert(lang[selectedLang].pleaseVerifyEmail);
section = 'profile'; // 如果邮箱未验证,强制显示个人资料页面
// showUserCenterSection('profile'); // 跳转到个人资料页面
return;
}
const dashboardContent = document.getElementById('dashboardContent');
const usersContent = document.getElementById('usersContent');
const chatContent = document.getElementById('chatContent');
const featureContent = document.getElementById('featureContent');
const userCenterContent = document.getElementById('userCenterContent');
const pageTitle = document.getElementById('pageTitle');
const showApiDocs = document.getElementById('showApiDocs');
const apiDocsContent = document.getElementById('apiDocsContent');
if (apiDocsContent) apiDocsContent.style.display = 'none';
if (dashboardContent) dashboardContent.style.display = 'none';
if (usersContent) usersContent.style.display = 'none';
if (chatContent) chatContent.style.display = 'none';
if (featureContent) featureContent.style.display = 'none';
if (userCenterContent) userCenterContent.style.display = 'block';
if (showApiDocs) showApiDocs.style.display = 'none';
// 根据选择的部分设置相应的标题
if (pageTitle) {
switch(section) {
case 'profile':
pageTitle.innerText = i18n('personalInfo');
break;
case 'apiKey':
pageTitle.innerText = i18n('apiKeys');
break;
case 'apiUsage':
pageTitle.innerText = i18n('modelCalls');
break;
default:
pageTitle.innerText = i18n('userCenter');
}
}
const navButtons = document.querySelectorAll('.user-center-nav-btn');
const sections = document.querySelectorAll('.user-center-section');
navButtons.forEach(btn => btn.classList.remove('active'));
sections.forEach(sec => sec.classList.remove('active'));
const targetButton = document.querySelector(`.user-center-nav-btn[data-target="${section}"]`);
const targetSection = document.getElementById(`${section}Section`);
if (targetButton) targetButton.classList.add('active');
if (targetSection) targetSection.classList.add('active');
if (section === 'profile') {
loadUserProfile();
} else if (section === 'apiKey') {
loadApiKeys();
} else if (section === 'apiUsage') {
loadapiUsage();
}
} catch (error) {
console.error('Error in showFeature:', error);
alert(lang[selectedLang].errorGettingUserInfo);
}
}
// 将 showUserCenterSection 函数添加到全局作用域
window.showUserCenterSection = showUserCenterSection;
const BASE_URL = 'https://user.obscura.work/user';
function updateAllAvatars(avatarUrl) {
const avatars = document.querySelectorAll('.user-avatar, #currentAvatar');
avatars.forEach(avatar => {
avatar.src = avatarUrl || 'picture/cn__03041_.png';
});
}
// 加载用户个人资料
async function loadUserProfile() {
try {
const response = await fetch(`${BASE_URL}/me`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
if (response.ok) {
const userData = await response.json();
const profileSection = document.getElementById('profileSection');
updateAllAvatars(userData.avatar)
profileSection.innerHTML = `
<div class="profile-container">
<div class="profile-info">
<h3>${i18n("basicInfo")}</h3>
<form id="profileForm">
<div class="form-group">
<label for="username">${i18n("username")}</label>
<input type="text" id="username" value="${userData.username}" readonly>
<p class="field-description">${i18n("usernameDescription")}</p>
</div>
<div class="form-group">
<label for="email">${i18n("email")}</label>
<input type="email" id="email" value="${userData.email}">
<p class="field-description">${i18n("emailDescription")}</p>
</div>
<div class="form-group">
<label for="phone_number">${i18n("phoneNumber")}</label>
<input type="tel" id="phone_number" value="${userData.phone_number}">
</div>
<button type="submit" class="btn-update">${i18n("updateProfile")}</button>
</form>
</div>
<div class="profile-picture">
<img src="${userData.avatar || 'picture/cn__03041_.png'}" alt="用户头像" id="currentAvatar">
<button class="btn-update" onclick="openAvatarModal()">${i18n("editAvatar")}</button>
</div>
</div>
<div class="verification-card">
<h3>${i18n("userVerification")}</h3>
<div class="verification-content">
<p>${i18n("emailVerification")}<span id="emailStatus">${userData.email_verified ? i18n("verified") : i18n("unverified")}</span></p>
${userData.email_verified ? '' : `
<button type="button" id="sendVerificationEmail" class="btn-verify">${i18n("sendVerificationEmail")}</button>
<div id="verificationCodeSection" style="display: none;">
<input type="text" id="verificationCode" name="email_verification_code" autocomplete="off" placeholder="${i18n("enterVerificationCode")}">
<button type="button" id="submitVerificationCode" class="btn-verify">${i18n("submitVerificationCode")}</button>
</div>
`}
</div>
<div class="verification-content" style="margin-top: 15px;">
<p>${i18n("phoneVerification")}<span id="emailStatus">${userData.phone_verified ? i18n("verified") : i18n("unverified")}</span></p>
${userData.phone_verified ? '' : `
<button type="button" id="sendPhoneVerification" class="btn-verify">${i18n("sendPhoneVerification")}</button>
<div id="phoneVerificationCodeSection" style="display: none;">
<input type="text" id="phoneVerificationCode" placeholder="${i18n("enterPhoneVerificationCode")}">
<button type="button" id="submitPhoneVerificationCode" class="btn-verify">${i18n("submitPhoneVerificationCode")}</button>
</div>
`}
</div>
</div>
`;
document.getElementById('profileForm').addEventListener('submit', updateProfile);
if (!userData.email_verified) {
document.getElementById('sendVerificationEmail').addEventListener('click', sendVerificationEmail);
document.getElementById('submitVerificationCode').addEventListener('click', submitVerificationCode);
}
if (!userData.phone_verified) {
document.getElementById('sendPhoneVerification').addEventListener('click', sendPhoneVerification);
document.getElementById('submitPhoneVerificationCode').addEventListener('click', submitPhoneVerificationCode);
}
} else {
console.error(i18n('loadProfileFailed'));
}
} catch (error) {
console.error(i18n('loadProfileError'), error);
}
}
// 提交验证码
async function sendVerificationEmail() {
const sendButton = document.getElementById('sendVerificationEmail');
if (sendButton.disabled) {
return; // 如果按钮已经被禁用,直接返回
}
try {
const response = await fetch(`${BASE_URL}/send-verification-email`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
if (response.ok) {
alert(i18n('verificationEmailSent'));
document.getElementById('verificationCodeSection').style.display = 'block';
// 禁用按钮并开始倒计时
sendButton.disabled = true;
let countdown = 60;
sendButton.textContent = `${i18n('resend')} (${countdown}s)`;
const timer = setInterval(() => {
countdown--;
if (countdown <= 0) {
clearInterval(timer);
sendButton.disabled = false;
sendButton.textContent = i18n('sendVerificationEmail');
} else {
sendButton.textContent = `${i18n('resend')} (${countdown}s)`;
}
}, 1000);
} else {
const errorData = await response.json();
alert(`${i18n('sendVerificationEmailFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('sendVerificationEmailError'), error);
alert(i18n('sendVerificationEmailError'));
}
}
async function submitVerificationCode() {
const verificationCode = document.getElementById('verificationCode').value;
console.log(i18n('submittingVerificationCode'), verificationCode);
try {
const response = await fetch(`${BASE_URL}/verify-email`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `verification_code=${encodeURIComponent(verificationCode)}`
});
if (response.ok) {
alert(i18n('emailVerificationSuccess'));
loadUserProfile();
} else {
const errorData = await response.json();
console.error('Error response:', errorData);
alert(`${i18n('verificationFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('submitVerificationCodeError'), error);
alert(i18n('submitVerificationCodeError'));
}
}
// 新增发送手机验证短信的函数
async function sendPhoneVerification() {
const sendButton = document.getElementById('sendPhoneVerification');
if (sendButton.disabled) {
return;
}
try {
const response = await fetch(`${BASE_URL}/send-phone-verification`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
if (response.ok) {
alert(i18n('verificationSMSSent'));
document.getElementById('phoneVerificationCodeSection').style.display = 'block';
sendButton.disabled = true;
let countdown = 60;
sendButton.textContent = `${i18n('resend')} (${countdown}s)`;
const timer = setInterval(() => {
countdown--;
if (countdown <= 0) {
clearInterval(timer);
sendButton.disabled = false;
sendButton.textContent = i18n('sendPhoneVerification');
} else {
sendButton.textContent = `${i18n('resend')} (${countdown}s)`;
}
}, 1000);
} else {
const errorData = await response.json();
alert(`${i18n('sendVerificationSMSFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('sendVerificationSMSError'), error);
alert(i18n('sendVerificationSMSError'));
}
}
// 新增提交手机验证码的函数
async function submitPhoneVerificationCode() {
const verificationCode = document.getElementById('phoneVerificationCode').value;
try {
const response = await fetch(`${BASE_URL}/verify-phone`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `verification_code=${encodeURIComponent(verificationCode)}`
});
if (response.ok) {
alert(i18n('phoneVerificationSuccess'));
loadUserProfile(); // 重新加载用户资料以更新验证状态
} else {
const errorData = await response.json();
alert(`${i18n('verificationFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('submitPhoneVerificationCodeError'), error);
alert(i18n('submitPhoneVerificationCodeError'));
}
}
// / 打开头像选择模态框
function openAvatarModal() {
const modal = document.createElement('div');
modal.className = 'avatar-modal';
modal.innerHTML = `
<div class="avatar-modal-content">
<h3>${i18n("selectAvatar")}</h3>
<div id="avatarOptions"></div>
<button onclick="closeAvatarModal()">${i18n("close")}</button>
</div>
`;
document.body.appendChild(modal);
loadAvatarOptions();
}
// 加载头像选项
async function loadAvatarOptions() {
try {
const avatars = [
'picture/cn__02504_.png',
'picture/cn__02505_.png',
'picture/cn__02506_.png',
'picture/cn__02507_.png',
'picture/cn__02510_.png',
'picture/cn__02511_.png',
'picture/cn__02512_.png',
'picture/cn__03018_.png',
'picture/cn__03040_.png',
'picture/cn__03041_.png',
'picture/cn__03042_.png',
'picture/cn__03044_.png',
'picture/cn__03059_.png'
];
const avatarOptions = document.getElementById('avatarOptions');
avatarOptions.innerHTML = avatars.map(avatar => `
<img src="${avatar}" alt="头像选项" onclick="selectAvatar('${avatar}')" class="avatar-option">
`).join('');
} catch (error) {
console.error(i18n('loadAvatarOptionsError'), error);
}
}
// 选择头像
function selectAvatar(avatarUrl) {
document.getElementById('currentAvatar').src = avatarUrl;
document.getElementById('userAvatar').src = avatarUrl;
closeAvatarModal();
updateUserAvatar(avatarUrl); // 添加这行来保存头像更改
}
async function updateUserAvatar(avatarUrl) {
try {
const response = await fetch(`${BASE_URL}/me`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ avatar: avatarUrl })
});
if (response.ok) {
console.log(i18n('avatarUpdateSuccess'));
updateAllAvatars(avatarUrl);
} else {
const errorData = await response.json();
console.error(i18n('avatarUpdateFailed'), errorData);
alert(`${i18n('avatarUpdateFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('avatarUpdateError'), error);
alert(i18n('avatarUpdateError'));
}
}
// 关闭头像选择模态框
function closeAvatarModal() {
const modal = document.querySelector('.avatar-modal');
if (modal) {
modal.remove();
}
}
async function updateProfile(event) {
event.preventDefault();
const email = document.getElementById('email').value;
const phone_number = document.getElementById('phone_number').value;
const avatar = document.getElementById('currentAvatar').src;
try {
const response = await fetch(`${BASE_URL}/me`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
},
body: JSON.stringify({ email, phone_number, avatar })
});
if (response.ok) {
alert(i18n('profileUpdateSuccess'));
} else {
const errorData = await response.json();
alert(`${i18n('profileUpdateFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('profileUpdateError'), error);
alert(i18n('profileUpdateError'));
}
}
// 遮蔽 API 密钥
function maskApiKey(key) {
if (!key) return i18n('invalidApiKey');
return key.substring(0, 4) + '*'.repeat(Math.max(0, key.length - 8)) + key.substring(Math.max(0, key.length - 4));
}
// 加载 API 密钥
async function loadApiKeys() {
try {
const response = await fetch(`${BASE_URL}/api-keys`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
'Cache-Control': 'no-cache'
}
});
if (response.ok) {
const apiKeys = await response.json();
const apiKeyContent = document.getElementById('apiKeyContent');
apiKeyContent.innerHTML = `
<table class="api-key-table">
<thead>
<tr>
<th></th>
<th>${i18n("apiKeyTable")}</th>
<th>${i18n("createdAt")}</th>
<th>${i18n("expiresAt")}</th>
<th>${i18n("operation")}</th>
</tr>
</thead>
<tbody id="apiKeyTableBody">
${apiKeys.map((key, index) => {
const actualKey = key.key.replace('api_key:', '');
return `
<tr>
<td>
<i class="fas fa-eye toggle-visibility" onclick="toggleApiKeyVisibility(${index}, '${actualKey}')"></i>
</td>
<td>
<span id="apiKey${index}" class="api-key-value" onclick="copyToClipboard('${actualKey}')">${maskApiKey(actualKey)}</span>
</td>
<td>${new Date(key.created_at).toLocaleString()}</td>
<td>${new Date(key.expires_at).toLocaleString()}</td>
<td>
<button class="btn-delete" onclick="deleteApiKey('${actualKey}')">
<i class="fas fa-trash-alt"></i>
</button>
</td>
</tr>
`;
}).join('')}
</tbody>
</table>
<button class="btn-generate-key" onclick="generateNewApiKey()">${i18n("createNewApiKey")}</button>
<button class="btn-refresh" onclick="refreshApiKeys()">${i18n("refreshList")}</button>
`;
} else {
console.error(i18n('loadApiKeysError'), response.status, response.statusText);
const apiKeyContent = document.getElementById('apiKeyContent');
apiKeyContent.innerHTML = `<p>${i18n('loadApiKeysFailed')}</p>`;
}
} catch (error) {
console.error(i18n('loadApiKeysError'), error);
const apiKeyContent = document.getElementById('apiKeyContent');
apiKeyContent.innerHTML = `<p>${i18n('loadApiKeysFailed')}</p>`;
}
}
// 切换 API 密钥可见性
function toggleApiKeyVisibility(index, fullKey) {
const keyElement = document.getElementById(`apiKey${index}`);
if (keyElement.textContent === fullKey) {
keyElement.textContent = maskApiKey(fullKey);
} else {
keyElement.textContent = fullKey;
}
}
// 复制到剪贴板
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
alert(i18n('apiKeyCopied'));
}).catch(err => {
console.error(i18n('copyTextFailed'), err);
});
}
// 生成新的 API 密钥
async function generateNewApiKey() {
try {
const response = await fetch(`${BASE_URL}/api-keys`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
if (response.ok) {
const newKey = await response.json();
alert(`${i18n('newApiKeyGenerated')}${newKey.api_key}\n${i18n('expirationTime')}${new Date(newKey.expires_at).toLocaleString()}`);
loadApiKeys(); // 重新加载 API 密钥列表
} else {
const errorData = await response.json();
alert(`${i18n('generateNewApiKeyFailed')}${errorData.detail || i18n('unknownError')}`);
}
} catch (error) {
console.error(i18n('generateNewApiKeyError'), error);
alert(i18n('generateNewApiKeyFailed'));
}
}
// 修改 deleteApiKey 函数
async function deleteApiKey(keyId) {
const confirmed = confirm(i18n('confirmDeleteApiKey'));
if (confirmed) {
try {
const encodedKeyId = encodeURIComponent(keyId);
const response = await fetch(`${BASE_URL}/api-keys/${encodedKeyId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
const data = await response.json();
if (response.ok) {
alert(data.message);
} else {
const errorData = await response.json();
alert(`${i18n('deleteApiKeyFailed')}${errorData.detail || i18n('unknownError')}`);
}
if (data.action === 'clear_api_info') {
await loadApiKeys(); // 重新加载API密钥列表
}
} catch (error) {
console.error(i18n('deleteApiKeyError'), error);
alert(i18n('deleteApiKeyFailed'));
} finally {
await loadApiKeys(); // 无论成功与否,都重新加载API密钥列表
}
}
}
// 新增清除缓存并重新加载的函数
// 确保 refreshApiKeys 函数被正确定义
async function refreshApiKeys() {
try {
await fetch(`${BASE_URL}/clear-cache`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
console.log(i18n('cacheCleared'));
} catch (error) {
console.error(i18n('clearCacheFailed'), error);
} finally {
await loadApiKeys();
console.log(i18n('apiKeyListRefreshed'));
}
}
// 加载模型调用信息
async function loadapiUsage() {
try {
const response = await fetch(`${BASE_URL}/api-usage`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
if (response.ok) {
const usageData = await response.json();
const apiUsageContent = document.getElementById('apiUsageContent');
apiUsageContent.innerHTML = `
<div class="usage-tabs">
<h3 id="apiUsageBtn" class="tab-btn active" onclick="showApiUsage()">${i18n("apiUsage")}</h3>
<h3 id="modelUsageBtn" class="tab-btn" onclick="showModelUsage()">${i18n("modelUsage")}</h3>
</div>
<div id="apiUsageTable" class="tab-content active">
<table class="rate-limit-table">
<thead>
<tr>
<th></th>
<th>API KEY</th>
<th>${i18n("tokensUsed")}</th>
<th>${i18n("totalTokens")}</th>
<th>${i18n("lastUsedAt")}</th>
</tr>
</thead>
<tbody id="apiUsageTableBody">
${Object.keys(usageData).length === 0 ?
`<tr><td colspan="5">${i18n("noUsageRecord")}</td></tr>` :
Object.entries(usageData).map(([key, usage], index) => `
<tr>
<td>
<i class="fas fa-eye toggle-visibility" onclick="toggleApiKeyVisibility(${index}, '${key}')"></i>
</td>
<td>
<span id="apiKey${index}" class="api-key-value">${maskApiKey(key)}</span>
</td>
<td>${usage.tokens_used || 0} token</td>
<td>${usage.total_tokens || 0} token</td>
<td>${usage.last_used_at ? new Date(usage.last_used_at).toLocaleString() : i18n("unused")}</td>
</tr>
`).join('')
}
</tbody>
</table>
</div>
<div id="modelUsageTable" class="tab-content">
<p>加载中...</p>
</div>
`;
// 初始显示API使用情况
showApiUsage();
} else {
console.error(i18n('loadModelCallInfoError'), response.status, response.statusText);
const apiUsageContent = document.getElementById('apiUsageContent');
apiUsageContent.innerHTML = `<p>${i18n('loadModelCallInfoFailed')}</p>`;
}
} catch (error) {
console.error(i18n('loadModelCallInfoError'), error);
const apiUsageContent = document.getElementById('apiUsageContent');
apiUsageContent.innerHTML = `
<p>${i18n('loadModelCallInfoFailed')}</p>
<button onclick="loadapiUsage()">${i18n('reload')}</button>
`;
}
}
// 显示 API 使用情况
function showApiUsage() {
document.getElementById('apiUsageBtn').classList.add('active');
document.getElementById('modelUsageBtn').classList.remove('active');
document.getElementById('apiUsageTable').classList.add('active');
document.getElementById('modelUsageTable').classList.remove('active');
// 添加动画效果
document.getElementById('apiUsageTable').style.animation = 'none';
setTimeout(() => {
document.getElementById('apiUsageTable').style.animation = 'fadeIn 0.5s ease-in-out';
}, 10);
}
// 显示模型使用情况
async function showModelUsage() {
document.getElementById('apiUsageBtn').classList.remove('active');
document.getElementById('modelUsageBtn').classList.add('active');
document.getElementById('apiUsageTable').classList.remove('active');
document.getElementById('modelUsageTable').classList.add('active');
// 添加动画效果
document.getElementById('modelUsageTable').style.animation = 'none';
setTimeout(() => {
document.getElementById('modelUsageTable').style.animation = 'fadeIn 0.5s ease-in-out';
}, 10);
// 加载模型使用情况数据
try {
const response = await fetch(`${BASE_URL}/model-usage`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
});
if (response.ok) {
const modelUsageData = await response.json();
const modelUsageTable = document.getElementById('modelUsageTable');
modelUsageTable.innerHTML = `
<table class="rate-limit-table">
<thead>
<tr>
<th>${i18n("modelName")}</th>
<th>${i18n("lastCallTime")}</th>
<th>${i18n("usage")}</th>
</tr>
</thead>
<tbody>
${Object.entries(modelUsageData).map(([model, usage]) => `
<tr>
<td>${model}</td>
<td>${usage.last_called_at ? new Date(usage.last_called_at).toLocaleString() : '未使用'}</td>
<td>${usage.calls} token</td>
</tr>
`).join('')}
</tbody>
</table>
`;
} else {
console.error(i18n('loadModelUsageFailed'), response.status, response.statusText);
}
} catch (error) {
console.error(i18n('loadModelUsageError'), error);
document.getElementById('modelUsageTable').innerHTML = `
<p>${i18n('loadModelUsageFailed')}</p>
`;
}
}
// 初始化用户中心
function initUserCenter() {
const navButtons = document.querySelectorAll('.user-center-nav-btn');
navButtons.forEach(button => {
button.addEventListener('click', () => {
const target = button.getAttribute('data-target');
showUserCenterSection(target);
});
});
// 加载用户信息并更新头像
fetch(`${BASE_URL}/me`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
}
})
.then(response => response.json())
.then(userData => {
updateAllAvatars(userData.avatar);
if (!userData.email_verified) {
const sendVerificationEmailBtn = document.getElementById('sendVerificationEmail');
const submitVerificationCodeBtn = document.getElementById('submitVerificationCode');
if (sendVerificationEmailBtn) {
sendVerificationEmailBtn.addEventListener('click', sendVerificationEmail);
}
if (submitVerificationCodeBtn) {
submitVerificationCodeBtn.addEventListener('click', submitVerificationCode);
}
}
})
.catch(error => console.error(i18n('getUserInfoFailed'), error));
}
// 页面加载完成后初始化用户中心
window.addEventListener('load', initUserCenter);
// 将 showUserCenterSection 函数添加到全局作用域
window.showUserCenterSection = showUserCenterSection;
window.generateNewApiKey = generateNewApiKey;
window.deleteApiKey = deleteApiKey;
window.copyToClipboard = copyToClipboard;
window.refreshApiKeys = refreshApiKeys;
window.loadapiUsage = loadapiUsage;
window.showApiUsage = showApiUsage;
window.showModelUsage = showModelUsage;
window.toggleApiKeyVisibility = toggleApiKeyVisibility;
window.openAvatarModal = openAvatarModal;
window.selectAvatar = selectAvatar;
window.closeAvatarModal = closeAvatarModal;
window.showUserCenterSection = showUserCenterSection;
window.sendPhoneVerification = sendPhoneVerification;
window.submitPhoneVerificationCode = submitPhoneVerificationCode;
window.sendVerificationEmail = sendVerificationEmail;
window.submitVerificationCode = submitVerificationCode;
// 获取用户信息的函数
async function fetchUserInfo() {
try {
const token = localStorage.getItem('access_token');
if (!token) {
console.error(i18n('noAccessTokenFound'));
return null;
}
const response = await fetch(`${BASE_URL}/me`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
console.error(i18n('failedToFetchUserInfo'));
return null;
}
const userInfo = await response.json();
return userInfo;
} catch (error) {
console.error(i18n('errorFetchingUserInfo'), error);
// 可以在这里处理错误,比如清除 token 并重定向到登录页面
localStorage.removeItem('access_token');
window.location.href = 'login.html'; // 重定向到登录页面
return null;
}
}