feat: 完成多多畅职就业服务平台核心功能开发
主要更新: - ✅ 完成主题配色从暗色到亮蓝白配色的全面转换 - ✅ 实现高薪岗位页面及后端API集成 - ✅ 完成登录注册页面及认证系统 - ✅ 实现预招录确认功能 - ✅ 添加数据库管理和维护工具脚本 - ✅ 优化错误处理和用户体验 核心功能: 1. 首页 (index.html) - 3D地球、专业分类、过渡岗位 2. 高薪岗位页面 (high.html) - 岗位详情、预招录确认、成功案例 3. 登录注册 (auth.html) - 用户认证、专业分类选择 4. 后端API - RESTful接口,JWT认证,MySQL数据库 技术栈: - 前端:Three.js, GSAP, 原生JavaScript - 后端:Node.js, Express, MySQL - 认证:JWT, bcrypt - 样式:自定义CSS,响应式设计 数据库工具: - kill-by-ids.js - 批量终止MySQL进程 - unlock-all-tables.js - 解锁数据库表 - init-db.js - 初始化数据库 - 其他管理脚本 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
350
js/auth.js
Normal file
350
js/auth.js
Normal file
@@ -0,0 +1,350 @@
|
||||
/**
|
||||
* 用户认证逻辑
|
||||
* 处理登录、注册表单的提交和验证
|
||||
*/
|
||||
|
||||
// API配置
|
||||
const API_BASE_URL = 'http://192.168.1.17:8080/api';
|
||||
const AUTH_TOKEN_KEY = 'duoduo_auth_token';
|
||||
const USER_INFO_KEY = 'duoduo_user_info';
|
||||
|
||||
// 专业大类数据
|
||||
let professionalCategories = [];
|
||||
|
||||
/**
|
||||
* 加载专业大类数据
|
||||
*/
|
||||
async function loadProfessionalCategories() {
|
||||
try {
|
||||
const response = await fetch('/专业大类.json');
|
||||
professionalCategories = await response.json();
|
||||
|
||||
// 填充注册表单的下拉选择框
|
||||
const selectElement = document.getElementById('register-professional-category');
|
||||
if (selectElement) {
|
||||
professionalCategories.forEach(category => {
|
||||
const option = document.createElement('option');
|
||||
option.value = category.大类代码;
|
||||
option.textContent = category.大类名称;
|
||||
selectElement.appendChild(option);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载专业大类失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 显示错误信息
|
||||
*/
|
||||
function showError(elementId, message) {
|
||||
const errorElement = document.getElementById(elementId);
|
||||
errorElement.textContent = message;
|
||||
errorElement.style.display = 'block';
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示成功信息
|
||||
*/
|
||||
function showSuccess(elementId, message) {
|
||||
const successElement = document.getElementById(elementId);
|
||||
successElement.textContent = message;
|
||||
successElement.style.display = 'block';
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏消息
|
||||
*/
|
||||
function hideMessage(elementId) {
|
||||
const element = document.getElementById(elementId);
|
||||
element.textContent = '';
|
||||
element.style.display = 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏所有消息
|
||||
*/
|
||||
function hideAllMessages() {
|
||||
hideMessage('login-error-msg');
|
||||
hideMessage('register-error-msg');
|
||||
hideMessage('register-success-msg');
|
||||
}
|
||||
|
||||
// ==================== 表单验证 ====================
|
||||
|
||||
/**
|
||||
* 验证登录表单
|
||||
*/
|
||||
function validateLoginForm(username, password) {
|
||||
if (!username || !password) {
|
||||
return '用户名和密码不能为空';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证注册表单
|
||||
*/
|
||||
function validateRegisterForm(username, password, confirmPassword, email, phone) {
|
||||
// 真实姓名验证
|
||||
if (!username) {
|
||||
return '真实姓名不能为空';
|
||||
}
|
||||
if (username.length < 2 || username.length > 10) {
|
||||
return '姓名长度必须在2-10个字符之间';
|
||||
}
|
||||
|
||||
// 密码验证
|
||||
if (!password) {
|
||||
return '密码不能为空';
|
||||
}
|
||||
if (password.length < 6) {
|
||||
return '密码长度至少为6个字符';
|
||||
}
|
||||
|
||||
// 确认密码验证
|
||||
if (password !== confirmPassword) {
|
||||
return '两次输入的密码不一致';
|
||||
}
|
||||
|
||||
// 邮箱验证(如果填写)
|
||||
if (email && email.trim() !== '') {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(email)) {
|
||||
return '邮箱格式不正确';
|
||||
}
|
||||
}
|
||||
|
||||
// 手机号验证(必填)
|
||||
if (!phone || phone.trim() === '') {
|
||||
return '手机号码不能为空';
|
||||
}
|
||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||
if (!phoneRegex.test(phone)) {
|
||||
return '手机号格式不正确';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==================== 登录功能 ====================
|
||||
|
||||
/**
|
||||
* 处理用户登录
|
||||
*/
|
||||
async function handleLogin() {
|
||||
// 隐藏之前的错误信息
|
||||
hideAllMessages();
|
||||
|
||||
// 获取表单数据
|
||||
const username = document.getElementById('login-username').value.trim();
|
||||
const password = document.getElementById('login-password').value;
|
||||
|
||||
// 前端验证
|
||||
const validationError = validateLoginForm(username, password);
|
||||
if (validationError) {
|
||||
showError('login-error-msg', validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
// 禁用提交按钮,显示加载状态
|
||||
const submitBtn = document.getElementById('login-submit-btn');
|
||||
const originalText = submitBtn.textContent;
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '登录中...';
|
||||
submitBtn.style.opacity = '0.7';
|
||||
|
||||
try {
|
||||
// 调用登录API
|
||||
const response = await fetch(`${API_BASE_URL}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ username, password })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
// 保存token和用户信息到localStorage
|
||||
localStorage.setItem(AUTH_TOKEN_KEY, data.data.token);
|
||||
localStorage.setItem(USER_INFO_KEY, JSON.stringify(data.data.user));
|
||||
|
||||
// 登录成功,跳转到首页
|
||||
window.location.href = 'index.html';
|
||||
} else {
|
||||
// 显示后端返回的错误信息
|
||||
showError('login-error-msg', data.message || '登录失败,请重试');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('登录错误:', error);
|
||||
showError('login-error-msg', '网络错误,请检查服务器是否运行');
|
||||
} finally {
|
||||
// 恢复按钮状态
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalText;
|
||||
submitBtn.style.opacity = '1';
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 注册功能 ====================
|
||||
|
||||
/**
|
||||
* 处理用户注册
|
||||
*/
|
||||
async function handleRegister() {
|
||||
// 隐藏之前的消息
|
||||
hideAllMessages();
|
||||
|
||||
// 获取表单数据
|
||||
const username = document.getElementById('register-username').value.trim();
|
||||
const password = document.getElementById('register-password').value;
|
||||
const confirmPassword = document.getElementById('register-password-confirm').value;
|
||||
const email = document.getElementById('register-email').value.trim();
|
||||
const phone = document.getElementById('register-phone').value.trim();
|
||||
const professionalCategoryCode = document.getElementById('register-professional-category').value;
|
||||
|
||||
// 前端验证
|
||||
const validationError = validateRegisterForm(username, password, confirmPassword, email, phone);
|
||||
if (validationError) {
|
||||
showError('register-error-msg', validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
// 禁用提交按钮,显示加载状态
|
||||
const submitBtn = document.getElementById('register-submit-btn');
|
||||
const originalText = submitBtn.textContent;
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '注册中...';
|
||||
submitBtn.style.opacity = '0.7';
|
||||
|
||||
try {
|
||||
// 调用注册API
|
||||
const requestBody = { username, password };
|
||||
if (email) requestBody.email = email;
|
||||
if (phone) requestBody.phone = phone;
|
||||
// 如果选择了专业大类,添加到请求体
|
||||
if (professionalCategoryCode) {
|
||||
requestBody.professional_category_code = professionalCategoryCode;
|
||||
const category = professionalCategories.find(c => c.大类代码 === professionalCategoryCode);
|
||||
if (category) {
|
||||
requestBody.professional_category = category.大类名称;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/auth/register`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
// 显示成功提示
|
||||
showSuccess('register-success-msg', '注册成功!正在跳转到登录...');
|
||||
|
||||
// 2秒后切换到登录表单并预填充用户名
|
||||
setTimeout(() => {
|
||||
// 切换到登录表单
|
||||
switchToLogin();
|
||||
|
||||
// 预填充用户名
|
||||
document.getElementById('login-username').value = username;
|
||||
|
||||
// 清空注册表单
|
||||
document.getElementById('register-username').value = '';
|
||||
document.getElementById('register-password').value = '';
|
||||
document.getElementById('register-password-confirm').value = '';
|
||||
document.getElementById('register-email').value = '';
|
||||
document.getElementById('register-phone').value = '';
|
||||
|
||||
hideAllMessages();
|
||||
}, 2000);
|
||||
} else {
|
||||
// 显示后端返回的错误信息
|
||||
showError('register-error-msg', data.message || '注册失败,请重试');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注册错误:', error);
|
||||
showError('register-error-msg', '网络错误,请检查服务器是否运行');
|
||||
} finally {
|
||||
// 恢复按钮状态
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalText;
|
||||
submitBtn.style.opacity = '1';
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 表单切换功能 ====================
|
||||
|
||||
/**
|
||||
* 切换到注册表单
|
||||
*/
|
||||
function switchToRegister() {
|
||||
hideAllMessages();
|
||||
|
||||
const loginContainer = document.getElementById('login-form-container');
|
||||
const registerContainer = document.getElementById('register-form-container');
|
||||
|
||||
// 隐藏登录
|
||||
loginContainer.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
loginContainer.classList.add('hidden');
|
||||
// 显示注册
|
||||
registerContainer.classList.remove('hidden');
|
||||
registerContainer.classList.add('fade-in');
|
||||
registerContainer.style.opacity = '1';
|
||||
}, 300);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换到登录表单
|
||||
*/
|
||||
function switchToLogin() {
|
||||
hideAllMessages();
|
||||
|
||||
const loginContainer = document.getElementById('login-form-container');
|
||||
const registerContainer = document.getElementById('register-form-container');
|
||||
|
||||
// 隐藏注册
|
||||
registerContainer.classList.remove('fade-in');
|
||||
registerContainer.style.opacity = '0';
|
||||
|
||||
setTimeout(() => {
|
||||
registerContainer.classList.add('hidden');
|
||||
registerContainer.style.opacity = '1';
|
||||
|
||||
// 显示登录
|
||||
loginContainer.classList.remove('hidden');
|
||||
loginContainer.style.opacity = '1';
|
||||
loginContainer.classList.add('fade-in');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// ==================== 页面初始化 ====================
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// 加载专业大类数据
|
||||
loadProfessionalCategories();
|
||||
|
||||
// 检查是否已登录
|
||||
const token = localStorage.getItem(AUTH_TOKEN_KEY);
|
||||
if (token) {
|
||||
// 已登录,直接跳转到首页
|
||||
window.location.href = 'index.html';
|
||||
return;
|
||||
}
|
||||
|
||||
// 绑定切换按钮事件
|
||||
document.getElementById('switch-to-register').addEventListener('click', switchToRegister);
|
||||
document.getElementById('switch-to-login').addEventListener('click', switchToLogin);
|
||||
|
||||
// 绑定表单提交事件(通过form的onsubmit已经绑定,这里只是确保)
|
||||
// 表单已通过内联 onsubmit 绑定
|
||||
});
|
||||
@@ -91,15 +91,15 @@ export class ListInterface {
|
||||
card.innerHTML = `
|
||||
<div class="h-40 w-full overflow-hidden relative">
|
||||
<img src="${company.cover}" class="w-full h-full object-cover" alt="${company.shortName}">
|
||||
<div class="absolute bottom-0 left-0 w-full h-1/2 bg-gradient-to-t from-gray-900 to-transparent"></div>
|
||||
<div class="absolute bottom-0 left-0 w-full h-1/2 bg-gradient-to-t from-slate-900 to-transparent"></div>
|
||||
</div>
|
||||
<div class="p-5 text-white">
|
||||
<div class="p-5 text-slate-900">
|
||||
<h3 class="font-bold text-lg mb-2">${company.shortName}</h3>
|
||||
<div class="flex flex-wrap gap-2 mb-3">${tagsHtml}</div>
|
||||
<p class="text-xs text-gray-400 line-clamp-2 mb-3">${company.intro}</p>
|
||||
<div class="pt-3 border-t border-white/10 flex justify-between items-center">
|
||||
<span class="text-xs text-gray-500">热招: ${jobsPreview}...</span>
|
||||
<span class="text-cyan-400 text-xs font-bold">详情 →</span>
|
||||
<p class="text-xs text-slate-600 line-clamp-2 mb-3">${company.intro}</p>
|
||||
<div class="pt-3 border-t border-slate-200 flex justify-between items-center">
|
||||
<span class="text-xs text-slate-600">热招: ${jobsPreview}...</span>
|
||||
<span class="text-blue-600 text-xs font-bold">详情 →</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -113,9 +113,9 @@ export class MapInterface {
|
||||
const breadcrumb = document.getElementById('breadcrumb-container');
|
||||
if (breadcrumb) {
|
||||
breadcrumb.innerHTML = `
|
||||
<span class="hover:text-white cursor-pointer transition" onclick="window.resetMapToChina()">全国</span>
|
||||
<span class="mx-2 text-gray-600">/</span>
|
||||
<span class="text-cyan-400 font-bold">${provinceInfo.name}</span>
|
||||
<span class="hover:text-blue-600 cursor-pointer transition" onclick="window.resetMapToChina()">全国</span>
|
||||
<span class="mx-2 text-slate-400">/</span>
|
||||
<span class="text-blue-600 font-bold">${provinceInfo.name}</span>
|
||||
`;
|
||||
breadcrumb.classList.remove('hidden');
|
||||
}
|
||||
@@ -192,18 +192,18 @@ export class MapInterface {
|
||||
return {
|
||||
name: name,
|
||||
itemStyle: {
|
||||
// 有数据的区域:金黄色高亮
|
||||
areaColor: hasData ? 'rgba(251, 191, 36, 0.35)' : 'rgba(11, 16, 38, 0.8)',
|
||||
borderColor: hasData ? '#fbbf24' : '#1e293b',
|
||||
borderWidth: hasData ? 2 : 0.5
|
||||
// 有数据的区域:深蓝色高亮
|
||||
areaColor: hasData ? 'rgba(2, 132, 199, 0.3)' : '#f1f5f9',
|
||||
borderColor: hasData ? '#0284c7' : '#cbd5e1',
|
||||
borderWidth: hasData ? 2 : 1
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
// 鼠标悬停:更亮的金黄色
|
||||
areaColor: hasData ? 'rgba(251, 191, 36, 0.6)' : 'rgba(30, 41, 59, 0.9)'
|
||||
// 鼠标悬停:浅蓝色
|
||||
areaColor: hasData ? '#bae6fd' : 'rgba(241, 245, 249, 0.9)'
|
||||
},
|
||||
label: {
|
||||
color: hasData ? '#fff' : '#94a3b8',
|
||||
color: hasData ? '#0369a1' : '#64748b',
|
||||
fontWeight: hasData ? 'bold' : 'normal'
|
||||
}
|
||||
},
|
||||
@@ -224,12 +224,12 @@ export class MapInterface {
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
color: '#94a3b8',
|
||||
color: '#64748b', // 改为深灰色,适配亮色背景
|
||||
fontSize: isMobile ? 8 : 10 // 移动端使用更小字体
|
||||
},
|
||||
itemStyle: {
|
||||
areaColor: '#0f172a',
|
||||
borderColor: '#1e293b'
|
||||
areaColor: '#f1f5f9', // 极浅的蓝灰色
|
||||
borderColor: '#cbd5e1' // 省份边界线
|
||||
},
|
||||
select: { disabled: true }
|
||||
},
|
||||
|
||||
220
js/utils/auth-helper.js
Normal file
220
js/utils/auth-helper.js
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* 认证工具模块
|
||||
* 用于其他页面检查登录状态、获取用户信息、退出登录等
|
||||
*/
|
||||
|
||||
const AuthHelper = {
|
||||
// 配置常量
|
||||
TOKEN_KEY: 'duoduo_auth_token',
|
||||
USER_INFO_KEY: 'duoduo_user_info',
|
||||
API_BASE_URL: 'http://192.168.1.17:8080/api',
|
||||
|
||||
/**
|
||||
* 获取存储的token
|
||||
* @returns {string|null} token字符串或null
|
||||
*/
|
||||
getToken() {
|
||||
return localStorage.getItem(this.TOKEN_KEY);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取存储的用户信息
|
||||
* @returns {Object|null} 用户信息对象或null
|
||||
*/
|
||||
getUserInfo() {
|
||||
const userInfo = localStorage.getItem(this.USER_INFO_KEY);
|
||||
return userInfo ? JSON.parse(userInfo) : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查是否已登录
|
||||
* @returns {boolean} 是否已登录
|
||||
*/
|
||||
isLoggedIn() {
|
||||
return !!this.getToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* 清除所有认证信息并跳转到登录页
|
||||
*/
|
||||
logout() {
|
||||
localStorage.removeItem(this.TOKEN_KEY);
|
||||
localStorage.removeItem(this.USER_INFO_KEY);
|
||||
window.location.href = 'auth.html';
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证token是否有效
|
||||
* 调用后端API验证token,如果无效则清除登录状态
|
||||
* @returns {Promise<boolean>} token是否有效
|
||||
*/
|
||||
async validateToken() {
|
||||
const token = this.getToken();
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.API_BASE_URL}/auth/me`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
// 更新用户信息
|
||||
localStorage.setItem(this.USER_INFO_KEY, JSON.stringify(data.data));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Token无效,清除登录状态
|
||||
this.logout();
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Token验证失败:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 路由守卫:保护需要登录的页面
|
||||
* 如果未登录则跳转到登录页
|
||||
* @param {string} redirectUrl 跳转的登录页URL,默认为auth.html
|
||||
* @returns {boolean} 是否已登录
|
||||
*/
|
||||
requireAuth(redirectUrl = 'auth.html') {
|
||||
if (!this.isLoggedIn()) {
|
||||
window.location.href = redirectUrl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取带认证头的fetch配置
|
||||
* @param {Object} options fetch的配置对象
|
||||
* @returns {Object} 包含Authorization头的配置对象
|
||||
*/
|
||||
getAuthHeaders(options = {}) {
|
||||
const token = this.getToken();
|
||||
|
||||
return {
|
||||
...options,
|
||||
headers: {
|
||||
...options.headers,
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* 发送认证请求的封装方法
|
||||
* @param {string} url 请求URL
|
||||
* @param {Object} options fetch配置
|
||||
* @returns {Promise<Object>} 响应数据
|
||||
*/
|
||||
async fetchWithAuth(url, options = {}) {
|
||||
const response = await fetch(url, this.getAuthHeaders(options));
|
||||
|
||||
// 如果返回401未授权,清除登录状态并跳转
|
||||
if (response.status === 401) {
|
||||
this.logout();
|
||||
return null;
|
||||
}
|
||||
|
||||
return response.json();
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取当前用户信息(从服务器获取最新)
|
||||
* @returns {Promise<Object|null>} 用户信息或null
|
||||
*/
|
||||
async getCurrentUser() {
|
||||
try {
|
||||
const data = await this.fetchWithAuth(`${this.API_BASE_URL}/auth/me`);
|
||||
|
||||
if (data && data.success) {
|
||||
// 更新本地存储的用户信息
|
||||
localStorage.setItem(this.USER_INFO_KEY, JSON.stringify(data.data));
|
||||
return data.data;
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新用户资料
|
||||
* @param {Object} profileData 要更新的资料数据
|
||||
* @returns {Promise<boolean>} 是否更新成功
|
||||
*/
|
||||
async updateProfile(profileData) {
|
||||
try {
|
||||
const data = await this.fetchWithAuth(`${this.API_BASE_URL}/auth/profile`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(profileData)
|
||||
});
|
||||
|
||||
if (data && data.success) {
|
||||
// 更新成功后刷新用户信息
|
||||
await this.getCurrentUser();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('更新资料失败:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 在页面中显示用户名
|
||||
* @param {string} elementId 要显示用户名的元素ID
|
||||
*/
|
||||
displayUsername(elementId) {
|
||||
const userInfo = this.getUserInfo();
|
||||
if (userInfo && userInfo.username) {
|
||||
const element = document.getElementById(elementId);
|
||||
if (element) {
|
||||
element.textContent = userInfo.username;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 在页面中显示用户完整信息
|
||||
* @param {Object} elementIds 元素ID映射对象 {username: 'username-el', email: 'email-el', ...}
|
||||
*/
|
||||
displayUserInfo(elementIds) {
|
||||
const userInfo = this.getUserInfo();
|
||||
if (!userInfo) return;
|
||||
|
||||
for (const [field, elementId] of Object.entries(elementIds)) {
|
||||
const element = document.getElementById(elementId);
|
||||
if (element && userInfo[field]) {
|
||||
element.textContent = userInfo[field];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 如果在浏览器环境中,暴露到全局
|
||||
if (typeof window !== 'undefined') {
|
||||
window.AuthHelper = AuthHelper;
|
||||
}
|
||||
|
||||
// 支持ES6模块导出
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = AuthHelper;
|
||||
}
|
||||
@@ -196,17 +196,17 @@ function updateMenuHighlight(activePageId) {
|
||||
const target = link.dataset.target;
|
||||
|
||||
if (target === activePageId) {
|
||||
// 激活状态:白色粗体
|
||||
link.classList.remove('text-gray-400');
|
||||
link.classList.add('text-white', 'font-bold');
|
||||
// 激活状态:深色粗体
|
||||
link.classList.remove('text-slate-600');
|
||||
link.classList.add('text-slate-900', 'font-bold');
|
||||
} else if (target === 'app') {
|
||||
// 内推平台保持青色
|
||||
link.classList.remove('text-white', 'font-bold');
|
||||
link.classList.add('text-cyan-400');
|
||||
// 内推平台保持蓝色
|
||||
link.classList.remove('text-slate-900', 'font-bold');
|
||||
link.classList.add('text-blue-600');
|
||||
} else {
|
||||
// 非激活状态:灰色
|
||||
link.classList.remove('text-white', 'font-bold');
|
||||
link.classList.add('text-gray-400');
|
||||
link.classList.remove('text-slate-900', 'font-bold');
|
||||
link.classList.add('text-slate-600');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user