Skip to content

Commit 0c83776

Browse files
committed
新增用户信息修改
1 parent 47808d0 commit 0c83776

File tree

5 files changed

+258
-8
lines changed

5 files changed

+258
-8
lines changed

auth.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,22 +135,56 @@ def update_user_profile(user_id, data):
135135
if not user:
136136
return None, '用户不存在'
137137

138-
# 更新允许的字段
139-
if 'email' in data:
138+
password_changed = False
139+
140+
# 更新用户名
141+
if 'username' in data and data['username'] != user.username:
142+
# 检查用户名是否已被其他用户使用
143+
existing_user = db.query(User).filter(
144+
User.username == data['username'],
145+
User.id != user_id
146+
).first()
147+
if existing_user:
148+
return None, '用户名已存在'
149+
user.username = data['username']
150+
151+
# 更新邮箱
152+
if 'email' in data and data['email'] != user.email:
140153
# 检查邮箱是否已被其他用户使用
141154
existing_user = db.query(User).filter(
142155
User.email == data['email'],
143156
User.id != user_id
144157
).first()
145158
if existing_user:
146-
return None, '邮箱已被使用'
159+
return None, '邮箱已存在'
147160
user.email = data['email']
148161

149-
if 'password' in data:
150-
user.set_password(data['password'])
162+
# 更新密码(需要验证旧密码)
163+
if 'new_password' in data and data['new_password']:
164+
# 验证新密码长度
165+
if len(data['new_password']) < 8:
166+
return None, '新密码长度至少8位'
167+
168+
# 验证旧密码
169+
old_password = data.get('old_password', '')
170+
if not old_password:
171+
return None, '修改密码需要提供旧密码'
172+
173+
if not user.check_password(old_password):
174+
return None, '旧密码错误'
175+
176+
# 更新密码
177+
user.set_password(data['new_password'])
178+
password_changed = True
151179

152180
db.commit()
153181

154-
return {
182+
result = {
155183
'user': user.to_dict()
156-
}, None
184+
}
185+
186+
# 如果修改了密码,返回标识
187+
if password_changed:
188+
result['password_changed'] = True
189+
190+
return result, None

static/css/styles.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,22 @@ header p {
223223
transform: translateY(-2px);
224224
}
225225

226+
/* 设置按钮样式 */
227+
.settings-btn {
228+
background: rgba(255, 255, 255, 0.15);
229+
color: white;
230+
border: none;
231+
padding: 6px 18px;
232+
border-radius: 999px;
233+
cursor: pointer;
234+
transition: background 0.3s, transform 0.3s;
235+
}
236+
237+
.settings-btn:hover {
238+
background: rgba(255, 255, 255, 0.3);
239+
transform: translateY(-2px);
240+
}
241+
226242
.main-content {
227243
display: grid;
228244
grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
@@ -360,6 +376,15 @@ header p {
360376
resize: vertical;
361377
}
362378

379+
/* 表单提示文字样式 */
380+
.form-hint {
381+
display: block;
382+
margin-top: 5px;
383+
font-size: 0.9em;
384+
color: #666;
385+
line-height: 1.5;
386+
}
387+
363388
.config-fields {
364389
background: rgba(99, 102, 241, 0.05);
365390
padding: 18px;

static/index.html

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ <h1>📬 消息推送系统</h1>
113113
<input type="file" id="importFileInput" accept=".json" style="display: none;" onchange="importData(event)">
114114
<button id="openCalendarBtn" class="btn btn-sm btn-ghost" onclick="openCalendarView()">📅 日历</button>
115115
<button id="syncBtn" class="btn btn-sm btn-ghost" onclick="openSyncModal()">🔄 订阅</button>
116+
<button class="settings-btn" onclick="openUserSettingsModal()">⚙️ 设置</button>
116117
<button class="logout-btn" onclick="logout()">退出</button>
117118
</div>
118119
</header>
@@ -482,6 +483,48 @@ <h2>编辑任务</h2>
482483
</div>
483484
</div>
484485

486+
<!-- 用户设置模态框 -->
487+
<div id="userSettingsModal" class="modal">
488+
<div class="modal-content">
489+
<span class="close" onclick="closeUserSettingsModal()">&times;</span>
490+
<h2>⚙️ 用户设置</h2>
491+
<form id="userSettingsForm" onsubmit="handleUserSettingsSubmit(event)">
492+
<div class="form-group">
493+
<label for="settingsUsername">用户名 *</label>
494+
<input type="text" id="settingsUsername" name="username" maxlength="50" placeholder="请输入用户名" required>
495+
</div>
496+
497+
<div class="form-group">
498+
<label for="settingsEmail">邮箱 *</label>
499+
<input type="email" id="settingsEmail" name="email" placeholder="请输入邮箱" required>
500+
</div>
501+
502+
<div class="form-group">
503+
<label for="settingsOldPassword">旧密码</label>
504+
<input type="password" id="settingsOldPassword" name="old_password" placeholder="仅修改密码时需要填写">
505+
<small class="form-hint">仅在修改密码时需要填写</small>
506+
</div>
507+
508+
<div class="form-group">
509+
<label for="settingsNewPassword">新密码</label>
510+
<input type="password" id="settingsNewPassword" name="new_password" minlength="8" placeholder="留空表示不修改,最少8位">
511+
<small class="form-hint">留空表示不修改密码,修改时最少8位</small>
512+
</div>
513+
514+
<div class="form-group">
515+
<label for="settingsConfirmPassword">确认新密码</label>
516+
<input type="password" id="settingsConfirmPassword" name="confirm_password" minlength="8" placeholder="再次输入新密码">
517+
<small class="form-hint">请再次输入新密码以确认</small>
518+
</div>
519+
520+
<div class="form-actions">
521+
<button type="button" class="btn btn-secondary" onclick="closeUserSettingsModal()">取消</button>
522+
<button type="submit" class="btn btn-primary">保存设置</button>
523+
</div>
524+
</form>
525+
</div>
526+
</div>
527+
485528
<!-- 添加:视图切换控制(在加载 app.js 和 calendar.js 之前) -->
486529
<script>
487530
// filepath: /Users/7ommmy/Code/DIY/Notify-Scheduler/static/index.html

static/js/app.js

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2819,3 +2819,151 @@ window.addEventListener('click', function(event) {
28192819
closeLogsModal();
28202820
}
28212821
});
2822+
// ============= 用户设置功能 =============
2823+
2824+
// 打开用户设置模态框
2825+
async function openUserSettingsModal() {
2826+
try {
2827+
// 获取当前用户信息
2828+
const response = await fetch(`${API_BASE}/auth/profile`, {
2829+
method: 'GET',
2830+
headers: {
2831+
'Authorization': `Bearer ${localStorage.getItem('token')}`
2832+
}
2833+
});
2834+
2835+
if (response.ok) {
2836+
const data = await response.json();
2837+
const user = data.user;
2838+
2839+
// 填充表单
2840+
document.getElementById('settingsUsername').value = user.username || '';
2841+
document.getElementById('settingsEmail').value = user.email || '';
2842+
document.getElementById('settingsOldPassword').value = '';
2843+
document.getElementById('settingsNewPassword').value = '';
2844+
document.getElementById('settingsConfirmPassword').value = '';
2845+
2846+
// 显示模态框
2847+
document.getElementById('userSettingsModal').style.display = 'block';
2848+
} else {
2849+
const error = await response.json();
2850+
showNotification(error.error || '获取用户信息失败', 'error');
2851+
}
2852+
} catch (error) {
2853+
console.error('打开用户设置失败:', error);
2854+
showNotification('打开用户设置失败', 'error');
2855+
}
2856+
}
2857+
2858+
// 关闭用户设置模态框
2859+
function closeUserSettingsModal() {
2860+
document.getElementById('userSettingsModal').style.display = 'none';
2861+
// 清空密码字段
2862+
document.getElementById('settingsOldPassword').value = '';
2863+
document.getElementById('settingsNewPassword').value = '';
2864+
document.getElementById('settingsConfirmPassword').value = '';
2865+
}
2866+
2867+
// 处理用户设置提交
2868+
async function handleUserSettingsSubmit(event) {
2869+
event.preventDefault();
2870+
2871+
const username = document.getElementById('settingsUsername').value.trim();
2872+
const email = document.getElementById('settingsEmail').value.trim();
2873+
const oldPassword = document.getElementById('settingsOldPassword').value;
2874+
const newPassword = document.getElementById('settingsNewPassword').value;
2875+
const confirmPassword = document.getElementById('settingsConfirmPassword').value;
2876+
2877+
// 验证用户名和邮箱
2878+
if (!username) {
2879+
showNotification('用户名不能为空', 'error');
2880+
return;
2881+
}
2882+
2883+
if (!email) {
2884+
showNotification('邮箱不能为空', 'error');
2885+
return;
2886+
}
2887+
2888+
// 验证邮箱格式
2889+
if (!email.includes('@')) {
2890+
showNotification('请输入有效的邮箱地址', 'error');
2891+
return;
2892+
}
2893+
2894+
// 构建更新数据
2895+
const updateData = {
2896+
username: username,
2897+
email: email
2898+
};
2899+
2900+
// 如果填写了新密码,进行密码相关验证
2901+
if (newPassword) {
2902+
// 验证新密码长度
2903+
if (newPassword.length < 8) {
2904+
showNotification('新密码长度至少8位', 'error');
2905+
return;
2906+
}
2907+
2908+
// 验证确认密码
2909+
if (newPassword !== confirmPassword) {
2910+
showNotification('两次输入的新密码不一致', 'error');
2911+
return;
2912+
}
2913+
2914+
// 验证是否填写旧密码
2915+
if (!oldPassword) {
2916+
showNotification('修改密码需要输入旧密码', 'error');
2917+
return;
2918+
}
2919+
2920+
// 添加密码字段到更新数据
2921+
updateData.old_password = oldPassword;
2922+
updateData.new_password = newPassword;
2923+
}
2924+
2925+
try {
2926+
const response = await fetch(`${API_BASE}/auth/profile`, {
2927+
method: 'PUT',
2928+
headers: {
2929+
'Authorization': `Bearer ${localStorage.getItem('token')}`,
2930+
'Content-Type': 'application/json'
2931+
},
2932+
body: JSON.stringify(updateData)
2933+
});
2934+
2935+
const result = await response.json();
2936+
2937+
if (response.ok) {
2938+
showNotification(result.message || '更新成功', 'success');
2939+
closeUserSettingsModal();
2940+
2941+
// 更新页面显示的用户名
2942+
if (currentUser && updateData.username !== currentUser.username) {
2943+
currentUser.username = updateData.username;
2944+
document.getElementById('currentUsername').textContent = updateData.username;
2945+
}
2946+
2947+
// 如果修改了密码,强制重新登录
2948+
if (result.data && result.data.password_changed) {
2949+
showNotification('密码已修改,请重新登录', 'info');
2950+
setTimeout(() => {
2951+
logout();
2952+
}, 1500);
2953+
}
2954+
} else {
2955+
showNotification(result.error || '更新失败', 'error');
2956+
}
2957+
} catch (error) {
2958+
console.error('更新用户设置失败:', error);
2959+
showNotification('更新用户设置失败', 'error');
2960+
}
2961+
}
2962+
2963+
// 点击模态框外部关闭用户设置
2964+
window.addEventListener('click', function(event) {
2965+
const userSettingsModal = document.getElementById('userSettingsModal');
2966+
if (event.target === userSettingsModal) {
2967+
closeUserSettingsModal();
2968+
}
2969+
});

version.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version: 0.9.2
1+
version: 1.0.0

0 commit comments

Comments
 (0)