344 lines
11 KiB
JavaScript
344 lines
11 KiB
JavaScript
// 个人中心页面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); // 每秒检查一次
|