Files
aitsc/src/flask_prompt_master/templates/auth/profile.html
2025-08-29 20:32:52 +08:00

409 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}个人资料 - 提示词大师{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<!-- 侧边栏 -->
<div class="col-md-3">
<div class="card">
<div class="card-header">
<h5 class="mb-0">个人中心</h5>
</div>
<div class="card-body">
<div class="nav flex-column nav-pills" id="profile-tab" role="tablist">
<button class="nav-link active" id="profile-info-tab" data-bs-toggle="pill" data-bs-target="#profile-info" type="button" role="tab">
<i class="fas fa-user me-2"></i>基本信息
</button>
<button class="nav-link" id="change-password-tab" data-bs-toggle="pill" data-bs-target="#change-password" type="button" role="tab">
<i class="fas fa-lock me-2"></i>修改密码
</button>
<button class="nav-link" id="usage-stats-tab" data-bs-toggle="pill" data-bs-target="#usage-stats" type="button" role="tab">
<i class="fas fa-chart-bar me-2"></i>使用统计
</button>
</div>
</div>
</div>
</div>
<!-- 主内容区 -->
<div class="col-md-9">
<div class="tab-content" id="profile-tabContent">
<!-- 基本信息 -->
<div class="tab-pane fade show active" id="profile-info" role="tabpanel">
<div class="card">
<div class="card-header">
<h4 class="mb-0">基本信息</h4>
</div>
<div class="card-body">
<form id="profile-form">
<div class="row">
<div class="col-md-6 mb-3">
<label for="nickname" class="form-label">昵称 <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="nickname" name="nickname" required>
</div>
<div class="col-md-6 mb-3">
<label for="login_name" class="form-label">用户名</label>
<input type="text" class="form-control" id="login_name" readonly>
<small class="text-muted">用户名不可修改</small>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="email" class="form-label">邮箱</label>
<input type="email" class="form-control" id="email" name="email">
</div>
<div class="col-md-6 mb-3">
<label for="mobile" class="form-label">手机号</label>
<input type="tel" class="form-control" id="mobile" name="mobile">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="sex" class="form-label">性别</label>
<select class="form-select" id="sex" name="sex">
<option value="0">保密</option>
<option value="1"></option>
<option value="2"></option>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="avatar" class="form-label">头像</label>
<div class="d-flex align-items-center">
<img id="avatar-preview" src="/static/images/default-avatar.png" alt="头像" class="rounded-circle me-3" style="width: 60px; height: 60px; object-fit: cover;">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="document.getElementById('avatar-input').click()">
更换头像
</button>
<input type="file" id="avatar-input" accept="image/*" style="display: none;">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="created_time" class="form-label">注册时间</label>
<input type="text" class="form-control" id="created_time" readonly>
</div>
<div class="col-md-6 mb-3">
<label for="last_login" class="form-label">最后登录</label>
<input type="text" class="form-control" id="last_login" readonly>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save me-2"></i>保存修改
</button>
</div>
</form>
</div>
</div>
</div>
<!-- 修改密码 -->
<div class="tab-pane fade" id="change-password" role="tabpanel">
<div class="card">
<div class="card-header">
<h4 class="mb-0">修改密码</h4>
</div>
<div class="card-body">
<form id="password-form">
<div class="mb-3">
<label for="old_password" class="form-label">当前密码 <span class="text-danger">*</span></label>
<input type="password" class="form-control" id="old_password" name="old_password" required>
</div>
<div class="mb-3">
<label for="new_password" class="form-label">新密码 <span class="text-danger">*</span></label>
<input type="password" class="form-control" id="new_password" name="new_password" required>
<div class="form-text">密码长度至少6位建议包含字母、数字和特殊字符</div>
</div>
<div class="mb-3">
<label for="confirm_password" class="form-label">确认新密码 <span class="text-danger">*</span></label>
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-warning">
<i class="fas fa-key me-2"></i>修改密码
</button>
</div>
</form>
</div>
</div>
</div>
<!-- 使用统计 -->
<div class="tab-pane fade" id="usage-stats" role="tabpanel">
<div class="card">
<div class="card-header">
<h4 class="mb-0">使用统计</h4>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4 mb-3">
<div class="card bg-primary text-white">
<div class="card-body text-center">
<h3 id="total-prompts">0</h3>
<p class="mb-0">生成提示词</p>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="card bg-success text-white">
<div class="card-body text-center">
<h3 id="total-favorites">0</h3>
<p class="mb-0">收藏数量</p>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="card bg-info text-white">
<div class="card-body text-center">
<h3 id="days-active">0</h3>
<p class="mb-0">活跃天数</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<h5>最近活动</h5>
<div id="recent-activity">
<p class="text-muted">加载中...</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 成功提示模态框 -->
<div class="modal fade" id="successModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">操作成功</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p id="success-message">操作已成功完成</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">确定</button>
</div>
</div>
</div>
</div>
<!-- 错误提示模态框 -->
<div class="modal fade" id="errorModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">操作失败</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p id="error-message">操作失败,请重试</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">确定</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
// 页面加载完成后执行
$(document).ready(function() {
loadProfile();
loadUsageStats();
// 基本信息表单提交
$('#profile-form').submit(function(e) {
e.preventDefault();
updateProfile();
});
// 修改密码表单提交
$('#password-form').submit(function(e) {
e.preventDefault();
changePassword();
});
// 头像上传
$('#avatar-input').change(function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
$('#avatar-preview').attr('src', e.target.result);
};
reader.readAsDataURL(file);
}
});
});
// 加载个人资料
function loadProfile() {
$.get('/api/profile')
.done(function(response) {
if (response.success) {
const user = response.data;
$('#nickname').val(user.nickname || '');
$('#login_name').val(user.login_name || '');
$('#email').val(user.email || '');
$('#mobile').val(user.mobile || '');
$('#sex').val(user.sex || 0);
$('#created_time').val(user.created_time || '');
$('#last_login').val(user.last_login || '');
if (user.avatar) {
$('#avatar-preview').attr('src', user.avatar);
}
} else {
showError(response.message || '加载个人资料失败');
}
})
.fail(function() {
showError('加载个人资料失败');
});
}
// 更新个人资料
function updateProfile() {
const formData = {
nickname: $('#nickname').val(),
email: $('#email').val(),
mobile: $('#mobile').val(),
sex: parseInt($('#sex').val())
};
$.ajax({
url: '/api/profile',
method: 'PUT',
contentType: 'application/json',
data: JSON.stringify(formData)
})
.done(function(response) {
if (response.success) {
showSuccess('个人资料更新成功');
// 更新session中的昵称
if (formData.nickname) {
// 这里可以更新页面上的用户昵称显示
}
} else {
showError(response.message || '更新失败');
}
})
.fail(function() {
showError('更新失败,请重试');
});
}
// 修改密码
function changePassword() {
const oldPassword = $('#old_password').val();
const newPassword = $('#new_password').val();
const confirmPassword = $('#confirm_password').val();
if (newPassword !== confirmPassword) {
showError('两次输入的新密码不一致');
return;
}
if (newPassword.length < 6) {
showError('新密码长度至少6位');
return;
}
$.ajax({
url: '/api/change-password',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
old_password: oldPassword,
new_password: newPassword
})
})
.done(function(response) {
if (response.success) {
showSuccess('密码修改成功,请重新登录');
// 清空表单
$('#password-form')[0].reset();
// 可以选择跳转到登录页面
setTimeout(function() {
window.location.href = '/login';
}, 2000);
} else {
showError(response.message || '密码修改失败');
}
})
.fail(function() {
showError('密码修改失败,请重试');
});
}
// 加载使用统计
function loadUsageStats() {
$.get('/api/profile/stats')
.done(function(response) {
if (response.success) {
const data = response.data;
$('#total-prompts').text(data.total_prompts || 0);
$('#total-favorites').text(data.total_favorites || 0);
$('#days-active').text(data.days_active || 0);
// 加载最近活动
let activityHtml = '<div class="list-group">';
if (data.recent_activities && data.recent_activities.length > 0) {
data.recent_activities.forEach(activity => {
activityHtml += `
<div class="list-group-item">
<div class="d-flex justify-content-between">
<span>${activity.type}: ${activity.content}</span>
<small class="text-muted">${activity.time}</small>
</div>
</div>
`;
});
} else {
activityHtml += '<div class="list-group-item"><span class="text-muted">暂无活动记录</span></div>';
}
activityHtml += '</div>';
$('#recent-activity').html(activityHtml);
} else {
$('#recent-activity').html('<p class="text-danger">加载统计信息失败</p>');
}
})
.fail(function() {
$('#recent-activity').html('<p class="text-danger">加载统计信息失败</p>');
});
}
// 显示成功提示
function showSuccess(message) {
$('#success-message').text(message);
new bootstrap.Modal(document.getElementById('successModal')).show();
}
// 显示错误提示
function showError(message) {
$('#error-message').text(message);
new bootstrap.Modal(document.getElementById('errorModal')).show();
}
</script>
{% endblock %}