2025-07-04 19:07:35 +08:00

344 lines
11 KiB
JavaScript
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.

// 个人中心页面JavaScript功能
let selectedFile = null;
// 强制设置头像样式的函数
function forceAvatarStyle(imgElement) {
if (!imgElement) return;
// 强制设置所有样式属性
imgElement.style.width = '120px';
imgElement.style.height = '120px';
imgElement.style.borderRadius = '50%';
imgElement.style.border = '3px solid #ddd';
imgElement.style.objectFit = 'cover';
imgElement.style.cursor = 'pointer';
imgElement.style.transition = 'all 0.3s ease';
imgElement.style.display = 'block';
imgElement.style.maxWidth = '120px';
imgElement.style.maxHeight = '120px';
imgElement.style.minWidth = '120px';
imgElement.style.minHeight = '120px';
// 设置属性避免被覆盖
imgElement.setAttribute('width', '120');
imgElement.setAttribute('height', '120');
}
// 页面加载完成后的处理
document.addEventListener('DOMContentLoaded', function() {
// 隐藏进度条
const progressContainer = document.getElementById('uploadProgress');
if (progressContainer) {
progressContainer.classList.remove('show');
progressContainer.style.display = 'none';
}
// *** 关键:强制设置已存在的头像样式 ***
const existingAvatar = document.getElementById('avatarPreview');
if (existingAvatar) {
forceAvatarStyle(existingAvatar);
// 图片加载完成后再次强制设置
if (existingAvatar.complete) {
forceAvatarStyle(existingAvatar);
} else {
existingAvatar.onload = function() {
forceAvatarStyle(existingAvatar);
};
}
}
// 添加拖拽上传支持
initDragAndDrop();
});
// 触发文件选择
function triggerFileInput() {
document.getElementById('avatarInput').click();
}
// 处理文件选择
function handleFileSelect(event) {
const file = event.target.files[0];
if (!file) return;
// 验证文件类型
if (!file.type.match('image.*')) {
showAlert('请选择图片文件!', 'error');
return;
}
// 验证文件大小 (2MB)
if (file.size > 2 * 1024 * 1024) {
showAlert('图片大小不能超过 2MB', 'error');
return;
}
selectedFile = file;
// 预览图片
const reader = new FileReader();
reader.onload = function(e) {
const previewImage = document.getElementById('previewImage');
previewImage.src = e.target.result;
// 更新文件信息
updateFileInfo(file);
// 确保图片加载完成后再显示模态框
previewImage.onload = function() {
// *** 强制设置预览图片样式 ***
previewImage.style.maxWidth = '280px';
previewImage.style.maxHeight = '280px';
previewImage.style.width = 'auto';
previewImage.style.height = 'auto';
previewImage.style.objectFit = 'contain';
previewImage.style.borderRadius = '12px';
previewImage.style.boxShadow = '0 8px 25px rgba(0,0,0,0.15)';
previewImage.style.border = '3px solid #fff';
// 更新图片尺寸信息
document.getElementById('imageWidth').textContent = previewImage.naturalWidth;
document.getElementById('imageHeight').textContent = previewImage.naturalHeight;
const modal = new bootstrap.Modal(document.getElementById('imagePreviewModal'));
modal.show();
};
};
reader.readAsDataURL(file);
}
// 更新文件信息
function updateFileInfo(file) {
// 文件大小
const sizeInMB = (file.size / 1024 / 1024).toFixed(2);
document.getElementById('imageSize').textContent = sizeInMB + ' MB';
// 文件类型
const fileType = file.type.split('/')[1].toUpperCase();
document.getElementById('imageType').textContent = fileType;
}
// 确认上传
function confirmUpload() {
if (!selectedFile) return;
// 关闭模态框
const modal = bootstrap.Modal.getInstance(document.getElementById('imagePreviewModal'));
modal.hide();
// 开始上传
uploadAvatar(selectedFile);
}
// 上传头像
function uploadAvatar(file) {
const formData = new FormData();
formData.append('avatar', file);
// 显示上传进度
const progressContainer = document.getElementById('uploadProgress');
const progressBar = progressContainer.querySelector('.progress-bar');
progressContainer.style.display = 'block';
progressContainer.classList.add('show');
progressBar.style.width = '0%';
progressBar.textContent = '0%';
// 创建XMLHttpRequest以支持进度显示
const xhr = new XMLHttpRequest();
// 上传进度
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
const percentComplete = (e.loaded / e.total) * 100;
progressBar.style.width = percentComplete + '%';
progressBar.textContent = Math.round(percentComplete) + '%';
}
});
// 上传完成
xhr.addEventListener('load', function() {
// 隐藏进度条
progressContainer.style.display = 'none';
progressContainer.classList.remove('show');
if (xhr.status === 200) {
try {
const response = JSON.parse(xhr.responseText);
if (response.success) {
// 更新头像显示
updateAvatarDisplay(response.avatar_url);
showAlert('头像上传成功!', 'success');
} else {
showAlert(response.message || '上传失败', 'error');
}
} catch (e) {
showAlert('服务器响应错误', 'error');
}
} else {
showAlert('上传失败,请重试', 'error');
}
// 清理文件输入
document.getElementById('avatarInput').value = '';
selectedFile = null;
});
// 上传错误
xhr.addEventListener('error', function() {
progressContainer.style.display = 'none';
progressContainer.classList.remove('show');
showAlert('网络错误,请重试', 'error');
// 清理文件输入
document.getElementById('avatarInput').value = '';
selectedFile = null;
});
// 发送请求
xhr.open('POST', '/upload/avatar');
xhr.send(formData);
}
// *** 关键:更新头像显示函数 ***
function updateAvatarDisplay(avatarUrl) {
const avatarPreview = document.getElementById('avatarPreview');
const avatarPlaceholder = document.getElementById('avatarPlaceholder');
if (avatarPreview) {
// 更新现有头像
avatarPreview.src = avatarUrl + '?t=' + new Date().getTime();
// *** 强制设置头像样式 ***
avatarPreview.onload = function() {
forceAvatarStyle(avatarPreview);
// 延迟再次确保样式生效
setTimeout(function() {
forceAvatarStyle(avatarPreview);
}, 100);
};
} else if (avatarPlaceholder) {
// 替换占位符为头像
const avatarUpload = avatarPlaceholder.parentElement;
avatarPlaceholder.remove();
const img = document.createElement('img');
img.src = avatarUrl + '?t=' + new Date().getTime();
img.alt = '头像';
img.className = 'avatar-preview';
img.id = 'avatarPreview';
// *** 创建新头像时强制设置样式 ***
img.onload = function() {
forceAvatarStyle(img);
// 延迟再次确保样式生效
setTimeout(function() {
forceAvatarStyle(img);
}, 100);
};
avatarUpload.insertBefore(img, avatarUpload.firstChild);
}
}
// 显示提示信息
function showAlert(message, type = 'info') {
// 移除现有的提示框
const existingAlerts = document.querySelectorAll('.alert.position-fixed');
existingAlerts.forEach(alert => alert.remove());
// 创建提示框
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type === 'error' ? 'danger' : type} alert-dismissible fade show position-fixed`;
alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px; max-width: 400px;';
const icon = type === 'success' ? 'check-circle' : type === 'error' ? 'exclamation-triangle' : 'info-circle';
alertDiv.innerHTML = `
<i class="bi bi-${icon} me-2"></i>
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(alertDiv);
// 3秒后自动消失
setTimeout(() => {
if (alertDiv.parentElement) {
alertDiv.classList.remove('show');
setTimeout(() => {
if (alertDiv.parentElement) {
alertDiv.remove();
}
}, 150);
}
}, 3000);
}
// 初始化拖拽上传功能
function initDragAndDrop() {
const avatarUpload = document.querySelector('.avatar-upload');
if (avatarUpload) {
// 防止默认拖拽行为
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
avatarUpload.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
// 拖拽进入和离开的视觉反馈
['dragenter', 'dragover'].forEach(eventName => {
avatarUpload.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
avatarUpload.addEventListener(eventName, unhighlight, false);
});
function highlight(e) {
avatarUpload.style.transform = 'scale(1.05)';
avatarUpload.style.boxShadow = '0 0 20px rgba(0,123,255,0.5)';
}
function unhighlight(e) {
avatarUpload.style.transform = '';
avatarUpload.style.boxShadow = '';
}
// 处理文件拖拽
avatarUpload.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
if (files.length > 0) {
const file = files[0];
// 模拟文件输入事件
const event = { target: { files: [file] } };
handleFileSelect(event);
}
}
}
}
// 额外的保险措施:定期检查并修正头像样式
setInterval(function() {
const avatar = document.getElementById('avatarPreview');
if (avatar) {
// 检查头像是否超出预期尺寸
const rect = avatar.getBoundingClientRect();
if (rect.width > 125 || rect.height > 125) {
forceAvatarStyle(avatar);
}
}
}, 1000); // 每秒检查一次