feat : 优化文件上传 优化一体机体验

This commit is contained in:
2025-12-18 18:53:16 +08:00
parent 284d696b25
commit bb67e9ba12
11 changed files with 919 additions and 369 deletions

View File

@@ -62,38 +62,6 @@
margin-top: 10px;
}
.code-card {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 16px;
padding: 20px;
margin-bottom: 25px;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.3);
}
.code-label {
font-size: 14px;
color: #666;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.code-value {
font-size: 22px;
color: #2d3436;
font-weight: 700;
letter-spacing: 2px;
padding: 12px;
background: white;
border-radius: 12px;
margin-top: 8px;
word-break: break-all;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.upload-section {
margin-bottom: 25px;
}
@@ -131,6 +99,17 @@
background: rgba(102, 126, 234, 0.05);
}
.upload-area.disabled {
opacity: 0.6;
cursor: not-allowed;
background: #f5f5f5;
border-color: #e0e0e0;
}
.upload-area.disabled:active {
transform: none;
}
.upload-icon {
font-size: 48px;
color: #667eea;
@@ -161,6 +140,10 @@
cursor: pointer;
}
.file-input:disabled {
cursor: not-allowed;
}
.selected-files {
display: none;
}
@@ -516,6 +499,62 @@
font-size: 20px;
}
}
/* 限制提示样式 */
.limit-info {
background: #fff8e1;
border: 1px solid #ffd54f;
border-radius: 12px;
padding: 12px 16px;
margin-bottom: 20px;
font-size: 14px;
color: #f57c00;
display: none;
align-items: center;
gap: 8px;
animation: slideIn 0.3s ease;
}
.limit-info.show {
display: flex;
}
.limit-icon {
font-size: 18px;
flex-shrink: 0;
}
.limit-text {
flex: 1;
}
/* 限制警告提示 */
.limit-warning-info {
background: #ffebee;
border: 1px solid #ffcdd2;
border-radius: 12px;
padding: 12px 16px;
margin-bottom: 20px;
font-size: 14px;
color: #d32f2f;
display: none;
align-items: center;
gap: 8px;
animation: slideIn 0.3s ease;
}
.limit-warning-info.show {
display: flex;
}
.limit-warning-icon {
font-size: 18px;
flex-shrink: 0;
}
.limit-warning-text {
flex: 1;
}
</style>
</head>
<body>
@@ -526,18 +565,30 @@
</div>
<div class="main-content">
<!-- 限制提示 -->
<div class="limit-info" id="limitInfo">
<span class="limit-icon">⚠️</span>
<div class="limit-text" id="limitText">加载中...</div>
</div>
<!-- 总数量限制警告 -->
<div class="limit-warning-info" id="limitWarningInfo">
<span class="limit-warning-icon">⚠️</span>
<div class="limit-warning-text" id="limitWarningText">已超过文件上传总数限制</div>
</div>
<div class="upload-section">
<h3 class="section-title">📎 选择文件</h3>
<div class="upload-area" id="uploadArea">
<div class="upload-icon">📁</div>
<div class="upload-text">点击选择文件</div>
<div class="upload-hint">支持图片、文档、文本等格式<br />单个文件不超过10MB</div>
<div class="upload-text" id="uploadText">点击选择文件</div>
<div class="upload-hint" id="uploadHint">支持图片、文档、文本等格式</div>
<input
type="file"
id="fileInput"
class="file-input"
multiple
accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.csv,.ppt,.pptx,.txt,.md,.html"
accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.csv,.ppt,.pptx,.txt,.md"
/>
</div>
</div>
@@ -566,7 +617,7 @@
<!-- 状态提示框 -->
<div class="status-message" id="statusMessage">
<span class="status-icon"></span>
<span class="status-icon" id="statusIcon"></span>
<h3 class="status-title" id="statusTitle">上传成功!</h3>
<p class="status-desc" id="statusDesc">文件已成功上传到电脑端</p>
<button class="status-btn" id="statusBtn">完成</button>
@@ -579,15 +630,24 @@
</div>
<script>
// 获取URL中的code参数
// 获取URL中的参数
const urlParams = new URLSearchParams(window.location.search);
const sessionId = urlParams.get('sessionId');
const uploadApi = urlParams.get('uploadApi');
console.log(sessionId);
console.log(uploadApi);
const fileCountParam = urlParams.get('fileCount');
// 配置常量
const MAX_FILE_COUNT = fileCountParam ? parseInt(fileCountParam) : 2; // 从URL参数获取默认为2
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
console.log('Session ID:', sessionId);
console.log('Upload API:', uploadApi);
console.log('Max file count:', MAX_FILE_COUNT);
// DOM元素
const uploadArea = document.getElementById('uploadArea');
const uploadText = document.getElementById('uploadText');
const uploadHint = document.getElementById('uploadHint');
const fileInput = document.getElementById('fileInput');
const fileList = document.getElementById('fileList');
const selectedFilesContainer = document.getElementById('selectedFiles');
@@ -596,19 +656,34 @@
const loadingOverlay = document.getElementById('loadingOverlay');
const loadingText = document.getElementById('loadingText');
const statusMessage = document.getElementById('statusMessage');
const statusIcon = document.getElementById('statusIcon');
const statusTitle = document.getElementById('statusTitle');
const statusDesc = document.getElementById('statusDesc');
const statusBtn = document.getElementById('statusBtn');
const imagePreviewModal = document.getElementById('imagePreviewModal');
const previewImage = document.getElementById('previewImage');
const closePreview = document.getElementById('closePreview');
const limitInfo = document.getElementById('limitInfo');
const limitText = document.getElementById('limitText');
const limitWarningInfo = document.getElementById('limitWarningInfo');
const limitWarningText = document.getElementById('limitWarningText');
// 状态变量
let selectedFiles = [];
let isUploading = false;
let uploadedCount = 0; // 已上传的总文件数量
// 初始化
function init() {
// 更新限制提示文本
updateLimitText();
// 显示限制提示
limitInfo.classList.add('show');
// 检查本地存储中已上传的文件数量
checkUploadedCount();
// 事件监听
fileInput.addEventListener('change', handleFileSelect);
clearBtn.addEventListener('click', clearAllFiles);
@@ -632,6 +707,46 @@
// 防止页面滚动
document.body.addEventListener('touchmove', preventScroll, { passive: false });
// 更新UI
updateUI();
}
// 更新限制提示文本
function updateLimitText() {
if (MAX_FILE_COUNT <= 0) {
limitText.textContent = '未设置可上传文件数量';
} else {
limitText.textContent = `总共可上传 ${MAX_FILE_COUNT} 个文件每个文件不超过10MB已上传: ${uploadedCount}`;
}
}
// 检查已上传的文件数量
function checkUploadedCount() {
// 使用sessionStorage存储当前会话的上传数量
// 如果要永久存储可以改用localStorage
const storedCount = sessionStorage.getItem('uploadedFileCount');
uploadedCount = storedCount ? parseInt(storedCount) : 0;
// 更新警告提示
updateWarningText();
}
// 更新警告提示
function updateWarningText() {
if (MAX_FILE_COUNT > 0 && uploadedCount >= MAX_FILE_COUNT) {
limitWarningInfo.classList.add('show');
limitWarningText.textContent = `已超过文件上传总数限制(${MAX_FILE_COUNT}个)`;
} else {
limitWarningInfo.classList.remove('show');
}
}
// 保存已上传的文件数量
function saveUploadedCount() {
sessionStorage.setItem('uploadedFileCount', uploadedCount.toString());
updateLimitText();
updateWarningText();
}
// 处理文件选择
@@ -646,6 +761,12 @@
// 设置拖拽上传
function setupDragAndDrop() {
uploadArea.addEventListener('dragover', (e) => {
// 如果已达总数限制,禁止拖拽
if (MAX_FILE_COUNT > 0 && uploadedCount >= MAX_FILE_COUNT) {
e.preventDefault();
return;
}
e.preventDefault();
uploadArea.classList.add('dragover');
});
@@ -659,6 +780,12 @@
e.preventDefault();
uploadArea.classList.remove('dragover');
// 如果已达总数限制,禁止拖拽上传
if (MAX_FILE_COUNT > 0 && uploadedCount >= MAX_FILE_COUNT) {
showError(`已超过文件上传总数限制(${MAX_FILE_COUNT}个)`);
return;
}
if (e.dataTransfer.files.length) {
handleFiles(e.dataTransfer.files);
}
@@ -667,12 +794,41 @@
// 处理文件
function handleFiles(files) {
const maxSize = 20 * 1024 * 1024; // 20MB
// 检查是否已达到总文件数量上限
if (MAX_FILE_COUNT > 0 && uploadedCount >= MAX_FILE_COUNT) {
showError(`已超过文件上传总数限制(${MAX_FILE_COUNT}个)`);
return;
}
// 检查当前选择的文件是否会导致超过总数限制
const potentialTotalCount = uploadedCount + files.length;
if (MAX_FILE_COUNT > 0 && potentialTotalCount > MAX_FILE_COUNT) {
showError(`最多只能上传 ${MAX_FILE_COUNT} 个文件,已上传 ${uploadedCount}`);
return;
}
// 检查是否已达到本次选择的文件数量上限
if (selectedFiles.length >= MAX_FILE_COUNT) {
showError(`最多只能选择 ${MAX_FILE_COUNT} 个文件`);
return;
}
for (let file of files) {
// 检查是否已达到本次选择的文件数量上限
if (selectedFiles.length >= MAX_FILE_COUNT) {
showError(`最多只能选择 ${MAX_FILE_COUNT} 个文件,已忽略多余文件`);
break;
}
// 检查是否会导致超过总数限制
if (MAX_FILE_COUNT > 0 && (uploadedCount + selectedFiles.length) >= MAX_FILE_COUNT) {
showError(`已超过文件上传总数限制(${MAX_FILE_COUNT}个)`);
break;
}
// 检查文件大小
if (file.size > maxSize) {
showError(`文件 ${file.name} 超过20MB限制`);
if (file.size > MAX_FILE_SIZE) {
showError(`文件 ${file.name} 超过10MB限制`);
continue;
}
@@ -843,18 +999,55 @@
// 更新UI状态
function updateUI() {
const hasFiles = selectedFiles.length > 0;
const isTotalLimitReached = MAX_FILE_COUNT > 0 && uploadedCount >= MAX_FILE_COUNT;
// 显示/隐藏文件列表
selectedFilesContainer.classList.toggle('show', hasFiles);
// 更新按钮状态
clearBtn.disabled = !hasFiles || isUploading;
uploadBtn.disabled = !hasFiles || isUploading;
// 检查是否已达总文件数量上限
if (isTotalLimitReached) {
// 禁用所有上传相关功能
uploadArea.classList.add('disabled');
fileInput.disabled = true;
uploadText.textContent = '文件上传总数已达上限';
uploadHint.innerHTML = `总共可上传 ${MAX_FILE_COUNT} 个文件<br />已上传: ${uploadedCount}`;
// 禁用按钮
clearBtn.disabled = true;
uploadBtn.disabled = true;
// 显示限制警告提示
limitWarningInfo.classList.add('show');
limitWarningText.textContent = `已超过文件上传总数限制(${MAX_FILE_COUNT}个)`;
} else {
// 更新上传区域状态
uploadArea.classList.remove('disabled');
// 根据文件数量更新上传区域
if (MAX_FILE_COUNT <= 0) {
// 如果没有设置文件数量限制,始终可以上传
uploadText.textContent = '点击选择文件';
uploadHint.innerHTML = '支持图片、文档、文本等格式<br />文件大小不超过10MB';
fileInput.disabled = false;
} else if (selectedFiles.length >= MAX_FILE_COUNT) {
uploadText.textContent = `已达到最大文件数量(${MAX_FILE_COUNT}个)`;
uploadHint.innerHTML = `最多${MAX_FILE_COUNT}个文件每个不超过10MB<br /><strong>已选满</strong>`;
fileInput.disabled = true;
} else {
uploadText.textContent = '点击选择文件';
uploadHint.innerHTML = `支持图片、文档、文本等格式<br />最多${MAX_FILE_COUNT}个文件每个不超过10MB<br />已上传: ${uploadedCount}/${MAX_FILE_COUNT}`;
fileInput.disabled = false;
}
// 更新按钮状态
clearBtn.disabled = !hasFiles || isUploading;
uploadBtn.disabled = !hasFiles || isUploading;
}
// 更新上传按钮文本
if (hasFiles) {
if (hasFiles && !isTotalLimitReached) {
const totalSize = selectedFiles.reduce((sum, file) => sum + file.size, 0);
uploadBtn.innerHTML = `<span>⬆️</span> 上传 (${selectedFiles.length}, ${formatFileSize(
uploadBtn.innerHTML = `<span>⬆️</span> 上传 (${selectedFiles.length}/${MAX_FILE_COUNT}, ${formatFileSize(
totalSize
)})`;
} else {
@@ -866,6 +1059,19 @@
async function startUpload() {
if (isUploading || selectedFiles.length === 0) return;
// 检查是否已达总数限制
if (MAX_FILE_COUNT > 0 && uploadedCount >= MAX_FILE_COUNT) {
showError(`已超过文件上传总数限制(${MAX_FILE_COUNT}个)`);
return;
}
// 检查是否会导致超过总数限制
const potentialTotalCount = uploadedCount + selectedFiles.length;
if (MAX_FILE_COUNT > 0 && potentialTotalCount > MAX_FILE_COUNT) {
showError(`最多只能上传 ${MAX_FILE_COUNT} 个文件,已上传 ${uploadedCount}`);
return;
}
isUploading = true;
updateUI();
showLoading('正在准备上传...');
@@ -903,6 +1109,7 @@
} catch (error) {
console.error(`文件上传失败: ${file.name}`, error);
failCount++;
const progressBar = document.querySelector(`#progress-${CSS.escape(file.name)}`);
if (progressBar) {
progressBar.style.width = '0%';
}
@@ -913,9 +1120,15 @@
hideLoading();
if (successCount > 0) {
// 更新已上传的文件数量
uploadedCount += successCount;
saveUploadedCount();
showSuccess(`成功上传 ${successCount} 个文件${failCount > 0 ? `${failCount} 个失败` : ''}`);
// 清空文件列表
clearAllFiles();
// 更新UI
updateUI();
} else {
showError('文件上传失败,请重试');
}
@@ -957,7 +1170,7 @@
const result = await response.json();
return {
success: result.code == 200 ,
success: result.code == 200,
data: result,
};
} catch (error) {
@@ -984,6 +1197,7 @@
// 显示成功提示
function showSuccess(message) {
statusMessage.className = 'status-message status-success';
statusIcon.textContent = '✅';
statusTitle.textContent = '上传成功!';
statusDesc.textContent = message;
statusMessage.style.display = 'block';
@@ -993,6 +1207,7 @@
// 显示错误提示
function showError(message) {
statusMessage.className = 'status-message status-error';
statusIcon.textContent = '❌';
statusTitle.textContent = '出错了';
statusDesc.textContent = message;
statusMessage.style.display = 'block';
@@ -1031,4 +1246,4 @@
document.addEventListener('drop', (e) => e.preventDefault());
</script>
</body>
</html>
</html>