1753 lines
69 KiB
HTML
1753 lines
69 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>用户中心 - 易搜高</title>
|
||
<meta name="keywords" content="用户中心,个人信息,密码修改,易搜高">
|
||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
|
||
<style>
|
||
/* 全局样式重置 */
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
|
||
background: #f5f6fa;
|
||
color: #333;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
/* 头部样式 */
|
||
.header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 15px 0;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.header-content {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 0 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.logo {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
text-decoration: none;
|
||
color: white;
|
||
}
|
||
|
||
.nav-menu {
|
||
display: flex;
|
||
gap: 30px;
|
||
align-items: center;
|
||
}
|
||
|
||
.nav-menu a {
|
||
color: white;
|
||
text-decoration: none;
|
||
transition: opacity 0.3s;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.nav-menu a:hover {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.nav-menu a.active {
|
||
opacity: 1;
|
||
border-bottom: 2px solid white;
|
||
padding-bottom: 3px;
|
||
}
|
||
|
||
/* 用户信息和登出按钮样式 */
|
||
.user-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.user-name {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.logout-btn {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
color: white;
|
||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||
padding: 6px 16px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.logout-btn:hover {
|
||
background: rgba(255, 255, 255, 0.3);
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
/* 主内容区域 */
|
||
.main-content {
|
||
max-width: 1200px;
|
||
margin: 30px auto;
|
||
padding: 0 20px;
|
||
}
|
||
|
||
.page-title {
|
||
font-size: 28px;
|
||
color: #2c3e50;
|
||
margin-bottom: 30px;
|
||
padding-bottom: 15px;
|
||
border-bottom: 2px solid #e0e6ed;
|
||
}
|
||
|
||
/* 用户中心容器 */
|
||
.user-center-container {
|
||
display: flex;
|
||
gap: 30px;
|
||
}
|
||
|
||
/* 侧边栏 */
|
||
.sidebar {
|
||
width: 280px;
|
||
background: white;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||
padding: 25px;
|
||
height: fit-content;
|
||
position: sticky;
|
||
top: 100px;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
margin: 0 auto 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: white;
|
||
font-size: 32px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.sidebar-user-name {
|
||
text-align: center;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #2c3e50;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.sidebar-join-date {
|
||
text-align: center;
|
||
font-size: 14px;
|
||
color: #95a5a6;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.sidebar-menu {
|
||
list-style: none;
|
||
}
|
||
|
||
.sidebar-menu li {
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.sidebar-menu a {
|
||
display: block;
|
||
padding: 12px 16px;
|
||
color: #5a6c7d;
|
||
text-decoration: none;
|
||
border-radius: 8px;
|
||
transition: all 0.3s;
|
||
font-size: 15px;
|
||
}
|
||
|
||
.sidebar-menu a:hover {
|
||
background: #f5f7fa;
|
||
color: #667eea;
|
||
}
|
||
|
||
.sidebar-menu a.active {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
}
|
||
|
||
/* 内容区域 */
|
||
.content-area {
|
||
flex: 1;
|
||
background: white;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||
padding: 30px;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 20px;
|
||
color: #2c3e50;
|
||
margin-bottom: 25px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.section-icon {
|
||
width: 24px;
|
||
height: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: #667eea;
|
||
color: white;
|
||
border-radius: 50%;
|
||
font-size: 14px;
|
||
}
|
||
|
||
/* 信息卡片 */
|
||
.info-card {
|
||
background: #f8f9fa;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.info-row {
|
||
display: flex;
|
||
padding: 12px 0;
|
||
border-bottom: 1px solid #e9ecef;
|
||
}
|
||
|
||
.info-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.info-label {
|
||
width: 120px;
|
||
color: #6c757d;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.info-value {
|
||
flex: 1;
|
||
color: #2c3e50;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 表单样式 */
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.form-label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
font-weight: 600;
|
||
color: #2c3e50;
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 8px;
|
||
font-size: 15px;
|
||
transition: border-color 0.3s;
|
||
}
|
||
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: #667eea;
|
||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||
}
|
||
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 24px;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: #6c757d;
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 24px;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
margin-left: 10px;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: #5a6268;
|
||
transform: translateY(-1px);
|
||
}
|
||
|
||
/* 消息提示 */
|
||
.message {
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
margin-bottom: 20px;
|
||
display: none;
|
||
}
|
||
|
||
.message-success {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
border: 1px solid #c3e6cb;
|
||
}
|
||
|
||
.message-error {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
border: 1px solid #f5c6cb;
|
||
}
|
||
|
||
.message-info {
|
||
background: #d1ecf1;
|
||
color: #0c5460;
|
||
border: 1px solid #bee5eb;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.user-center-container {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.sidebar {
|
||
width: 100%;
|
||
position: static;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.sidebar-menu {
|
||
display: flex;
|
||
gap: 10px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.sidebar-menu li {
|
||
flex: 1;
|
||
min-width: calc(50% - 5px);
|
||
}
|
||
|
||
.info-row {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.info-label {
|
||
width: 100%;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.btn-secondary {
|
||
margin-left: 0;
|
||
margin-top: 10px;
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.header-content {
|
||
flex-direction: column;
|
||
gap: 15px;
|
||
}
|
||
|
||
.nav-menu {
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
gap: 15px;
|
||
}
|
||
|
||
.sidebar-menu li {
|
||
min-width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- 头部导航 -->
|
||
<header class="header">
|
||
<div class="header-content">
|
||
<a href="frontend.html" class="logo">易搜高</a>
|
||
<nav class="nav-menu">
|
||
<a href="frontend.html">首页监控</a>
|
||
<a href="history-articles.html">历史文章</a>
|
||
<a href="user-center.html" class="active">用户中心</a>
|
||
<!-- 用户信息和登出按钮会通过JavaScript动态添加 -->
|
||
<div id="userMenu"></div>
|
||
<a href="login.html" id="loginLink" class="login-link">登录/注册</a>
|
||
</nav>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- 主内容区域 -->
|
||
<main class="main-content">
|
||
<h1 class="page-title">用户中心</h1>
|
||
|
||
<div class="user-center-container">
|
||
<!-- 侧边栏 -->
|
||
<aside class="sidebar">
|
||
<div class="user-avatar" id="sidebar-avatar">U</div>
|
||
<h3 class="sidebar-user-name" id="sidebar-username">用户名</h3>
|
||
<p class="sidebar-join-date" id="sidebar-join-date">注册时间:--</p>
|
||
|
||
<!-- 侧边栏菜单更新 -->
|
||
<ul class="sidebar-menu">
|
||
<li><a href="#info-section" class="active" onclick="showSection('info-section')">个人信息</a></li>
|
||
<li><a href="#password-section" onclick="showSection('password-section')">修改密码</a></li>
|
||
<li><a href="#account-settings-section" onclick="showSection('account-settings-section')">账号设置</a></li>
|
||
</ul>
|
||
</aside>
|
||
|
||
<!-- 内容区域 -->
|
||
<div class="content-area">
|
||
<!-- 消息提示 -->
|
||
<div id="message" class="message"></div>
|
||
|
||
<!-- 个人信息区域 -->
|
||
<section id="info-section">
|
||
<h2 class="section-title">
|
||
<span class="section-icon">👤</span>
|
||
个人信息
|
||
</h2>
|
||
|
||
<div class="info-card">
|
||
<!-- 修复个人信息区域中重复的ID -->
|
||
<div class="info-row">
|
||
<span class="info-label">用户名</span>
|
||
<span class="info-value" id="info-username">--</span>
|
||
<span id="username-display" style="display: none;"></span>
|
||
</div>
|
||
|
||
<div class="info-row">
|
||
<span class="info-label">邮箱</span>
|
||
<span class="info-value" id="info-email">--</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="info-label">注册时间</span>
|
||
<span class="info-value" id="info-join-date">--</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="info-label">上次登录</span>
|
||
<span class="info-value" id="info-last-login">--</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="info-label">账号状态</span>
|
||
<span class="info-value" id="info-status">--</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 密码修改部分 -->
|
||
<section id="password-section" class="content-section" style="display: none;">
|
||
<h2 class="section-title">
|
||
<span class="section-icon">🔒</span>
|
||
修改密码
|
||
</h2>
|
||
<form id="password-form" onsubmit="return changePassword(event)">
|
||
<div class="form-group">
|
||
<label for="current-password" class="form-label">当前密码</label>
|
||
<input type="password" id="current-password" class="form-input" required placeholder="请输入当前密码">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="new-password" class="form-label">新密码</label>
|
||
<input type="password" id="new-password" class="form-input" required placeholder="请输入新密码"
|
||
oninput="checkPasswordStrength(this.value); checkPasswordMatch(this.value, document.getElementById('confirm-password').value)">
|
||
<!-- 密码强度指示器 -->
|
||
<div id="password-strength-container" class="password-strength-container">
|
||
<div class="password-strength-bar">
|
||
<div id="strength-bar" class="strength-bar"></div>
|
||
</div>
|
||
<div id="strength-text" class="strength-text">密码强度:未输入</div>
|
||
<div id="password-requirements" class="password-requirements">
|
||
<div class="requirement">✓ 至少8个字符</div>
|
||
<div class="requirement">✗ 包含小写字母</div>
|
||
<div class="requirement">✗ 包含大写字母</div>
|
||
<div class="requirement">✗ 包含数字</div>
|
||
<div class="requirement">✗ 包含特殊字符</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="confirm-password" class="form-label">确认新密码</label>
|
||
<input type="password" id="confirm-password" class="form-input" required placeholder="请再次输入新密码"
|
||
oninput="checkPasswordMatch(document.getElementById('new-password').value, this.value)">
|
||
<div id="password-match-message" class="password-match-message"></div>
|
||
</div>
|
||
<button type="submit" class="btn-primary">修改密码</button>
|
||
</form>
|
||
</section>
|
||
|
||
<!-- 在密码修改表单之后,账号设置区域 -->
|
||
<section id="account-settings-section" class="content-section" style="display: none;">
|
||
<h2 class="section-title">
|
||
<span class="section-icon">⚙️</span>
|
||
账号设置
|
||
</h2>
|
||
<div class="settings-form">
|
||
<div class="form-group">
|
||
<label for="notification-enabled" class="form-label">启用通知</label>
|
||
<div class="switch-container">
|
||
<input type="checkbox" id="notification-enabled" class="toggle-switch">
|
||
<label for="notification-enabled" class="switch-label"></label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="theme-select" class="form-label">主题设置</label>
|
||
<select id="theme-select" class="form-input">
|
||
<option value="light">浅色主题</option>
|
||
<option value="dark">深色主题</option>
|
||
<option value="system">跟随系统</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="language-select" class="form-label">语言设置</label>
|
||
<select id="language-select" class="form-input">
|
||
<option value="zh-CN">简体中文</option>
|
||
<option value="en-US">English</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-actions">
|
||
<button id="save-settings-btn" class="btn-primary">保存设置</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 账号注销区域 -->
|
||
<div class="account-delete-section">
|
||
<h3 class="section-title" style="font-size: 18px;">
|
||
<span class="section-icon">⚠️</span>
|
||
账号注销
|
||
</h3>
|
||
<div class="delete-warning">
|
||
<p><i class="warning-icon">⚠️</i> 账号注销后,所有数据将被永久删除,此操作无法撤销!</p>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="confirm-username" class="form-label">请输入您的用户名以确认注销:</label>
|
||
<input type="text" id="confirm-username" class="form-input" placeholder="输入用户名确认">
|
||
</div>
|
||
<div class="form-actions">
|
||
<button id="delete-account-btn" class="btn-danger">注销我的账号</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 账号注销确认对话框 -->
|
||
<div id="delete-confirm-modal" class="modal" style="display: none;">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h3>确认账号注销</h3>
|
||
<button id="close-modal-btn" class="close-btn">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="warning-text">⚠️ 您确定要永久删除您的账号吗?</p>
|
||
<p>此操作将:</p>
|
||
<ul>
|
||
<li>删除所有个人资料和设置</li>
|
||
<li>删除您的所有收藏和历史记录</li>
|
||
<li>无法恢复已删除的数据</li>
|
||
</ul>
|
||
<div class="form-group">
|
||
<label for="final-confirm">请输入 "DELETE" 以确认:</label>
|
||
<input type="text" id="final-confirm" class="form-control" placeholder="DELETE">
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button id="cancel-delete-btn" class="btn btn-secondary">取消</button>
|
||
<button id="confirm-delete-btn" class="btn btn-danger">确认注销</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 账号设置相关 CSS 样式 -->
|
||
<style>
|
||
.switch-container {
|
||
position: relative;
|
||
display: inline-block;
|
||
width: 60px;
|
||
height: 34px;
|
||
}
|
||
|
||
.toggle-switch {
|
||
opacity: 0;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
|
||
.switch-label {
|
||
position: absolute;
|
||
cursor: pointer;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: #ccc;
|
||
transition: .4s;
|
||
border-radius: 34px;
|
||
}
|
||
|
||
.switch-label:before {
|
||
position: absolute;
|
||
content: "";
|
||
height: 26px;
|
||
width: 26px;
|
||
left: 4px;
|
||
bottom: 4px;
|
||
background-color: white;
|
||
transition: .4s;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.toggle-switch:checked + .switch-label {
|
||
background-color: #2196F3;
|
||
}
|
||
|
||
.toggle-switch:checked + .switch-label:before {
|
||
transform: translateX(26px);
|
||
}
|
||
|
||
.account-delete-section {
|
||
margin-top: 30px;
|
||
padding: 20px;
|
||
background-color: #f9f9f9;
|
||
border-radius: 8px;
|
||
border: 1px solid #ddd;
|
||
}
|
||
|
||
.delete-warning {
|
||
padding: 10px;
|
||
background-color: #fff3cd;
|
||
border: 1px solid #ffeaa7;
|
||
border-radius: 4px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.warning-icon {
|
||
font-size: 1.2em;
|
||
margin-right: 5px;
|
||
}
|
||
|
||
.modal {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: rgba(0,0,0,0.5);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.modal-content {
|
||
background-color: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
width: 90%;
|
||
max-width: 500px;
|
||
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
|
||
.modal-header h3 {
|
||
margin: 0;
|
||
color: #d9534f;
|
||
}
|
||
|
||
.close-btn {
|
||
background: none;
|
||
border: none;
|
||
font-size: 24px;
|
||
cursor: pointer;
|
||
color: #999;
|
||
}
|
||
|
||
.modal-body {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.warning-text {
|
||
font-weight: bold;
|
||
color: #d9534f;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.modal-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 10px;
|
||
padding-top: 15px;
|
||
border-top: 1px solid #eee;
|
||
}
|
||
|
||
.btn-danger {
|
||
background-color: #d9534f;
|
||
color: white;
|
||
border: none;
|
||
}
|
||
|
||
.btn-danger:hover {
|
||
background-color: #c9302c;
|
||
}
|
||
|
||
.btn-secondary {
|
||
background-color: #6c757d;
|
||
color: white;
|
||
border: none;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background-color: #5a6268;
|
||
border: none;
|
||
}
|
||
</style>
|
||
|
||
// 添加缺失的函数定义,确保功能完整性
|
||
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 = `
|
||
<div class="user-info">
|
||
<span class="user-name">${username}</span>
|
||
<button class="logout-btn" onclick="logout()">退出登录</button>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
// 加载用户信息
|
||
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;
|
||
} |