Files

145 lines
4.6 KiB
JavaScript
Raw Permalink Normal View History

2026-08-27 16:12:37 +08:00
// 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;
}
});