const PLATFORM_META = Object.freeze({ xiaohongshu: { short: '红', className: 'platform-xiaohongshu' }, douyin: { short: '抖', className: 'platform-douyin' }, wechat_channels: { short: '视', className: 'platform-wechat_channels' }, bilibili: { short: 'B', className: 'platform-bilibili' }, xianyu: { short: '闲', className: 'platform-xianyu' } }) const STATUS_META = Object.freeze({ PENDING: { text: '等待扩展接收', className: '' }, OPENING: { text: '正在打开平台', className: 'is-running' }, LOGIN_REQUIRED: { text: '需要登录', className: 'is-login' }, DOWNLOADING: { text: '正在读取素材', className: 'is-running' }, UPLOADING: { text: '正在上传素材', className: 'is-running' }, FILLING: { text: '正在填写资料', className: 'is-running' }, READY_TO_PUBLISH: { text: '等待手动发布', className: 'is-ready' }, SUCCEEDED: { text: '发布成功', className: 'is-ready' }, FAILED: { text: '处理失败,可重试', className: 'is-failed' }, CANCELLED: { text: '页面已关闭,可重试', className: 'is-failed' } }) const taskList = document.getElementById('task-list') const emptyState = document.getElementById('empty-state') const notice = document.getElementById('notice') const template = document.getElementById('task-template') document.getElementById('version').textContent = 'v' + chrome.runtime.getManifest().version document.getElementById('refresh-list').addEventListener('click', loadTasks) chrome.storage.onChanged.addListener((changes, areaName) => { if (areaName !== 'local') return if (Object.keys(changes).some(key => key.startsWith('publisher_task_'))) loadTasks() }) async function loadTasks() { const response = await sendMessage({ type: 'SIDEPANEL_GET_TASKS' }) if (!response || !response.ok) { showNotice(response && response.message || '读取发布任务失败') return } renderTasks(response.tasks || []) } function renderTasks(tasks) { taskList.replaceChildren() emptyState.hidden = tasks.length > 0 for (const task of tasks) { const card = template.content.firstElementChild.cloneNode(true) const meta = PLATFORM_META[task.platform] || { short: '?', className: '' } const status = STATUS_META[task.status] || { text: task.status || '未知状态', className: '' } const icon = card.querySelector('.platform-icon') icon.textContent = meta.short icon.classList.add(meta.className) card.querySelector('.platform-name').textContent = task.platformName || task.platform card.querySelector('.task-title').textContent = task.title || '当前发布任务' const statusLine = card.querySelector('.status-line') statusLine.classList.add(status.className) statusLine.querySelector('span').textContent = task.statusMessage || status.text card.querySelector('.task-main').addEventListener('click', async () => { const response = await sendMessage({ type: 'SIDEPANEL_ACTIVATE_TASK', taskId: task.taskId }) if (!response || !response.ok) showNotice(response && response.message || '无法定位平台页面') }) const retryButton = card.querySelector('.retry-button') retryButton.disabled = !task.canRetry retryButton.title = task.canRetry ? '重新打开并重试' : '已发布成功,不能重复执行' retryButton.addEventListener('click', async () => { retryButton.disabled = true retryButton.classList.add('is-loading') const response = await sendMessage({ type: 'SIDEPANEL_RETRY_TASK', taskId: task.taskId }) retryButton.classList.remove('is-loading') if (!response || !response.ok) { retryButton.disabled = !task.canRetry showNotice(response && response.message || '重试失败') return } showNotice('已重新打开' + (task.platformName || task.platform) + '并开始填写', true) await loadTasks() }) taskList.appendChild(card) } } function showNotice(message, success = false) { notice.textContent = message notice.classList.toggle('is-success', success) notice.hidden = false window.setTimeout(() => { notice.hidden = true }, 4000) } function sendMessage(message) { return new Promise(resolve => { chrome.runtime.sendMessage(message, response => { if (chrome.runtime.lastError) { resolve({ ok: false, message: chrome.runtime.lastError.message }) return } resolve(response) }) }) } loadTasks()