添加用户修改密码功能

- 左边栏添加修改密码按钮
- 添加修改密码弹窗
- 添加 /api/user/password API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-10 20:37:27 +08:00
parent 32a29e61e9
commit 3e8988896a
2 changed files with 81 additions and 0 deletions

26
app.py
View File

@@ -2247,6 +2247,32 @@ def get_current_user_vip():
return jsonify(vip_info)
@app.route('/api/user/password', methods=['POST'])
@login_required
def change_user_password():
"""用户修改自己的密码"""
data = request.get_json()
current_password = data.get('current_password')
new_password = data.get('new_password')
if not current_password or not new_password:
return jsonify({"error": "请填写完整信息"}), 400
if len(new_password) < 6:
return jsonify({"error": "新密码至少6位"}), 400
# 验证当前密码
user = database.get_user_by_id(current_user.id)
if not user or not check_password_hash(user['password_hash'], current_password):
return jsonify({"error": "当前密码错误"}), 400
# 更新密码(使用管理员重置密码的函数,因为已经验证过当前密码了)
if database.admin_reset_user_password(current_user.id, new_password):
return jsonify({"success": True})
else:
return jsonify({"error": "密码更新失败"}), 500
@app.route('/api/run_stats', methods=['GET'])
@login_required
def get_run_stats():

View File

@@ -285,6 +285,7 @@
<div class="nav-item active" data-tab="accounts"><span class="nav-icon">👤</span><span class="nav-label">账号管理</span></div>
<div class="nav-item" data-tab="schedule"><span class="nav-icon"></span><span class="nav-label">定时任务</span></div>
<div class="nav-item" data-tab="screenshots"><span class="nav-icon">📸</span><span class="nav-label">截图管理</span></div>
<div class="nav-item" onclick="openModal('changePasswordModal')" style="margin-top: auto;"><span class="nav-icon">⚙️</span><span class="nav-label">修改密码</span></div>
</nav>
<main class="main-content">
@@ -499,6 +500,33 @@
</div>
</div>
<!-- 修改密码弹窗 -->
<div class="modal-overlay" id="changePasswordModal">
<div class="modal" style="max-width: 400px;">
<div class="modal-header">
<h3 class="modal-title">修改密码</h3>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">当前密码</label>
<input type="password" class="form-input" id="currentPassword" placeholder="请输入当前密码">
</div>
<div class="form-group">
<label class="form-label">新密码</label>
<input type="password" class="form-input" id="newPassword" placeholder="请输入新密码至少6位">
</div>
<div class="form-group">
<label class="form-label">确认新密码</label>
<input type="password" class="form-input" id="confirmPassword" placeholder="请再次输入新密码">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-text" onclick="closeModal('changePasswordModal')">取消</button>
<button class="btn btn-primary" onclick="changePassword()">确认修改</button>
</div>
</div>
</div>
<!-- 反馈弹窗 -->
<div class="modal-overlay" id="feedbackModal">
<div class="modal" style="max-width: 560px;">
@@ -1750,7 +1778,34 @@
.catch(() => { window.location.href = '/login'; });
}
function changePassword() {
const currentPwd = document.getElementById('currentPassword').value;
const newPwd = document.getElementById('newPassword').value;
const confirmPwd = document.getElementById('confirmPassword').value;
if (!currentPwd) { showToast('请输入当前密码', 'error'); return; }
if (!newPwd || newPwd.length < 6) { showToast('新密码至少6位', 'error'); return; }
if (newPwd !== confirmPwd) { showToast('两次密码不一致', 'error'); return; }
fetch('/api/user/password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ current_password: currentPwd, new_password: newPwd })
})
.then(r => r.json().then(data => ({ ok: r.ok, data })))
.then(({ ok, data }) => {
if (ok) {
showToast('密码修改成功', 'success');
closeModal('changePasswordModal');
document.getElementById('currentPassword').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('confirmPassword').value = '';
} else {
showToast(data.error || '修改失败', 'error');
}
})
.catch(() => showToast('网络错误', 'error'));
}
// 点击overlay关闭弹窗
document.querySelectorAll('.modal-overlay').forEach(function(overlay) {