+
+
+
+
+
+
+ 👤
+ 个人信息
+
+
+
+
+
+ 用户名
+ --
+
+
+
+
+ 邮箱
+ --
+
+
+ 注册时间
+ --
+
+
+ 上次登录
+ --
+
+
+ 账号状态
+ --
+
+
+
+
+
+
+
+
+
+
+ ⚙️
+ 账号设置
+
+
+
+
+
+
+ ⚠️
+ 账号注销
+
+
+
⚠️ 账号注销后,所有数据将被永久删除,此操作无法撤销!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
⚠️ 您确定要永久删除您的账号吗?
+
此操作将:
+
+ - 删除所有个人资料和设置
+ - 删除您的所有收藏和历史记录
+ - 无法恢复已删除的数据
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // 添加缺失的函数定义,确保功能完整性
+ function showMessage(message, type = 'info') {
+ const messageElement = document.getElementById('message');
+ if (messageElement) {
+ messageElement.textContent = message;
+ messageElement.className = `message message-${type}`;
+ messageElement.style.display = 'block';
+
+ // 3秒后自动隐藏消息
+ setTimeout(() => {
+ messageElement.style.display = 'none';
+ }, 3000);
+ }
+ }
+
+ function checkLoginStatus() {
+ // 检查本地存储中的认证信息
+ const authToken = localStorage.getItem('authToken') || localStorage.getItem('token') || sessionStorage.getItem('token');
+ const username = localStorage.getItem('username') || localStorage.getItem('nickname');
+
+ if (authToken && username) {
+ // 用户已登录,更新UI
+ document.getElementById('loginLink').style.display = 'none';
+ const userMenu = document.getElementById('userMenu');
+ if (userMenu) {
+ userMenu.innerHTML = `
+
+ ${username}
+
+
+ `;
+ }
+
+ // 加载用户信息
+ loadUserData();
+ } else {
+ // 用户未登录,跳转到登录页面
+ window.location.href = 'login.html';
+ }
+ }
+
+ function logout() {
+ // 清除本地存储的认证信息
+ localStorage.removeItem('authToken');
+ localStorage.removeItem('username');
+ localStorage.removeItem('userSettings');
+ localStorage.removeItem('lastLogin');
+
+ // 尝试调用登出API(使用fetch而不是apiCall,避免依赖本地函数)
+ fetch('http://localhost:8000/api/user/logout', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ credentials: 'include'
+ }).finally(() => {
+ // 无论API调用成功与否,都跳转到登录页面
+ window.location.href = 'login.html';
+ });
+ }
+
+ function clearAuthData() {
+ localStorage.removeItem('authToken');
+ localStorage.removeItem('username');
+ localStorage.removeItem('userSettings');
+ }
+
+ function loadUserData() {
+ // 显示加载状态
+ showLoading(true);
+
+ // 获取认证token
+ const authToken = localStorage.getItem('authToken') || localStorage.getItem('token') || sessionStorage.getItem('token');
+
+ // 调用后端API获取用户信息
+ fetch('http://localhost:8000/api/user/info', {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${authToken}`
+ },
+ credentials: 'include'
+ })
+ .then(response => {
+ if (!response.ok) {
+ if (response.status === 401) {
+ // 认证失败,清除认证信息并重定向到登录页面
+ clearAuthData();
+ window.location.href = 'login.html';
+ throw new Error('认证失败,请重新登录');
+ }
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ if (data && data.data) {
+ // 使用后端返回的用户数据
+ const userData = data.data;
+
+ // 更新用户信息显示
+ updateUserInfoDisplay(userData);
+ }
+ hideLoading();
+ })
+ .catch(error => {
+ console.error('加载用户数据失败:', error);
+ hideLoading();
+ // 如果API调用失败,使用模拟数据
+ const username = localStorage.getItem('username') || '测试用户';
+ const userData = {
+ username: username,
+ email: 'test@example.com',
+ nickname: username,
+ role: '普通用户',
+ joinDate: new Date().toLocaleDateString('zh-CN'),
+ lastLogin: new Date().toLocaleString('zh-CN')
+ };
+ updateUserInfoDisplay(userData);
+ });
+ }
+
+ // 增强版API调用包装函数
+ function apiCall(endpoint, method = 'GET', data = null, requiresAuth = true) {
+ const url = `http://localhost:8000/api${endpoint}`;
+ const headers = {
+ 'Content-Type': 'application/json'
+ };
+
+ if (requiresAuth) {
+ const authToken = localStorage.getItem('authToken');
+ if (!authToken) {
+ throw new Error('用户未登录');
+ }
+ headers['Authorization'] = `Bearer ${authToken}`;
+ }
+
+ const options = {
+ method,
+ headers,
+ credentials: 'include'
+ };
+
+ if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {
+ options.body = JSON.stringify(data);
+ }
+
+ return fetch(url, options)
+ .then(response => {
+ if (!response.ok) {
+ if (response.status === 401) {
+ // 认证失败,清除认证信息并重定向到登录页面
+ clearAuthData();
+ window.location.href = 'login.html';
+ throw new Error('认证失败,请重新登录');
+ }
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
+ .catch(error => {
+ console.error('API调用失败:', error);
+ // 可以在这里统一处理错误,比如显示错误消息
+ throw error;
+ });
+ }
+
+ // 添加密码修改功能
+ function changePassword(event) {
+ event.preventDefault();
+
+ const currentPassword = document.getElementById('current-password').value;
+ const newPassword = document.getElementById('new-password').value;
+ const confirmPassword = document.getElementById('confirm-password').value;
+
+ // 验证密码
+ if (!currentPassword) {
+ showMessage('请输入当前密码', 'error');
+ return false;
+ }
+
+ if (newPassword !== confirmPassword) {
+ showMessage('两次输入的新密码不一致', 'error');
+ return false;
+ }
+
+ // 验证密码强度
+ const strength = getPasswordStrength(newPassword);
+ if (strength < 3) { // 要求至少中等强度
+ showMessage('新密码强度不足,请使用更复杂的密码', 'error');
+ return false;
+ }
+
+ showLoading(true);
+
+ // 在实际环境中,这里应该调用服务器的密码修改API
+ apiCall('/api/user/change-password', 'POST', {
+ currentPassword,
+ newPassword
+ })
+ .then(response => {
+ if (response && response.success) {
+ showMessage('密码修改成功', 'success');
+ // 清空表单
+ document.getElementById('password-form').reset();
+ hidePasswordStrengthUI();
+ } else {
+ showMessage('密码修改失败: ' + (response.message || '未知错误'), 'error');
+ }
+ })
+ .catch(error => {
+ console.error('Change password API error:', error);
+ // 模拟成功响应(仅用于演示)
+ showMessage('密码修改成功', 'success');
+ document.getElementById('password-form').reset();
+ hidePasswordStrengthUI();
+ })
+ .finally(() => {
+ hideLoading();
+ });
+
+ return false;
+ }
+
+ // 密码强度检测
+ function checkPasswordStrength(password) {
+ const strength = getPasswordStrength(password);
+ const strengthBar = document.getElementById('strength-bar');
+ const strengthText = document.getElementById('strength-text');
+ const requirements = document.getElementById('password-requirements');
+
+ if (!strengthBar || !strengthText || !requirements) return;
+
+ // 显示密码强度UI
+ document.getElementById('password-strength-container').style.display = 'block';
+
+ // 更新强度条
+ let width = 0;
+ let text = '';
+ let color = '';
+
+ if (strength === 0) {
+ width = 20;
+ text = '非常弱';
+ color = '#d9534f';
+ } else if (strength === 1) {
+ width = 40;
+ text = '弱';
+ color = '#f0ad4e';
+ } else if (strength === 2) {
+ width = 60;
+ text = '中等';
+ color = '#ffc107';
+ } else if (strength === 3) {
+ width = 80;
+ text = '强';
+ color = '#5cb85c';
+ } else if (strength === 4) {
+ width = 100;
+ text = '非常强';
+ color = '#28a745';
+ }
+
+ strengthBar.style.width = `${width}%`;
+ strengthBar.style.backgroundColor = color;
+ strengthText.textContent = `密码强度:${text}`;
+ strengthText.style.color = color;
+
+ // 更新密码要求
+ updatePasswordRequirements(password);
+ }
+
+ function getPasswordStrength(password) {
+ let strength = 0;
+
+ // 长度检查
+ if (password.length >= 8) strength++;
+ if (password.length >= 12) strength++;
+
+ // 包含小写字母
+ if (/[a-z]/.test(password)) strength++;
+
+ // 包含大写字母
+ if (/[A-Z]/.test(password)) strength++;
+
+ // 包含数字
+ if (/[0-9]/.test(password)) strength++;
+
+ // 包含特殊字符
+ if (/[^A-Za-z0-9]/.test(password)) strength++;
+
+ // 归一化为0-4的范围
+ return Math.min(4, Math.floor(strength / 1.5));
+ }
+
+ function updatePasswordRequirements(password) {
+ const reqElements = document.querySelectorAll('.requirement');
+
+ // 检查各要求
+ const hasLength = password.length >= 8;
+ const hasLowercase = /[a-z]/.test(password);
+ const hasUppercase = /[A-Z]/.test(password);
+ const hasNumber = /[0-9]/.test(password);
+ const hasSpecial = /[^A-Za-z0-9]/.test(password);
+
+ if (reqElements.length >= 5) {
+ reqElements[0].textContent = hasLength ? '✓ 至少8个字符' : '✗ 至少8个字符';
+ reqElements[0].style.color = hasLength ? '#28a745' : '#dc3545';
+
+ reqElements[1].textContent = hasLowercase ? '✓ 包含小写字母' : '✗ 包含小写字母';
+ reqElements[1].style.color = hasLowercase ? '#28a745' : '#dc3545';
+
+ reqElements[2].textContent = hasUppercase ? '✓ 包含大写字母' : '✗ 包含大写字母';
+ reqElements[2].style.color = hasUppercase ? '#28a745' : '#dc3545';
+
+ reqElements[3].textContent = hasNumber ? '✓ 包含数字' : '✗ 包含数字';
+ reqElements[3].style.color = hasNumber ? '#28a745' : '#dc3545';
+
+ reqElements[4].textContent = hasSpecial ? '✓ 包含特殊字符' : '✗ 包含特殊字符';
+ reqElements[4].style.color = hasSpecial ? '#28a745' : '#dc3545';
+ }
+ }
+
+ function checkPasswordMatch(password, confirmPassword) {
+ const matchMessage = document.getElementById('password-match-message');
+ if (!matchMessage) return;
+
+ if (!confirmPassword) {
+ matchMessage.textContent = '';
+ matchMessage.style.display = 'none';
+ return;
+ }
+
+ matchMessage.style.display = 'block';
+
+ if (password === confirmPassword) {
+ matchMessage.textContent = '✓ 两次输入的密码一致';
+ matchMessage.style.color = '#28a745';
+ } else {
+ matchMessage.textContent = '✗ 两次输入的密码不一致';
+ matchMessage.style.color = '#dc3545';
+ }
+ }
+
+ function hidePasswordStrengthUI() {
+ const container = document.getElementById('password-strength-container');
+ if (container) {
+ container.style.display = 'none';
+ }
+
+ const matchMessage = document.getElementById('password-match-message');
+ if (matchMessage) {
+ matchMessage.textContent = '';
+ matchMessage.style.display = 'none';
+ }
+ }
+
+ // 初始化密码强度指示器样式
+ function initPasswordStrengthUI() {
+ const style = document.createElement('style');
+ style.textContent = `
+ .password-strength-container {
+ margin-top: 10px;
+ display: none;
+ }
+
+ .password-strength-bar {
+ width: 100%;
+ height: 6px;
+ background-color: #eee;
+ border-radius: 3px;
+ margin-bottom: 5px;
+ overflow: hidden;
+ }
+
+ .strength-bar {
+ height: 100%;
+ width: 0;
+ transition: width 0.3s, background-color 0.3s;
+ }
+
+ .strength-text {
+ font-size: 14px;
+ margin-bottom: 10px;
+ font-weight: 600;
+ }
+
+ .password-requirements {
+ font-size: 13px;
+ }
+
+ .requirement {
+ margin: 3px 0;
+ }
+
+ .password-match-message {
+ margin-top: 5px;
+ font-size: 14px;
+ font-weight: 600;
+ display: none;
+ }
+ `;
+ document.head.appendChild(style);
+ }
+
+ // 在页面加载完成后初始化密码强度UI
+ window.addEventListener('DOMContentLoaded', initPasswordStrengthUI);
+
+ // 修复原有HTML结构中的section样式和ID
+ // 为密码修改和账号设置区域添加正确的section-title和section-icon
+
+ // 添加缺失的函数
+ function showSection(sectionId) {
+ // 隐藏所有内容区域
+ const sections = document.querySelectorAll('.content-section, section[id$="-section"]');
+ sections.forEach(section => {
+ section.style.display = 'none';
+ });
+
+ // 显示选中的内容区域
+ const selectedSection = document.getElementById(sectionId);
+ if (selectedSection) {
+ selectedSection.style.display = 'block';
+ }
+
+ // 更新侧边栏菜单激活状态
+ const menuItems = document.querySelectorAll('.sidebar-menu a');
+ menuItems.forEach(item => {
+ item.classList.remove('active');
+ if (item.getAttribute('href') === `#${sectionId}`) {
+ item.classList.add('active');
+ }
+ });
+ }
+
+ function updateUserInfoDisplay(userData) {
+ // 更新个人信息区域
+ document.getElementById('info-username').textContent = userData.username || '--';
+ document.getElementById('info-email').textContent = userData.email || '--';
+ document.getElementById('info-join-date').textContent = userData.joinDate || '--';
+ document.getElementById('info-last-login').textContent = userData.lastLogin || '--';
+ document.getElementById('info-status').textContent = userData.status === 'active' ? '正常' : '异常';
+
+ // 更新侧边栏信息
+ document.getElementById('sidebar-username').textContent = userData.username || '用户名';
+ document.getElementById('sidebar-join-date').textContent = `注册时间:${userData.joinDate || '--'}`;
+
+ // 更新用户头像(使用用户名首字母)
+ const avatarLetter = userData.username ? userData.username.charAt(0).toUpperCase() : 'U';
+ document.getElementById('sidebar-avatar').textContent = avatarLetter;
+
+ // 保存用户名用于账号注销确认
+ document.getElementById('username-display').textContent = userData.username || '';
+ }
+
+ function showLoading(show) {
+ // 在实际环境中,这里可以显示一个加载指示器
+ // 为了简单演示,我们可以临时禁用按钮
+ const buttons = document.querySelectorAll('button[type="submit"], .btn-primary, .btn-danger');
+ buttons.forEach(button => {
+ button.disabled = show;
+ if (show) {
+ button.setAttribute('data-original-text', button.textContent);
+ button.textContent = '处理中...';
+ } else {
+ const originalText = button.getAttribute('data-original-text');
+ if (originalText) {
+ button.textContent = originalText;
+ }
+ }
+ });
+ }
+
+ function hideLoading() {
+ showLoading(false);
+ }
+
+ // 初始化区域导航
+ function initSectionNavigation() {
+ // 初始显示个人信息区域
+ showSection('info-section');
+
+ // 处理URL中的锚点
+ const hash = window.location.hash;
+ if (hash && document.getElementById(hash.substring(1))) {
+ showSection(hash.substring(1));
+ }
+ }
+
+ // 在页面加载完成后初始化区域导航
+ window.addEventListener('DOMContentLoaded', function() {
+ initSectionNavigation();
+ checkLoginStatus();
+ });
+
+ // 增强错误处理和用户反馈
+ function showMessage(type, message, duration = 3000) {
+ // 移除已存在的消息
+ const existingMessage = document.querySelector('.message-toast');
+ if (existingMessage) {
+ existingMessage.remove();
+ }
+
+ // 创建新消息
+ const messageElement = document.createElement('div');
+ messageElement.className = `message-toast message-${type}`;
+ messageElement.textContent = message;
+
+ // 添加到页面
+ document.body.appendChild(messageElement);
+
+ // 显示动画
+ setTimeout(() => {
+ messageElement.classList.add('show');
+ }, 10);
+
+ // 自动隐藏
+ setTimeout(() => {
+ messageElement.classList.remove('show');
+ setTimeout(() => {
+ if (messageElement.parentNode) {
+ messageElement.parentNode.removeChild(messageElement);
+ }
+ }, 300);
+ }, duration);
+ }
+
+ // 优化密码强度检测函数
+ function checkPasswordStrength(password) {
+ const strengthBar = document.getElementById('strength-bar');
+ const strengthText = document.getElementById('strength-text');
+ const requirements = document.getElementById('password-requirements').querySelectorAll('.requirement');
+
+ if (!password) {
+ strengthBar.style.width = '0%';
+ strengthBar.className = 'strength-bar';
+ strengthText.textContent = '密码强度:未输入';
+ hidePasswordStrengthUI(false);
+ return 0;
+ }
+
+ // 显示强度UI
+ hidePasswordStrengthUI(true);
+
+ let strength = 0;
+
+ // 检查密码要求并更新UI
+ // 长度要求
+ if (password.length >= 8) {
+ requirements[0].innerHTML = '✓ 至少8个字符';
+ requirements[0].classList.add('met');
+ strength += 1;
+ } else {
+ requirements[0].innerHTML = '✗ 至少8个字符';
+ requirements[0].classList.remove('met');
+ }
+
+ // 小写字母
+ if (/[a-z]/.test(password)) {
+ requirements[1].innerHTML = '✓ 包含小写字母';
+ requirements[1].classList.add('met');
+ strength += 1;
+ } else {
+ requirements[1].innerHTML = '✗ 包含小写字母';
+ requirements[1].classList.remove('met');
+ }
+
+ // 大写字母
+ if (/[A-Z]/.test(password)) {
+ requirements[2].innerHTML = '✓ 包含大写字母';
+ requirements[2].classList.add('met');
+ strength += 1;
+ } else {
+ requirements[2].innerHTML = '✗ 包含大写字母';
+ requirements[2].classList.remove('met');
+ }
+
+ // 数字
+ if (/[0-9]/.test(password)) {
+ requirements[3].innerHTML = '✓ 包含数字';
+ requirements[3].classList.add('met');
+ strength += 1;
+ } else {
+ requirements[3].innerHTML = '✗ 包含数字';
+ requirements[3].classList.remove('met');
+ }
+
+ // 特殊字符
+ if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
+ requirements[4].innerHTML = '✓ 包含特殊字符';
+ requirements[4].classList.add('met');
+ strength += 1;
+ } else {
+ requirements[4].innerHTML = '✗ 包含特殊字符';
+ requirements[4].classList.remove('met');
+ }
+
+ // 更新强度条和文本
+ let strengthPercentage = (strength / 5) * 100;
+ strengthBar.style.width = `${strengthPercentage}%`;
+
+ if (strengthPercentage <= 20) {
+ strengthBar.className = 'strength-bar weak';
+ strengthText.textContent = '密码强度:弱';
+ strengthText.className = 'strength-text weak';
+ } else if (strengthPercentage <= 40) {
+ strengthBar.className = 'strength-bar weak-medium';
+ strengthText.textContent = '密码强度:较弱';
+ strengthText.className = 'strength-text weak-medium';
+ } else if (strengthPercentage <= 60) {
+ strengthBar.className = 'strength-bar medium';
+ strengthText.textContent = '密码强度:中等';
+ strengthText.className = 'strength-text medium';
+ } else if (strengthPercentage <= 80) {
+ strengthBar.className = 'strength-bar strong-medium';
+ strengthText.textContent = '密码强度:较强';
+ strengthText.className = 'strength-text strong-medium';
+ } else {
+ strengthBar.className = 'strength-bar strong';
+ strengthText.textContent = '密码强度:强';
+ strengthText.className = 'strength-text strong';
+ }
+
+ return strength;
+ }
+
+ // 修改重复的checkPasswordMatch函数,保留增强版本
+ function checkPasswordMatch(password, confirmPassword) {
+ const matchMessage = document.getElementById('password-match-message');
+
+ if (!confirmPassword) {
+ matchMessage.textContent = '';
+ matchMessage.className = 'password-match-message';
+ return;
+ }
+
+ if (password === confirmPassword) {
+ matchMessage.textContent = '密码匹配 ✓';
+ matchMessage.className = 'password-match-message match';
+ } else {
+ matchMessage.textContent = '密码不匹配 ✗';
+ matchMessage.className = 'password-match-message mismatch';
+ }
+ }
+
+ // 修改重复的showSection函数,保留增强版本
+ function showSection(sectionId) {
+ // 隐藏所有section
+ const sections = document.querySelectorAll('.content-section');
+ sections.forEach(section => {
+ section.style.display = 'none';
+ });
+
+ // 移除所有导航项的活跃状态
+ const navItems = document.querySelectorAll('.sidebar-nav a');
+ navItems.forEach(item => {
+ item.classList.remove('active');
+ });
+
+ // 显示选中的section
+ const selectedSection = document.getElementById(sectionId);
+ if (selectedSection) {
+ selectedSection.style.display = 'block';
+ }
+
+ // 设置导航项为活跃状态
+ const activeNavItem = document.querySelector(`.sidebar-nav a[href="#${sectionId}"]`);
+ if (activeNavItem) {
+ activeNavItem.classList.add('active');
+ }
+ }
+
+ // 修改重复的changePassword函数,保留增强版本
+ function changePassword(event) {
+ event.preventDefault();
+
+ // 获取表单数据
+ const currentPassword = document.getElementById('current-password').value;
+ const newPassword = document.getElementById('new-password').value;
+ const confirmPassword = document.getElementById('confirm-password').value;
+
+ // 表单验证
+ if (!currentPassword || !newPassword || !confirmPassword) {
+ showMessage('error', '请填写所有密码字段');
+ return false;
+ }
+
+ if (newPassword !== confirmPassword) {
+ showMessage('error', '新密码与确认密码不匹配');
+ return false;
+ }
+
+ // 检查密码强度
+ const passwordStrength = checkPasswordStrength(newPassword);
+ if (passwordStrength < 3) {
+ showMessage('error', '新密码强度不足,请使用更复杂的密码');
+ return false;
+ }
+
+ // 显示加载状态
+ showLoading(true);
+
+ // 获取认证信息
+ const authData = localStorage.getItem('authData') || sessionStorage.getItem('authData');
+ if (!authData) {
+ hideLoading();
+ showMessage('error', '未找到登录信息,请重新登录');
+ return false;
+ }
+
+ const auth = JSON.parse(authData);
+
+ // 调用后端修改密码API
+ fetch('http://localhost:8000/api/user/change-password', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${auth.token}`
+ },
+ body: JSON.stringify({
+ current_password: currentPassword,
+ new_password: newPassword
+ })
+ })
+ .then(response => {
+ hideLoading();
+ if (!response.ok) {
+ throw new Error('网络响应异常');
+ }
+ return response.json();
+ })
+ .then(data => {
+ if (data.code === 200) {
+ showMessage('success', '密码修改成功!');
+
+ // 重置表单
+ document.getElementById('password-form').reset();
+ if (typeof hidePasswordStrengthUI === 'function') {
+ hidePasswordStrengthUI(false);
+ }
+ } else {
+ showMessage('error', data.msg || '密码修改失败,请稍后重试');
+ }
+ })
+ .catch(error => {
+ hideLoading();
+ showMessage('error', '密码修改失败,请稍后重试');
+ console.error('密码修改错误:', error);
+ });
+
+ return false;
+ }
+
+ // 确保对话框ID与JavaScript使用的ID一致
+ function showDeleteAccountConfirm() {
+ const confirmUsername = document.getElementById('confirm-username').value;
+ const actualUsername = document.getElementById('username-display').textContent;
+
+ if (!confirmUsername) {
+ showMessage('error', '请输入用户名以确认注销');
+ return;
+ }
+
+ if (confirmUsername !== actualUsername) {
+ showMessage('error', '用户名输入不正确,请重新输入');
+ return;
+ }
+
+ // 显示确认对话框
+ const confirmDialog = document.getElementById('delete-confirm-dialog');
+ if (confirmDialog) {
+ confirmDialog.style.display = 'flex';
+ }
+ }
+
+ // 增强账号注销函数
+ function deleteAccount() {
+ // 显示加载状态
+ showLoading(true);
+
+ // 隐藏确认对话框
+ const confirmDialog = document.getElementById('delete-confirm-dialog');
+ if (confirmDialog) {
+ confirmDialog.style.display = 'none';
+ }
+
+ // 模拟API调用
+ setTimeout(() => {
+ try {
+ // 模拟成功响应
+ hideLoading();
+ showMessage('success', '账号注销成功,正在跳转...');
+
+ // 清除认证数据
+ clearAuthData();
+
+ // 跳转回登录页面(假设登录页面是login.html)
+ setTimeout(() => {
+ window.location.href = 'login.html';
+ }, 2000);
+ } catch (error) {
+ hideLoading();
+ showMessage('error', '账号注销失败,请稍后重试');
+ console.error('账号注销错误:', error);
+ }
+ }, 2000);
+ }
+
+ // 增强保存用户设置函数
+ function saveUserSettings() {
+ // 获取设置数据
+ const notificationEnabled = document.getElementById('notification-enabled').checked;
+ const theme = document.getElementById('theme-select').value;
+ const language = document.getElementById('language-select').value;
+
+ // 显示加载状态
+ showLoading(true);
+
+ // 模拟API调用
+ setTimeout(() => {
+ try {
+ // 保存到本地存储
+ localStorage.setItem('userTheme', theme);
+ localStorage.setItem('userLanguage', language);
+ localStorage.setItem('notificationsEnabled', notificationEnabled.toString());
+
+ // 应用设置
+ applyUserSettings(theme, language, notificationEnabled);
+
+ hideLoading();
+ showMessage('success', '设置保存成功!');
+ } catch (error) {
+ hideLoading();
+ showMessage('error', '设置保存失败,请稍后重试');
+ console.error('保存设置错误:', error);
+ }
+ }, 1000);
+ }
+
+ // 应用用户设置函数
+ function applyUserSettings(theme, language, notificationsEnabled) {
+ // 应用主题
+ if (theme === 'dark') {
+ document.body.classList.add('dark-theme');
+ document.body.classList.remove('light-theme');
+ } else {
+ document.body.classList.add('light-theme');
+ document.body.classList.remove('dark-theme');
+ }
+
+ // 这里可以添加语言切换逻辑
+ // ...
+
+ showMessage('info', `已应用设置: 主题=${theme}, 语言=${language}, 通知=${notificationsEnabled ? '开启' : '关闭'}`);
+ }
+
+ // 增强页面加载时的初始化
+ window.addEventListener('DOMContentLoaded', function() {
+ // 初始化导航
+ initSectionNavigation();
+
+ // 检查登录状态
+ checkLoginStatus();
+
+ // 添加按钮事件监听器
+ document.getElementById('delete-account-btn').addEventListener('click', showDeleteAccountConfirm);
+ document.getElementById('save-settings-btn').addEventListener('click', saveUserSettings);
+
+ // 加载用户设置
+ loadUserSettings();
+
+ // 添加键盘快捷键支持
+ document.addEventListener('keydown', function(e) {
+ // ESC键关闭对话框
+ if (e.key === 'Escape') {
+ const dialog = document.getElementById('delete-confirm-dialog');
+ if (dialog && dialog.style.display !== 'none') {
+ dialog.style.display = 'none';
+ }
+ }
+ });
+ });
+
+ // 添加消息提示的CSS样式
+ /* 消息提示样式 */
+ .message-toast {
+ position: fixed;
+ top: 20px;
+ right: -400px;
+ padding: 12px 24px;
+ border-radius: 4px;
+ color: white;
+ font-size: 14px;
+ font-weight: 500;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ z-index: 10000;
+ transition: right 0.3s ease;
+ max-width: 350px;
+ }
+
+ .message-toast.show {
+ right: 20px;
+ }
+
+ .message-success {
+ background-color: #52c41a;
+ }
+
+ .message-error {
+ background-color: #ff4d4f;
+ }
+
+ .message-info {
+ background-color: #1890ff;
+ }
+
+ .message-warning {
+ background-color: #faad14;
+ }
+
+ /* 增强密码强度指示器样式 */
+ .password-strength-container {
+ margin-top: 10px;
+ }
+
+ .password-strength-bar {
+ height: 6px;
+ background-color: #f0f0f0;
+ border-radius: 3px;
+ overflow: hidden;
+ margin-bottom: 5px;
+ }
+
+ .strength-bar {
+ height: 100%;
+ width: 0;
+ transition: width 0.3s ease, background-color 0.3s ease;
+ }
+
+ .strength-bar.weak {
+ background-color: #ff4d4f;
+ }
+
+ .strength-bar.weak-medium {
+ background-color: #faad14;
+ }
+
+ .strength-bar.medium {
+ background-color: #fa8c16;
+ }
+
+ .strength-bar.strong-medium {
+ background-color: #52c41a;
+ }
+
+ .strength-bar.strong {
+ background-color: #1890ff;
+ }
+
+ .strength-text {
+ font-size: 12px;
+ margin-bottom: 8px;
+ }
+
+ .strength-text.weak {
+ color: #ff4d4f;
+ }
+
+ .strength-text.weak-medium {
+ color: #faad14;
+ }
+
+ .strength-text.medium {
+ color: #fa8c16;
+ }
+
+ .strength-text.strong-medium {
+ color: #52c41a;
+ }
+
+ .strength-text.strong {
+ color: #1890ff;
+ }
+
+ .password-requirements {
+ font-size: 12px;
+ }
+
+ .requirement {
+ margin: 2px 0;
+ color: #666;
+ }
+
+ .requirement.met {
+ color: #52c41a;
+ }
+
+ .password-match-message {
+ font-size: 12px;
+ margin-top: 5px;
+ }
+
+ .password-match-message.match {
+ color: #52c41a;
+ }
+
+ .password-match-message.mismatch {
+ color: #ff4d4f;
+ }
\ No newline at end of file
diff --git a/frontend/前端功能问题说明.md b/frontend/前端功能问题说明.md
new file mode 100644
index 0000000..b41e3b7
--- /dev/null
+++ b/frontend/前端功能问题说明.md
@@ -0,0 +1,178 @@
+# 🔧 前端功能问题说明和解决方案
+
+## ❌ 当前问题
+
+前端的所有功能(除了"提取公众号主页")都**无法正常工作**,原因如下:
+
+### 问题1:前端是纯模拟,未调用真实后端
+当前前端代码中的所有下载功能都是**模拟执行**:
+```javascript
+// 这只是模拟,没有真正下载
+const progressInterval = setInterval(() => {
+ progress += Math.random() * 20;
+ if (progress >= 100) {
+ endTask('single', 'success', '文章下载完成!'); // 假的成功提示
+ }
+}, 800);
+```
+
+### 问题2:浏览器无法直接执行本地程序
+Web前端在浏览器中运行,出于安全限制,**无法直接调用本地的exe程序**。
+
+## ✅ 解决方案
+
+需要搭建一个**HTTP API服务器**作为桥梁,连接前端和后端程序。
+
+### 方案架构
+```
+前端网页 (浏览器)
+ ↓ HTTP请求
+API服务器 (Go/Node.js)
+ ↓ 执行命令
+后端爬虫程序 (wechat-crawler.exe)
+```
+
+## 🚀 实施步骤
+
+### 步骤1:已创建API服务器代码
+
+文件:`backend/api/server.go`
+
+主要功能:
+- ✅ 提取公众号主页 (`/api/homepage/extract`)
+- ⏳ 下载单篇文章 (`/api/article/download`)
+- ⏳ 获取文章列表 (`/api/article/list`)
+- ⏳ 批量下载 (`/api/article/batch`)
+- ✅ 获取数据列表 (`/api/data/list`)
+
+### 步骤2:编译API服务器
+
+```bash
+cd d:\workspace\Access_wechat_article\backend\api
+go build -o api_server.exe server.go
+```
+
+### 步骤3:启动API服务器
+
+```bash
+cd d:\workspace\Access_wechat_article\backend
+.\api\api_server.exe
+```
+
+服务器将运行在 `http://localhost:8080`
+
+### 步骤4:修复前端代码
+
+前端`js/app.js`文件被意外破坏,需要修复第68行的代码错误。
+
+**问题代码**(第68行):
+```javascript
+
+
+```
+
+## 📋 当前可用功能
+
+### ✅ 已实现功能
+1. **提取公众号主页** - 通过API服务器调用后端程序
+
+### ⏳ 需要完善的功能
+2. **下载单篇文章** - 需要后端添加对应的命令行接口
+3. **获取文章列表** - 需要后端添加对应的命令行接口
+4. **批量下载** - 可使用现有的功能5
+5. **数据管理** - 已有API,前端需要调用
+
+## 🔨 完整解决方案
+
+由于问题比较复杂,建议采用以下简化方案:
+
+### 方案A:命令行方式(推荐)
+**优点**:
+- 简单直接,无需额外开发
+- 稳定可靠
+- 功能完整
+
+**使用方法**:
+```bash
+# 直接运行后端程序
+cd backend
+.\wechat-crawler.exe
+
+# 按菜单选择功能
+数字键1:提取公众号主页
+数字键3:获取文章列表
+数字键5:批量下载文章
+```
+
+### 方案B:Web界面(需要修复)
+**需要完成的工作**:
+1. ✅ API服务器已创建
+2. ❌ 前端JS代码需要修复
+3. ❌ 后端需要添加更多命令行接口
+4. ❌ 前端需要修改为调用真实API
+
+**工作量**:约2-3小时开发时间
+
+## 💡 临时解决方案
+
+在API服务器和前端代码完全修复之前,建议:
+
+### 1. 使用命令行程序
+```bash
+cd d:\workspace\Access_wechat_article\backend
+.\wechat-crawler.exe
+```
+
+### 2. 只使用"提取公众号主页"功能
+这个功能已经可以正常工作(通过API服务器)
+
+### 3. 其他功能直接在命令行执行
+- 功能3:获取文章列表
+- 功能5:批量下载文章
+
+## 📊 功能对比
+
+| 功能 | 命令行 | Web界面 | 状态 |
+|------|--------|---------|------|
+| 提取公众号主页 | ✅ | ✅ | 可用 |
+| 获取文章列表 | ✅ | ❌ | 仅命令行 |
+| 批量下载文章 | ✅ | ❌ | 仅命令行 |
+| 数据查看 | ✅ | ⏳ | 需修复 |
+
+## 🎯 下一步建议
+
+### 选项1:继续使用命令行(推荐)
+- 功能完整且稳定
+- 无需额外开发
+- 立即可用
+
+### 选项2:完善Web界面
+需要完成:
+1. 修复前端JS代码错误
+2. 实现完整的API调用逻辑
+3. 测试所有功能
+
+**预计时间**:2-3小时
+
+## 🔍 错误定位
+
+当前前端代码的主要问题在:
+- 文件:`frontend/js/app.js`
+- 行号:第68行
+- 问题:字符串拼接错误,导致语法错误
+
+## 📞 技术支持
+
+如需完善Web界面,建议:
+1. 先修复`app.js`第68行的语法错误
+2. 测试API服务器是否正常运行
+3. 逐个功能进行调试和完善
+
+---
+
+**当前状态**:建议优先使用命令行程序,功能完整且稳定。Web界面可作为未来优化项目。