打开/关闭菜单
443
1222
42
4823
植物大战僵尸杂交版Wiki
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

微件:BatchUpload:修订间差异

来自植物大战僵尸杂交版Wiki
无编辑摘要
无编辑摘要
 
第47行: 第47行:
}
}
.batch-upload-item .file-rename:focus { border-color: #4CAF50; outline: none; }
.batch-upload-item .file-rename:focus { border-color: #4CAF50; outline: none; }
.batch-upload-item .file-status { font-size: 12px; min-width: 70px; text-align: right; }
.batch-upload-item .file-status { font-size: 12px; min-width: 85px; text-align: right; }
.status-waiting { color: #999; }
.status-waiting { color: #999; }
.status-uploading { color: #2196F3; }
.status-uploading { color: #2196F3; }
.status-success { color: #4CAF50; }
.status-success { color: #4CAF50; }
.status-error { color: #f44336; }
.status-error { color: #f44336; }
.status-retrying { color: #FF9800; }
.status-conflict { color: #FF9800; }
.status-conflict { color: #FF9800; }
.status-skipped { color: #9E9E9E; }
.status-skipped { color: #9E9E9E; }
第125行: 第126行:
     var isUploading = false;
     var isUploading = false;
     var conflictResolved = false;
     var conflictResolved = false;
    var MAX_RETRIES = 3;
    var retryCounts = {};
    var currentFailedFiles = [];


     function getExt(filename) {
     function getExt(filename) {
第168行: 第172行:
         files = [];
         files = [];
         conflictResolved = false;
         conflictResolved = false;
        retryCounts = {};
        currentFailedFiles = [];
         $conflictNotice.style.display = 'none';
         $conflictNotice.style.display = 'none';
         renderList();
         renderList();
第180行: 第186行:
                 file._targetName = getNameWithoutExt(file.name);
                 file._targetName = getNameWithoutExt(file.name);
                 file._ext = getExt(file.name);
                 file._ext = getExt(file.name);
                 file._conflictAction = 'ask'; // ask | overwrite | skip
                 file._conflictAction = 'ask';
                file._fileId = Date.now() + '_' + i + '_' + Math.random().toString(36).substr(2, 5);
                 files.push(file);
                 files.push(file);
                retryCounts[file._fileId] = 0;
             }
             }
         }
         }
第236行: 第244行:
             btn.addEventListener('click', function() {
             btn.addEventListener('click', function() {
                 var idx = parseInt(this.getAttribute('data-index'));
                 var idx = parseInt(this.getAttribute('data-index'));
                delete retryCounts[files[idx]._fileId];
                 files.splice(idx, 1);
                 files.splice(idx, 1);
                 renderList();
                 renderList();
第244行: 第253行:


     function updateStartButton() {
     function updateStartButton() {
         $startBtn.disabled = files.length === 0 || isUploading;
         if (currentFailedFiles.length > 0) {
         if (conflictResolved) {
            $startBtn.disabled = false;
            $startBtn.textContent = '重试失败文件 (' + currentFailedFiles.length + ')';
            $startBtn.style.background = '#FF9800';
         } else if (conflictResolved) {
            $startBtn.disabled = false;
             $startBtn.textContent = '开始上传';
             $startBtn.textContent = '开始上传';
            $startBtn.style.background = '#4CAF50';
         } else {
         } else {
            $startBtn.disabled = files.length === 0 || isUploading;
             $startBtn.textContent = '检测并上传';
             $startBtn.textContent = '检测并上传';
            $startBtn.style.background = '#4CAF50';
         }
         }
     }
     }
第256行: 第272行:
     }
     }


    // 检查文件是否存在
     function checkFileExists(filename) {
     function checkFileExists(filename) {
         return new Promise(function(resolve) {
         return new Promise(function(resolve) {
第293行: 第308行:
                     var data = JSON.parse(xhr.responseText);
                     var data = JSON.parse(xhr.responseText);
                     if (data.upload && data.upload.result === 'Success') {
                     if (data.upload && data.upload.result === 'Success') {
                         resolve({ success: true, name: targetName });
                         resolve({ success: true, name: targetName, fileId: file._fileId });
                     } else {
                     } else {
                         var errMsg = '未知错误';
                         var errMsg = '未知错误';
                         if (data.upload && data.upload.warnings) errMsg = JSON.stringify(data.upload.warnings);
                         if (data.upload && data.upload.warnings) errMsg = JSON.stringify(data.upload.warnings);
                         else if (data.error) errMsg = data.error.info || '未知错误';
                         else if (data.error) errMsg = data.error.info || '未知错误';
                         resolve({ success: false, name: targetName, error: errMsg });
                         resolve({ success: false, name: targetName, error: errMsg, fileId: file._fileId });
                     }
                     }
                 } catch(e) {
                 } catch(e) {
                     resolve({ success: false, name: targetName, error: '解析响应失败' });
                     resolve({ success: false, name: targetName, error: '解析响应失败', fileId: file._fileId });
                 }
                 }
             };
             };
             xhr.onerror = function() {
             xhr.onerror = function() {
                 resolve({ success: false, name: targetName, error: '网络错误' });
                 resolve({ success: false, name: targetName, error: '网络错误', fileId: file._fileId });
             };
             };
             xhr.send(formData);
             xhr.send(formData);
第311行: 第326行:
     }
     }


     // 显示冲突处理 UI
     function delay(ms) {
        return new Promise(function(resolve) { setTimeout(resolve, ms); });
    }
 
    function uploadWithRetry(file, index, attemptNumber) {
        attemptNumber = attemptNumber || 1;
        var statusEl = $list.querySelector('.file-status[data-index="' + index + '"]');
 
        if (attemptNumber > 1 && statusEl) {
            statusEl.classList.remove('status-error', 'status-uploading');
            statusEl.classList.add('status-retrying');
            statusEl.textContent = '重试 ' + (attemptNumber - 1) + '/' + MAX_RETRIES;
        }
 
        return uploadFile(file, index).then(function(result) {
            if (result.success) {
                if (statusEl) {
                    statusEl.classList.remove('status-uploading', 'status-retrying', 'status-error');
                    statusEl.classList.add('status-success');
                    statusEl.textContent = '✅ 成功';
                }
                retryCounts[file._fileId] = 0;
                uploadedCount++;
                var progress = Math.round((uploadedCount / totalCount) * 100);
                $progressBar.style.width = progress + '%';
                return { success: true, index: index };
            } else {
                if (attemptNumber < MAX_RETRIES) {
                    if (statusEl) {
                        statusEl.classList.remove('status-uploading', 'status-error');
                        statusEl.classList.add('status-retrying');
                        statusEl.textContent = '重试 ' + attemptNumber + '/' + MAX_RETRIES;
                    }
                    var waitTime = attemptNumber * 2000;
                    return delay(waitTime).then(function() {
                        return uploadWithRetry(file, index, attemptNumber + 1);
                    });
                } else {
                    if (statusEl) {
                        statusEl.classList.remove('status-uploading', 'status-retrying');
                        statusEl.classList.add('status-error');
                        statusEl.textContent = '❌ 失败(' + MAX_RETRIES + '次)';
                    }
                    retryCounts[file._fileId] = MAX_RETRIES;
                    uploadedCount++;
                    var progress = Math.round((uploadedCount / totalCount) * 100);
                    $progressBar.style.width = progress + '%';
                    currentFailedFiles.push({ file: file, index: index, error: result.error });
                    return { success: false, index: index, error: result.error };
                }
            }
        });
    }
 
     function showConflictUI(conflicts) {
     function showConflictUI(conflicts) {
         $conflictNotice.style.display = 'block';
         $conflictNotice.style.display = 'block';
第333行: 第401行:
         });
         });


        // 在列表中为每个冲突项添加覆盖/跳过按钮
         conflicts.forEach(function(idx) {
         conflicts.forEach(function(idx) {
             var item = $list.querySelector('.batch-upload-item[data-index="' + idx + '"]');
             var item = $list.querySelector('.batch-upload-item[data-index="' + idx + '"]');
第343行: 第410行:
                 statusEl.textContent = '⚠️ 重名';
                 statusEl.textContent = '⚠️ 重名';
             }
             }
            // 移除旧的动作区
             var oldActions = item.querySelector('.conflict-actions');
             var oldActions = item.querySelector('.conflict-actions');
             if (oldActions) oldActions.remove();
             if (oldActions) oldActions.remove();
第355行: 第421行:
         });
         });


        // 绑定单条操作
         $list.querySelectorAll('.conflict-btn.overwrite').forEach(function(btn) {
         $list.querySelectorAll('.conflict-btn.overwrite').forEach(function(btn) {
             btn.addEventListener('click', function(e) {
             btn.addEventListener('click', function(e) {
第400行: 第465行:
     }
     }


    // 主流程:先检测再上传
     $startBtn.addEventListener('click', function() {
     $startBtn.addEventListener('click', function() {
         if (isUploading || files.length === 0) return;
         if (isUploading) return;
 
        // 如果有失败文件,点击重试
        if (currentFailedFiles.length > 0) {
            retryFailedFiles();
            return;
        }
 
        if (files.length === 0) return;


        // 如果冲突已解决,直接上传
         if (conflictResolved) {
         if (conflictResolved) {
             startUpload();
             startUpload();
第410行: 第481行:
         }
         }


        // 先检测重名
         isUploading = true;
         isUploading = true;
         updateStartButton();
         updateStartButton();
第461行: 第531行:
         uploadedCount = 0;
         uploadedCount = 0;
         totalCount = 0;
         totalCount = 0;
        currentFailedFiles = [];
         updateStartButton();
         updateStartButton();
         $selectBtn.disabled = true;
         $selectBtn.disabled = true;
第471行: 第542行:
         $list.querySelectorAll('.conflict-actions').forEach(function(i) { i.style.display = 'none'; });
         $list.querySelectorAll('.conflict-actions').forEach(function(i) { i.style.display = 'none'; });


        // 过滤掉跳过的文件
         var toUpload = [];
         var toUpload = [];
         files.forEach(function(f, idx) {
         files.forEach(function(f, idx) {
第481行: 第551行:
         totalCount = toUpload.length;
         totalCount = toUpload.length;
         if (totalCount === 0) {
         if (totalCount === 0) {
             isUploading = false;
             finishUpload();
            $selectBtn.disabled = false;
            $clearBtn.disabled = false;
            updateStartButton();
            $summary.style.display = 'block';
            $summary.innerHTML = '所有文件已跳过,没有上传。';
            $progress.style.display = 'none';
            files = [];
             return;
             return;
         }
         }
第501行: 第564行:
                     statusEl.textContent = '上传中...';
                     statusEl.textContent = '上传中...';
                 }
                 }
                 return uploadFile(item.file, item.index).then(function(result) {
                 return uploadWithRetry(item.file, item.index);
                    uploadedCount++;
            });
                    var progress = Math.round((uploadedCount / totalCount) * 100);
        });
                    $progressBar.style.width = progress + '%';
 
                    if (statusEl) {
        uploadQueue.then(function() {
                        statusEl.classList.remove('status-uploading');
            finishUpload();
                        if (result.success) {
        });
                            statusEl.classList.add('status-success');
    }
                            statusEl.textContent = '✅ 成功';
 
                        } else {
    function retryFailedFiles() {
                            statusEl.classList.add('status-error');
        if (isUploading || currentFailedFiles.length === 0) return;
                            statusEl.textContent = '❌ 失败';
        isUploading = true;
                        }
        $selectBtn.disabled = true;
                    }
        $clearBtn.disabled = true;
                 });
        $progress.style.display = 'block';
        $progressBar.style.width = '0%';
        uploadedCount = 0;
        totalCount = currentFailedFiles.length;
        updateStartButton();
 
        var toRetry = currentFailedFiles.slice();
        currentFailedFiles = [];
 
        var uploadQueue = Promise.resolve();
        toRetry.forEach(function(item) {
            uploadQueue = uploadQueue.then(function() {
                retryCounts[item.file._fileId] = 0;
                var statusEl = $list.querySelector('.file-status[data-index="' + item.index + '"]');
                if (statusEl) {
                    statusEl.classList.remove('status-error');
                    statusEl.classList.add('status-uploading');
                    statusEl.textContent = '重试中...';
                }
                 return uploadWithRetry(item.file, item.index);
             });
             });
         });
         });


         uploadQueue.then(function() {
         uploadQueue.then(function() {
             isUploading = false;
             finishUpload();
            $selectBtn.disabled = false;
        });
            $clearBtn.disabled = false;
    }
            updateStartButton();
 
            var successCount = $list.querySelectorAll('.status-success').length;
    function finishUpload() {
            var failCount = $list.querySelectorAll('.status-error').length;
        isUploading = false;
            var skipCount = $list.querySelectorAll('.status-skipped').length;
        $selectBtn.disabled = false;
            var msg = '上传完成!成功 ' + successCount + ' 张';
        $clearBtn.disabled = false;
            if (failCount > 0) msg += ',失败 ' + failCount + ' 张';
        updateStartButton();
            if (skipCount > 0) msg += ',跳过 ' + skipCount + ' 张';
 
            msg += '';
        var successCount = $list.querySelectorAll('.status-success').length;
            $summary.style.display = 'block';
        var failCount = $list.querySelectorAll('.status-error').length;
             $summary.innerHTML = msg;
        var skipCount = $list.querySelectorAll('.status-skipped').length;
 
        var msgParts = [];
        if (successCount > 0) msgParts.push('成功 ' + successCount + ' 张');
        if (failCount > 0) msgParts.push('失败 ' + failCount + ' 张');
        if (skipCount > 0) msgParts.push('跳过 ' + skipCount + ' 张');
 
        $summary.style.display = 'block';
        $summary.innerHTML = '上传完成!' + msgParts.join(',') + '';
 
        if (currentFailedFiles.length > 0) {
             $summary.innerHTML += ' <a href="javascript:void(0)" id="retry-link" style="color:#FF9800;font-weight:bold;">点击重试失败文件</a>';
        }
 
        if (currentFailedFiles.length === 0) {
             files = [];
             files = [];
             conflictResolved = false;
             conflictResolved = false;
             setTimeout(function() {
             setTimeout(function() {
                 if (files.length === 0 && !isUploading) {
                 if (files.length === 0 && !isUploading && currentFailedFiles.length === 0) {
                     renderList();
                     renderList();
                     $progress.style.display = 'none';
                     $progress.style.display = 'none';
                 }
                 }
             }, 5000);
             }, 5000);
         });
         }
 
        // 绑定重试链接
        var retryLink = document.getElementById('retry-link');
        if (retryLink) {
            retryLink.addEventListener('click', function() {
                retryFailedFiles();
            });
        }
     }
     }
})();
})();
</script>
</script>
</includeonly>
</includeonly>

2026年6月12日 (五) 12:25的最新版本