Flask_web-template/app/templates/auth/profile.html
2024-10-30 00:52:53 +08:00

189 lines
8.5 KiB
HTML

{% extends "base.html" %}
{% block content %}
<div class="container py-4">
<div class="row justify-content-center">
<div class="col-md-8">
<!-- 個人資料卡片 -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-primary text-white">
<h5 class="card-title mb-0">個人資料</h5>
</div>
<div class="card-body">
<!-- 頭像上傳表單 -->
<form id="avatarForm" method="POST" action="{{ url_for('auth.profile') }}" enctype="multipart/form-data" class="mb-4">
<input type="hidden" name="action" value="update_avatar">
<div class="row">
<div class="col-auto">
<div class="position-relative">
{% if current_user.avatar_path %}
<img src="{{ url_for('static', filename=current_user.avatar_path) }}"
class="rounded-circle"
style="width: 100px; height: 100px; object-fit: cover;"
alt="用戶頭像">
{% else %}
<div class="avatar-circle bg-primary text-white d-flex align-items-center justify-content-center"
style="width: 100px; height: 100px; border-radius: 50%; font-size: 2.5rem;">
{{ current_user.username[0].upper() }}
</div>
{% endif %}
<div class="position-absolute bottom-0 end-0">
<label for="avatar"
class="btn btn-light rounded-circle d-flex align-items-center justify-content-center shadow-sm"
style="width: 36px; height: 36px; padding: 0; cursor: pointer; margin-right: -8px; margin-bottom: -8px;">
<i class="bi bi-camera" style="font-size: 1.2rem;"></i>
</label>
<input type="file" id="avatar" name="avatar"
class="d-none" accept="image/*"
onchange="handleAvatarChange(this);">
</div>
</div>
</div>
<div class="col">
<h5 class="mb-1">{{ current_user.username }}</h5>
<p class="text-muted mb-0">{{ current_user.email }}</p>
<small class="text-muted">加入時間:{{ current_user.created_at.strftime('%Y-%m-%d') }}</small>
</div>
</div>
</form>
<!-- 個人資料表單 -->
<form method="POST" action="{{ url_for('auth.profile') }}">
<input type="hidden" name="action" value="update_profile">
<div class="mb-3">
<label class="form-label">用戶名</label>
<input type="text" class="form-control" name="username"
value="{{ current_user.username }}" required>
<div class="form-text">用戶名將顯示在您的個人檔案中</div>
</div>
<div class="mb-3">
<label class="form-label">電子郵件</label>
<input type="email" class="form-control" name="email"
value="{{ current_user.email }}" required>
<div class="form-text">用於接收通知和重要更新</div>
</div>
<button type="submit" class="btn btn-primary">
<i class="bi bi-save"></i> 保存變更
</button>
</form>
</div>
</div>
<!-- 密碼修改卡片 -->
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="card-title mb-0">修改密碼</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ url_for('auth.profile') }}" onsubmit="return validatePasswordForm()">
<input type="hidden" name="action" value="update_password">
<div class="mb-3">
<label class="form-label">目前密碼</label>
<input type="password" class="form-control" name="current_password" required>
</div>
<div class="mb-3">
<label class="form-label">新密碼</label>
<input type="password" class="form-control" name="new_password"
id="new_password" required>
<div class="form-text">密碼必須包含至少8個字元</div>
</div>
<div class="mb-3">
<label class="form-label">確認新密碼</label>
<input type="password" class="form-control" name="confirm_password"
id="confirm_password" required>
</div>
<button type="submit" class="btn btn-primary">
<i class="bi bi-key"></i> 更新密碼
</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function handleAvatarChange(input) {
if (input.files && input.files[0]) {
const file = input.files[0];
// 檢查文件大小
if (file.size > 1024 * 1024) {
alert('圖片大小不能超過 1MB');
input.value = '';
return;
}
// 檢查文件類型
if (!file.type.startsWith('image/')) {
alert('請上傳圖片文件');
input.value = '';
return;
}
// 預覽圖片
const reader = new FileReader();
reader.onload = function (e) {
const avatar = input.closest('.position-relative').querySelector('img');
if (avatar) {
avatar.src = e.target.result;
} else {
const avatarCircle = input.closest('.position-relative').querySelector('.avatar-circle');
const newAvatar = document.createElement('img');
newAvatar.src = e.target.result;
newAvatar.classList.add('rounded-circle');
newAvatar.style.width = '100px';
newAvatar.style.height = '100px';
newAvatar.style.objectFit = 'cover';
avatarCircle.replaceWith(newAvatar);
}
}
reader.readAsDataURL(file);
// 只提交頭像表單
document.getElementById('avatarForm').submit();
}
}
function validatePasswordForm() {
const newPassword = document.getElementById('new_password').value;
const confirmPassword = document.getElementById('confirm_password').value;
if (newPassword.length < 8) {
alert('新密碼長度必須至少8個字元');
return false;
}
if (newPassword !== confirmPassword) {
alert('兩次輸入的密碼不一致');
return false;
}
return true;
}
// Flash 消息自動隱藏
document.addEventListener('DOMContentLoaded', function () {
var alerts = document.querySelectorAll('.alert');
alerts.forEach(function (alert) {
setTimeout(function () {
alert.classList.add('fade');
setTimeout(function () {
alert.remove();
}, 150);
}, 3000);
});
});
</script>
{% endblock %}