// background.js — Service Worker:推送队列 worker + 本地数据汇聚(双写) // 以 chrome.storage 为本地汇聚权威源(MV3 的 SW 会被休眠,内存变量不可靠); // 同时通过 alarms + IndexedDB 队列把数据推送到后端 ingest 端点。 import { addItem, getStats } from './push/queue.js'; import { processQueue } from './push/worker.js'; import { loadConfig, saveConfig } from './push/config.js'; // ===== 本地数据汇聚(保留,供插件本地导出)===== const BG_KEY = 'alibaba_bg_details'; async function loadMeta() { const data = await chrome.storage.local.get(BG_KEY); return data[BG_KEY] || { dedup: true, customerIdMap: {}, detailData: [] }; } async function saveMeta(meta) { await chrome.storage.local.set({ [BG_KEY]: meta }); } // ===== 推送配置 + alarms ===== const ALARM = 'push-tick'; async function refresh() { try { const cfg = await loadConfig(); if (cfg.enabled) { await chrome.alarms.create(ALARM, { periodInMinutes: 1 }); processQueue(); } else { await chrome.alarms.clear(ALARM); } } catch (e) { // 配置/alarms 失败不应阻断 SW 启动 console.error('[bg] refresh error:', e); } } chrome.runtime.onInstalled.addListener(refresh); chrome.runtime.onStartup.addListener(refresh); chrome.alarms.onAlarm.addListener(a => { if (a && a.name === ALARM) processQueue(); }); // ===== 消息处理 ===== chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { // --- 推送相关 --- if (msg.type === 'enqueue') { (async () => { try { const cfg = await loadConfig(); if (!cfg.enabled) { sendResponse({ ok: false, reason: 'disabled' }); return; } const inquiryId = msg.record && msg.record.inquiryId; const id = await addItem({ payload: { record: msg.record, messages: msg.messages || [] }, inquiryId, }); sendResponse({ ok: true, id }); processQueue(); } catch (e) { sendResponse({ ok: false, error: String((e && e.message) || e) }); } })(); return true; } if (msg.type === 'getPushStats') { (async () => { try { sendResponse({ ok: true, stats: await getStats() }); } catch (e) { sendResponse({ ok: false, error: String((e && e.message) || e) }); } })(); return true; } if (msg.type === 'getPushConfig') { (async () => { try { sendResponse({ ok: true, config: await loadConfig() }); } catch (e) { sendResponse({ ok: false, error: String((e && e.message) || e) }); } })(); return true; } if (msg.type === 'setPushConfig') { (async () => { try { await saveConfig(msg.config || {}); await refresh(); sendResponse({ ok: true }); } catch (e) { sendResponse({ ok: false, error: String((e && e.message) || e) }); } })(); return true; } // --- 本地数据汇聚(保留原逻辑,照搬) --- if (msg.type === 'storeDetail') { // 先读后写:SW 休眠唤醒后 DETAIL_STORE 会清空,必须从 storage 恢复再合并 (async () => { try { const meta = await loadMeta(); // 首条写入时锁定本次抓取的 dedup 策略 const isEmpty = Object.keys(meta.customerIdMap).length === 0 && meta.detailData.length === 0; if (isEmpty) meta.dedup = !!msg.dedup; if (meta.dedup && msg.customerId) { // 按 customerId 去重,保留 createTime 更新的那条 const existing = meta.customerIdMap[msg.customerId]; if (!existing || (msg.createTime || '') >= (existing.createTime || '')) { meta.customerIdMap[msg.customerId] = msg.record; } } else { // 无 customerId 或非去重模式:直接追加 meta.detailData.push(msg.record); } meta.lastUpdate = Date.now(); await saveMeta(meta); sendResponse({ ok: true }); } catch (e) { sendResponse({ ok: false, error: String(e && e.message || e) }); } })(); return true; // 保持消息通道,等待异步 sendResponse } if (msg.type === 'clearBgData') { (async () => { await chrome.storage.local.remove(BG_KEY); sendResponse({ ok: true }); })(); return true; } if (msg.type === 'getBgData') { (async () => { const meta = await loadMeta(); // 合并两份数据源,避免去重模式下无 customerId 的记录被丢弃 const records = meta.dedup ? [...Object.values(meta.customerIdMap), ...meta.detailData] : meta.detailData; sendResponse({ records, dedup: meta.dedup }); })(); return true; } });