// ==UserScript== // @name 图片样本上传 // @namespace http://tampermonkey.net/ // @version 2.9.5 // @description 图片上传工具(完整修复版) // @author Hanabi // @match *://*/* // @grant GM_xmlhttpRequest // @grant GM_log // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function () { 'use strict'; // ===== 核心配置 ===== const SWITCH_KEY = 'blackSampleScriptSwitch'; const CONFIG_KEY = 'blackSampleSampleUploadConfig'; // ===== 上传队列 全局变量 ===== let uploadQueue = []; let uploadPanel = null; let uploadedFiles = new Set(); let lastFileUploadTime = 0; const UPLOAD_DEBOUNCE_INTERVAL = 3000; // ===== 核心:页面校验函数 ===== function isTargetPage() { return window.location.href.includes('library/list?breadcrumb') || window.location.href.includes('library/detail') || window.location.hash.includes('library/list?breadcrumb') || window.location.hash.includes('library/detail'); } console.log('黑样本上传脚本已加载,当前页面检测:', isTargetPage() ? '目标页面' : '非目标页面'); // ===== 开关状态管理 ===== function getSwitchState() { const state = GM_getValue(SWITCH_KEY, true); console.log('当前脚本开关状态:', state ? '开启' : '关闭'); return state; } function setSwitchState(state) { GM_setValue(SWITCH_KEY, state); console.log('脚本开关已切换为:', state ? '开启' : '关闭'); updateSwitchUI(state); } // ===== 默认配置 ===== const DEFAULT_CONFIG = { tag: '', contentSource: '', dangerLevel: '', selectedBusinesses: [], remark: '', autoClickBtn: false }; const OPTIONS = { tags: ['' ], contentSources: ['舆情事件', '日常总结', '平台要求'], dangerLevels: ['一般', '低危', '中危', '高危'], businesses: ['视频', '视频封面', '直播封面', '图文', '直播'] }; let currentConfig = GM_getValue(CONFIG_KEY, DEFAULT_CONFIG); if (currentConfig.excludedBusinesses && !currentConfig.selectedBusinesses) { currentConfig.selectedBusinesses = OPTIONS.businesses.filter(biz => !currentConfig.excludedBusinesses.includes(biz) ); delete currentConfig.excludedBusinesses; GM_setValue(CONFIG_KEY, currentConfig); } let configPanel = null; let controlPanelCreated = false; let observer = null; function saveConfig(config) { currentConfig = { ...currentConfig, ...config }; GM_setValue(CONFIG_KEY, currentConfig); console.log('配置已保存:', currentConfig); } // ===== 创建控制面板 ===== function createControlPanel() { if (controlPanelCreated || document.getElementById('blackSampleControlPanel')) return; const controlPanel = document.createElement('div'); controlPanel.id = 'blackSampleControlPanel'; controlPanel.style.cssText = ` display: flex; align-items: center; gap: 12px; padding: 0 16px; height: 100%; margin-left: auto; font-family: Helvetica Neue, Helvetica, PingFang SC, Microsoft YaHei, sans-serif; `; const switchText = document.createElement('span'); switchText.id = 'blackSampleSwitchText'; switchText.style.cssText = ` font-size: 14px; font-weight: 500; color: #303133; white-space: nowrap; `; switchText.textContent = getSwitchState() ? '已开启' : '已关闭'; const switchBtn = document.createElement('div'); switchBtn.id = 'blackSampleSwitchBtn'; switchBtn.style.cssText = ` width: 40px; height: 20px; border-radius: 10px; background: ${getSwitchState() ? '#409EFF' : '#C0C4CC'}; position: relative; cursor: pointer; transition: all 0.3s ease; `; const switchSlider = document.createElement('div'); switchSlider.style.cssText = ` width: 16px; height: 16px; border-radius: 50%; background: #fff; position: absolute; top: 2px; left: ${getSwitchState() ? '22px' : '2px'}; transition: left 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2); `; switchBtn.appendChild(switchSlider); const configBtn = document.createElement('button'); configBtn.id = 'blackSampleConfigBtn'; configBtn.textContent = '配置'; configBtn.style.cssText = ` padding: 6px 12px; background: #409EFF; color: #fff; border: none; border-radius: 4px; font-size: 14px; font-weight: 500; cursor: pointer; transition: background 0.2s ease; `; configBtn.addEventListener('mouseover', () => configBtn.style.background = '#66B1FF'); configBtn.addEventListener('mouseout', () => configBtn.style.background = '#409EFF'); const uploadBtn = document.createElement('button'); uploadBtn.textContent = '图片队列'; uploadBtn.style.cssText = ` padding: 6px 12px; background: #1890ff; color: #fff; border: none; border-radius: 4px; font-size: 14px; font-weight: 500; cursor: pointer; transition: background 0.2s ease; `; uploadBtn.addEventListener('mouseover', () => uploadBtn.style.background = '#40a9ff'); uploadBtn.addEventListener('mouseout', () => uploadBtn.style.background = '#1890ff'); uploadBtn.addEventListener('click', toggleUploadPanel); controlPanel.appendChild(switchText); controlPanel.appendChild(switchBtn); controlPanel.appendChild(configBtn); controlPanel.appendChild(uploadBtn); const topbar = document.querySelector('.library-topbar'); if (topbar) { topbar.appendChild(controlPanel); controlPanelCreated = true; } switchBtn.addEventListener('click', () => { const currentState = getSwitchState(); setSwitchState(!currentState); }); configBtn.addEventListener('click', () => { if (!configPanel) createConfigPanel(); configPanel.style.display = configPanel.style.display === 'none' ? 'block' : 'none'; }); } function updateSwitchUI(state) { const switchText = document.getElementById('blackSampleSwitchText'); const switchBtn = document.getElementById('blackSampleSwitchBtn'); const switchSlider = switchBtn?.querySelector('div'); if (switchText) switchText.textContent = state ? '已开启' : '已关闭'; if (switchBtn) switchBtn.style.background = state ? '#409EFF' : '#C0C4CC'; if (switchSlider) switchSlider.style.left = state ? '22px' : '2px'; } // ===== 创建全局配置面板 ===== function createConfigPanel() { if (configPanel) return; configPanel = document.createElement('div'); configPanel.id = 'blackSampleConfigPanel'; configPanel.style.cssText = ` position: fixed; top: 70px; right: 20px; width: 350px; background: #fff; border: 1px solid #E4E7ED; border-radius: 4px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); z-index: 999999; font-family: Helvetica Neue, Helvetica, PingFang SC, Microsoft YaHei, sans-serif; overflow: hidden; display: block; `; const header = document.createElement('div'); header.style.cssText = ` padding: 15px 20px; background: #F5F7FA; color: #303133; font-weight: 500; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #E4E7ED; `; header.innerHTML = ` 图片默认配置 `; configPanel.appendChild(header); const content = document.createElement('div'); content.style.cssText = `padding: 20px;`; content.innerHTML += `
${OPTIONS.businesses.map(business => ` `).join('')}
`; const saveBtn = document.createElement('button'); saveBtn.id = 'saveConfigBtn'; saveBtn.textContent = '保存配置'; saveBtn.style.cssText = ` width: 100%; padding: 10px; background: #409EFF; color: #fff; border: none; border-radius: 4px; font-weight: 500; cursor: pointer; transition: background 0.2s; font-size:14px; `; saveBtn.addEventListener('mouseover', () => saveBtn.style.background = '#66B1FF'); saveBtn.addEventListener('mouseout', () => saveBtn.style.background = '#409EFF'); content.appendChild(saveBtn); configPanel.appendChild(content); document.body.appendChild(configPanel); document.getElementById('closeConfigBtn').addEventListener('click', () => { configPanel.style.display = 'none'; }); document.getElementById('closeConfigBtn').addEventListener('mouseover', function(){ this.style.color = '#F56C6C'; }); document.getElementById('closeConfigBtn').addEventListener('mouseout', function(){ this.style.color = '#909399'; }); document.getElementById('saveConfigBtn').addEventListener('click', () => { const tag = document.getElementById('tagInput').value; const remark = document.getElementById('remarkInput').value; const contentSource = document.getElementById('sourceSelect').value; const dangerLevel = document.getElementById('dangerLevelSelect').value; const autoClickBtn = document.getElementById('autoClickBtn').checked; const selectedBusinesses = Array.from( document.querySelectorAll('#businessCheckboxes input[type="checkbox"]:checked') ).map(checkbox => checkbox.value); saveConfig({ tag, remark, contentSource, dangerLevel, selectedBusinesses, autoClickBtn }); const saveSuccess = document.createElement('div'); saveSuccess.textContent = '配置已保存!'; saveSuccess.style.cssText = ` position: fixed;top: 40px;right: 40px;padding: 10px 15px;background: #67C23A;color: #fff;border-radius: 4px;font-weight: 500;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);z-index: 999999;transition: all 0.3s;font-size:14px; `; document.body.appendChild(saveSuccess); setTimeout(() => { saveSuccess.style.opacity = '0'; setTimeout(() => document.body.removeChild(saveSuccess), 300); }, 3000); configPanel.style.display = 'none'; }); } // ===== 初始化/销毁 ===== function initPage() { console.log('初始化目标页面:创建控制面板 + 启动弹窗监听'); createControlPanel(); if (observer) observer.disconnect(); startObserver(); } function destroyPage() { console.log('离开目标页面:移除控制面板 + 停止弹窗监听'); const controlPanel = document.getElementById('blackSampleControlPanel'); if (controlPanel) controlPanel.remove(); if (configPanel) { configPanel.remove(); configPanel = null; } if(uploadPanel){ uploadPanel.remove(); uploadPanel = null; } controlPanelCreated = false; if (observer) { observer.disconnect(); observer = null; } } // ===== URL监听 ===== function setupUrlChangeListener() { window.addEventListener('hashchange', checkPageStatus); const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function(...args) { originalPushState.apply(this, args); checkPageStatus(); }; history.replaceState = function(...args) { originalReplaceState.apply(this, args); checkPageStatus(); }; checkPageStatus(); } function checkPageStatus() { console.log('检查页面状态,当前URL:', window.location.href); isTargetPage() ? initPage() : destroyPage(); } // ===== 弹窗监听 ===== function startObserver() { let automationState = { isExecuting: false, lastDialogId: null, dialogCount: 0 }; observer = new MutationObserver(() => { if (!getSwitchState()) return; const overlayElements = document.querySelectorAll('.aegis-v3-el-overlay'); const visibleOverlay = Array.from(overlayElements).find(el => window.getComputedStyle(el).display !== 'none' ); if (visibleOverlay) { const dialogContainer = visibleOverlay.nextElementSibling?.closest('.aegis-v3-el-dialog') || document.querySelector('.aegis-v3-el-dialog:not([style*="display: none"])'); if (dialogContainer) { if (!dialogContainer.dataset.dialogId) { automationState.dialogCount++; dialogContainer.dataset.dialogId = `dialog-${automationState.dialogCount}`; } const currentDialogId = dialogContainer.dataset.dialogId; if (!automationState.isExecuting && currentDialogId !== automationState.lastDialogId) { automationState.isExecuting = true; automationState.lastDialogId = currentDialogId; startAutomation(automationState); } } } else if (automationState.isExecuting) { automationState.isExecuting = false; } }); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style'], characterData: true }); } async function startAutomation(automationState) { if (!getSwitchState()) { automationState.isExecuting = false; return; } try { await fillForm(); } catch (error) { console.error('自动化过程出错:', error); } finally { setTimeout(() => { automationState.isExecuting = false; }, 2000); } } async function fillForm(uploadConfig = currentConfig) { if (!getSwitchState()) return; console.log('使用配置:', uploadConfig); await sleep(300); const tagInput = document.querySelector('.aegis-v3-el-select__input'); if (tagInput) { tagInput.value = uploadConfig.tag; triggerEvent(tagInput, 'input'); triggerEvent(tagInput, 'change'); await sleep(100); const dropdownList = document.querySelector('.aegis-v3-el-select-dropdown.is-multiple .aegis-v3-el-select-dropdown__list'); if (dropdownList) { const firstItem = dropdownList.querySelector('.aegis-v3-el-select-dropdown__item'); if (firstItem) firstItem.click(); } } const remarkInput = document.querySelector('input.aegis-v3-el-input__inner[placeholder="该内容的应对处理方案"]'); if (remarkInput) { remarkInput.value = uploadConfig.remark; triggerEvent(remarkInput, 'input'); triggerEvent(remarkInput, 'change'); } await sleep(200); const businessCheckboxes = document.querySelectorAll('.aegis-v3-el-checkbox'); businessCheckboxes.forEach(checkbox => { const label = checkbox.querySelector('.aegis-v3-el-checkbox__label'); if (label && OPTIONS.businesses.some(biz => label.textContent.includes(biz))) { if (checkbox.classList.contains('is-checked')) checkbox.click(); } }); await sleep(100); businessCheckboxes.forEach(checkbox => { const label = checkbox.querySelector('.aegis-v3-el-checkbox__label'); if (label && uploadConfig.selectedBusinesses.some(biz => label.textContent.includes(biz))) { if (!checkbox.classList.contains('is-checked')) checkbox.click(); } }); await sleep(200); const violationCheckboxes = document.querySelectorAll('.aegis-v3-el-checkbox'); violationCheckboxes.forEach(checkbox => { const label = checkbox.querySelector('.aegis-v3-el-checkbox__label'); if (label && label.textContent.includes('文字违规') && checkbox.classList.contains('is-checked')) { checkbox.click(); } }); await sleep(200); const sourceSelect = document.querySelector('input[placeholder="选择来源"]'); if (sourceSelect) { sourceSelect.click(); await sleep(100); const dropdowns = document.querySelectorAll('.aegis-v3-el-select-dropdown:not([style*="display: none"])'); if (dropdowns.length > 0) { const visibleDropdown = dropdowns[dropdowns.length - 1]; const allOptions = Array.from(visibleDropdown.querySelectorAll('.aegis-v3-el-select-dropdown__item')); const sourceOption = allOptions.find(item => item.textContent.trim().includes(uploadConfig.contentSource)); if (sourceOption) sourceOption.click(); } } await sleep(200); const dangerInputs = document.querySelectorAll('input[placeholder="危险程度"]'); if (dangerInputs.length > 1) { const dangerSelect = dangerInputs[1]; if (dangerSelect) { dangerSelect.click(); await sleep(100); const dropdowns = document.querySelectorAll('.aegis-v3-el-select-dropdown:not([style*="display: none"])'); if (dropdowns.length > 0) { const visibleDropdown = dropdowns[dropdowns.length - 2]; const allOptions = Array.from(visibleDropdown.querySelectorAll('.aegis-v3-el-select-dropdown__item')); const dangerOption = allOptions.find(item => item.textContent.trim().includes(uploadConfig.dangerLevel)); if (dangerOption) dangerOption.click(); } } } const successNotification = document.createElement('div'); successNotification.textContent = '配置已自动应用!'; successNotification.style.cssText = ` position: fixed;top: 40px;right: 40px;padding: 10px 15px;background: #67C23A;color: #fff;border-radius: 4px;font-weight: 500;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);z-index: 999999;transition: all 0.3s;font-size: 14px; `; document.body.appendChild(successNotification) setTimeout(() => { successNotification.style.opacity = '0'; setTimeout(() => document.body.removeChild(successNotification), 300); }, 3000); if (getSwitchState()) { const timer = setInterval(() => { const avatarWrapper = document.querySelector('.avatar-wrapper'); if (!avatarWrapper) return; const img = avatarWrapper.querySelector('img'); if (!img || !img.src) return; clearInterval(timer); if (uploadConfig.autoClickBtn) { const buttons = document.querySelectorAll('.aegis-v3-el-button.aegis-v3-el-button--primary'); if (buttons.length > 0) buttons[buttons.length - 1].click(); setTimeout(() => { const newButtons = document.querySelectorAll('.aegis-v3-el-button.aegis-v3-el-button--primary'); if (newButtons.length > 0) newButtons[newButtons.length - 1].click(); }, 750); } else { const btns = document.querySelectorAll('.aegis-v3-el-button.aegis-v3-el-button--primary'); const clickHandler = () => { setTimeout(() => { const newButtons = document.querySelectorAll('.aegis-v3-el-button.aegis-v3-el-button--primary'); if (newButtons.length > 0) newButtons[newButtons.length - 1].click(); }, 750); btns.forEach(b => b.removeEventListener('click', clickHandler)); }; btns.forEach(b => b.addEventListener('click', clickHandler)); } }, 500); setTimeout(() => clearInterval(timer), 10000); } } function triggerEvent(element, eventType) { const event = new Event(eventType, { bubbles: true }); element.dispatchEvent(event); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function waitForOverlayHidden() { const maxWaitTime = 15000; const startTime = Date.now(); return new Promise(resolve => { const timer = setInterval(() => { const list = document.querySelectorAll('.aegis-v3-el-overlay-dialog'); let allHide = true; list.forEach(el => { if (getComputedStyle(el).display !== 'none') allHide = false; }) if (allHide || Date.now() - startTime > maxWaitTime) { clearInterval(timer); resolve(); } }, 200); }); } function toggleUploadPanel() { if (!uploadPanel) createUploadPanel(); uploadPanel.style.display = uploadPanel.style.display === 'none' ? 'block' : 'none'; } // 创建上传队列面板(完整修复) function createUploadPanel() { if (uploadPanel) return; uploadPanel = document.createElement('div'); uploadPanel.id = 'uploadQueuePanel_FINAL'; uploadPanel.style.cssText = ` position: fixed; top: 70px; right: 20px; width: 460px; background: #fff; border-radius: 4px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); z-index: 9999999; font-family: Helvetica Neue, Helvetica, PingFang SC, Microsoft YaHei, sans-serif; border: 1px solid #E4E7ED; overflow: hidden; display: none; `; const header = document.createElement('div'); header.style.cssText = 'padding:12px 15px;background:#F5F7FA;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #E4E7ED;'; header.innerHTML = ` 批量上传队列
`; const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.accept = 'image/*'; fileInput.multiple = true; fileInput.style.display = 'none'; fileInput.id = 'fileInput_FINAL'; const queueContainer = document.createElement('div'); queueContainer.id = 'queueContainer_FINAL'; queueContainer.style.cssText = 'max-height:400px;overflow-y:auto;padding:10px;'; uploadPanel.append(header, fileInput, queueContainer); document.body.appendChild(uploadPanel); document.getElementById('closePanelBtn_FINAL').onclick = () => { uploadPanel.style.display = 'none'; }; document.getElementById('selectFilesBtn_FINAL').onclick = () => { document.getElementById('fileInput_FINAL').click(); }; document.getElementById('fileInput_FINAL').onchange = handleFileSelect; document.getElementById('clearAllBtn_FINAL').onclick = () => { uploadQueue.forEach(file => file.previewURL && URL.revokeObjectURL(file.previewURL)); uploadQueue = []; uploadedFiles.clear(); renderQueue(); showToast('已清空所有图片', '#67C23A'); }; } function handleFileSelect(e) { const files = Array.from(e.target.files); if (!files.length) return; files.forEach(file => { file.customConfig = {...currentConfig}; }); uploadQueue = [...uploadQueue, ...files]; renderQueue(); e.target.value = ''; } function deleteFile(fileName) { const fileToDelete = uploadQueue.find(file => file.name === fileName); if (fileToDelete) URL.revokeObjectURL(fileToDelete.previewURL); uploadQueue = uploadQueue.filter(file => file.name !== fileName); uploadedFiles.delete(fileName); renderQueue(); } // 自定义上拉菜单 class CustomPullUpSelect { constructor(container, options, selectedValue, onChange) { this.container = container; this.options = options; this.selectedValue = selectedValue; this.onChange = onChange; this.isOpen = false; this.init(); } init() { this.selectContainer = document.createElement('div'); this.selectContainer.className = 'custom-pullup-select'; this.selectContainer.style.cssText = ` position: relative; width: 100%; box-sizing: border-box; `; this.trigger = document.createElement('div'); this.trigger.className = 'custom-select-trigger'; this.trigger.style.cssText = ` width: 100%; padding: 2px 4px; border: 1px solid #ddd; border-radius: 2px; background: white; cursor: pointer; display: flex; justify-content: space-between; align-items: center; font-size: 12px; `; this.trigger.textContent = this.getSelectedText(); this.trigger.innerHTML += ''; this.menu = document.createElement('div'); this.menu.className = 'custom-select-menu'; this.menu.style.cssText = ` position: absolute; bottom: 100%; left: 0; right: 0; max-height: 150px; overflow-y: auto; background: white; border: 1px solid #ddd; border-radius: 2px; box-shadow: 0 -2px 5px rgba(0,0,0,0.1); z-index: 9999; display: none; margin-bottom: 2px; `; this.options.forEach(option => { const item = document.createElement('div'); item.className = 'custom-select-item'; item.style.cssText = ` padding: 4px 6px; cursor: pointer; font-size: 12px; `; item.textContent = option; item.dataset.value = option; if (option === this.selectedValue) { item.style.backgroundColor = '#e8f4ff'; } item.addEventListener('click', () => this.selectItem(item)); this.menu.appendChild(item); }); this.selectContainer.appendChild(this.trigger); this.selectContainer.appendChild(this.menu); this.container.appendChild(this.selectContainer); this.trigger.addEventListener('click', () => this.toggleMenu()); document.addEventListener('click', (e) => this.handleClickOutside(e)); } getSelectedText() { return this.selectedValue || this.options[0] || '请选择'; } toggleMenu() { this.isOpen = !this.isOpen; this.menu.style.display = this.isOpen ? 'block' : 'none'; this.trigger.querySelector('span').textContent = this.isOpen ? '▼' : '▲'; } selectItem(item) { this.selectedValue = item.dataset.value; this.trigger.firstChild.textContent = this.selectedValue; this.menu.querySelectorAll('.custom-select-item').forEach(el => { el.style.backgroundColor = ''; }); item.style.backgroundColor = '#e8f4ff'; this.toggleMenu(); this.onChange(this.selectedValue); } handleClickOutside(e) { if (!this.selectContainer.contains(e.target)) { this.isOpen = false; this.menu.style.display = 'none'; this.trigger.querySelector('span').textContent = '▲'; } } } // 渲染队列 function renderQueue() { const container = document.getElementById('queueContainer_FINAL'); if (!container) return; container.innerHTML = ''; if (uploadQueue.length === 0) { container.innerHTML = '
暂无上传文件
'; return; } uploadQueue.forEach((file, index) => { const isUploaded = uploadedFiles.has(file.name); const config = file.customConfig || currentConfig; const row = document.createElement('div'); row.style.cssText = ` border-bottom:1px solid #E4E7ED; ${isUploaded ? 'background:#F0F9FF;' : ''} `; const mainRow = document.createElement('div'); mainRow.style.cssText = `display:flex;align-items:center;gap:10px;padding:8px;`; const triggerArea = document.createElement('div'); triggerArea.style.cssText = "display:flex;align-items:center;gap:10px;flex:1;"; if (!file.previewURL) file.previewURL = URL.createObjectURL(file); const img = document.createElement('img'); img.src = file.previewURL; img.style.cssText = 'width:40px;height:40px;object-fit:cover;border-radius:4px;'; const info = document.createElement('div'); info.style.cssText = 'flex:1;overflow:hidden;'; // 文件名修复:省略号+悬停气泡 info.innerHTML = `
${file.name}
${formatFileSize(file.size)}
标签:${config.tag||'无'} | 危险:${config.dangerLevel||'无'} | 业务:${config.selectedBusinesses.join('、')||'全部'}
`; triggerArea.append(img, info); const actionArea = document.createElement('div'); actionArea.style.cssText = "display:flex;gap:6px;"; const uploadBtn = document.createElement('button'); uploadBtn.textContent = isUploaded ? '已上传(可重传)' : '上传'; uploadBtn.style.cssText = `padding:4px 8px;${isUploaded ? 'background:#909399;' : 'background:#67C23A;'}color:white;border:none;border-radius:4px;cursor:pointer;font-size:12px;`; uploadBtn.onclick = () => { uploadBtn.disabled = true; uploadBtn.style.background = '#C0C4CC'; uploadBtn.style.cursor = 'not-allowed'; startSingleUpload(file, uploadBtn); }; const delBtn = document.createElement('button'); delBtn.textContent = '删除'; delBtn.style.cssText = 'padding:4px 8px;background:#F56C6C;color:white;border:none;border-radius:4px;cursor:pointer;font-size:12px;'; delBtn.onclick = () => deleteFile(file.name); actionArea.append(uploadBtn, delBtn); mainRow.append(triggerArea, actionArea); const accordionPanel = document.createElement('div'); accordionPanel.style.cssText = ` max-height:0;overflow:hidden;transition:max-height 0.3s ease;padding:0 10px; border-top:1px dashed #E4E7ED;background:#fafafa; `; const formContainer = document.createElement('div'); formContainer.style.cssText = `padding:8px 0;display:grid;grid-template-columns:1fr 1fr;gap:8px;font-size:12px;`; const tagGroup = document.createElement('div'); tagGroup.innerHTML = ` `; const remarkGroup = document.createElement('div'); remarkGroup.innerHTML = ` `; const sourceGroup = document.createElement('div'); sourceGroup.innerHTML = ``; const sourceSelectContainer = document.createElement('div'); sourceGroup.appendChild(sourceSelectContainer); const dangerGroup = document.createElement('div'); dangerGroup.innerHTML = ``; const dangerSelectContainer = document.createElement('div'); dangerGroup.appendChild(dangerSelectContainer); const businessGroup = document.createElement('div'); businessGroup.style.gridColumn = 'span 2'; businessGroup.innerHTML = `
${OPTIONS.businesses.map(b => ` `).join('')}
`; formContainer.append(tagGroup, remarkGroup, sourceGroup, dangerGroup, businessGroup); accordionPanel.appendChild(formContainer); row.append(mainRow, accordionPanel); container.appendChild(row); triggerArea.addEventListener('mouseenter', () => { accordionPanel.style.maxHeight = '200px'; }); triggerArea.addEventListener('mouseleave', () => { setTimeout(() => { if (!accordionPanel.matches(':hover')) { accordionPanel.style.maxHeight = '0'; } }, 100); }); accordionPanel.addEventListener('mouseenter', () => { accordionPanel.style.maxHeight = '200px'; }); accordionPanel.addEventListener('mouseleave', () => { accordionPanel.style.maxHeight = '0'; }); new CustomPullUpSelect( sourceSelectContainer, OPTIONS.contentSources, config.contentSource, (value) => { file.customConfig.contentSource = value; } ); new CustomPullUpSelect( dangerSelectContainer, OPTIONS.dangerLevels, config.dangerLevel, (value) => { file.customConfig.dangerLevel = value; } ); bindRowConfigEvents(index); }); } function bindRowConfigEvents(index) { const file = uploadQueue[index]; if (!file) return; document.querySelector(`.row-tag[data-index="${index}"]`).addEventListener('change', function(){ file.customConfig.tag = this.value; renderQueue(); }); document.querySelector(`.row-remark[data-index="${index}"]`).addEventListener('change', function(){ file.customConfig.remark = this.value; }); document.querySelectorAll(`.row-biz[data-index="${index}"]`).forEach(checkbox => { checkbox.addEventListener('change', function(){ const allChecked = Array.from(document.querySelectorAll(`.row-biz[data-index="${index}"]:checked`)).map(i=>i.value); file.customConfig.selectedBusinesses = allChecked; }); }); } function formatFileSize(bytes) { if (bytes < 1024) return bytes + ' B'; if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'; return (bytes / 1048576).toFixed(1) + ' MB'; } async function startSingleUpload(file, btn) { if (!getSwitchState()) { showToast('脚本已关闭,无法上传', '#F56C6C'); restoreUploadBtn(btn, file); return; } try { const btns = document.querySelectorAll('.aegis-v3-el-button.aegis-v3-el-button--primary'); if (btns.length >= 2) btns[1].click(); await sleep(300); const now = Date.now(); if (now - lastFileUploadTime < UPLOAD_DEBOUNCE_INTERVAL) { const remainSeconds = Math.ceil((UPLOAD_DEBOUNCE_INTERVAL - (now - lastFileUploadTime)) / 1000); showToast(`操作频繁,请等待${remainSeconds}秒后再上传`, '#F56C6C'); return; } const fileInput = document.querySelector('input[name="file"]'); if (!fileInput) { showToast('未找到上传输入框', '#F56C6C'); return; } lastFileUploadTime = now; const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; fileInput.dispatchEvent(new Event('change', { bubbles: true })); fileInput.dispatchEvent(new Event('input', { bubbles: true })); await fillForm(file.customConfig); uploadedFiles.add(file.name); renderQueue(); console.log(`上传成功:${file.name}`); } catch (err) { showToast(`上传失败:${err.message}`, '#F56C6C'); console.error(err); } finally { await waitForOverlayHidden(); restoreUploadBtn(btn, file); } } function restoreUploadBtn(btn, file) { if (!btn) return; const isUploaded = uploadedFiles.has(file.name); btn.disabled = false; btn.style.cursor = 'pointer'; btn.textContent = isUploaded ? '已上传(可重传)' : '上传'; btn.style.background = isUploaded ? '#909399' : '#67C23A'; } function showToast(msg, bg) { const div = document.createElement('div'); div.style.cssText = `position:fixed;top:100px;right:40px;padding:8px 15px;background:${bg};color:white;border-radius:4px;z-index:999999;transition:opacity 0.3s;font-size:14px;`; div.textContent = msg; document.body.appendChild(div); setTimeout(() => { div.style.opacity = '0'; setTimeout(() => div.remove(), 300); }, 2000); } // ===== 初始化 ===== setupUrlChangeListener(); })();