Files
order_site/apps/extensions/pdd-cookie-sync/popup.js
T
yml2213 9fb27b0ad2 feat(pdd): 拼多多订单支持 out_sku_sn 匹配与浏览器插件加密保活
- 拼多多进单 Cookie 失效即时拦截与告警修复(支持 43001 会话过期等错误识别)
- 拼多多订单映射优先使用 out_sku_sn(外部商家编码)作为商品规格与工单匹配核心字段
- 新增 Chrome/Edge 浏览器扩展 (Manifest V3),支持端到端 RSA-OAEP + AES-256-GCM 信封加密自动保活
- 后台店铺管理新增插件配对面板、专属密钥管理与一键导入配置 JSON
2026-09-14 12:24:48 +08:00

182 lines
5.9 KiB
JavaScript

/**
* Pinduoduo Cookie Sync Extension Popup Script
*/
document.addEventListener('DOMContentLoaded', async () => {
const statusBadge = document.getElementById('statusBadge')
const mmsStatus = document.getElementById('mmsStatus')
const shopDisplay = document.getElementById('shopDisplay')
const lastSyncDisplay = document.getElementById('lastSyncDisplay')
const orderCountRow = document.getElementById('orderCountRow')
const orderCountDisplay = document.getElementById('orderCountDisplay')
const statusMsg = document.getElementById('statusMsg')
const btnSyncNow = document.getElementById('btnSyncNow')
const btnSaveConfig = document.getElementById('btnSaveConfig')
const btnToggleImport = document.getElementById('btnToggleImport')
const btnApplyImport = document.getElementById('btnApplyImport')
const importArea = document.getElementById('importArea')
const importJsonInput = document.getElementById('importJsonInput')
const inputServerUrl = document.getElementById('inputServerUrl')
const inputShopId = document.getElementById('inputShopId')
const inputSyncToken = document.getElementById('inputSyncToken')
function formatTime(timestamp) {
if (!timestamp) return '未同步'
const d = new Date(timestamp)
if (isNaN(d.getTime())) return '未同步'
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const h = String(d.getHours()).padStart(2, '0')
const min = String(d.getMinutes()).padStart(2, '0')
const s = String(d.getSeconds()).padStart(2, '0')
return `${m}-${day} ${h}:${min}:${s}`
}
function showMsg(text, isError = false) {
statusMsg.style.display = 'block'
statusMsg.className = isError ? 'msg-box msg-error' : 'msg-box msg-success'
statusMsg.textContent = text
}
function refreshStatusView(statusData) {
const storage = statusData?.storage || {}
const hasCookie = Boolean(statusData?.hasCookie)
// 1. MMS 登录状态
if (hasCookie) {
mmsStatus.textContent = `已在线 (长度: ${statusData.cookieLength || 0})`
mmsStatus.style.color = '#15803d'
} else {
mmsStatus.textContent = '未登录 / 无有效Cookie'
mmsStatus.style.color = '#b91c1c'
}
// 2. 店铺标识
if (storage.shopId) {
shopDisplay.textContent = storage.shopId
} else {
shopDisplay.textContent = '未配置'
}
// 3. 上次同步
if (storage.lastSyncAt) {
lastSyncDisplay.textContent = formatTime(storage.lastSyncAt)
} else {
lastSyncDisplay.textContent = '从未同步'
}
// 4. 订单数
if (storage.totalOrders !== undefined) {
orderCountRow.style.display = 'flex'
orderCountDisplay.textContent = `${storage.totalOrders} 笔`
} else {
orderCountRow.style.display = 'none'
}
// 5. 顶部角标与错误消息
if (!storage.serverUrl || !storage.shopId || !storage.syncToken) {
statusBadge.className = 'badge badge-gray'
statusBadge.textContent = '待配对'
} else if (storage.lastStatus === 'ok') {
statusBadge.className = 'badge badge-ok'
statusBadge.textContent = '运行正常'
if (storage.lastMessage) {
showMsg(storage.lastMessage, false)
}
} else if (storage.lastStatus === 'error') {
statusBadge.className = 'badge badge-err'
statusBadge.textContent = '同步异常'
if (storage.lastMessage) {
showMsg(storage.lastMessage, true)
}
} else {
statusBadge.className = 'badge badge-gray'
statusBadge.textContent = '待同步'
}
// 填充输入框
inputServerUrl.value = storage.serverUrl || ''
inputShopId.value = storage.shopId || ''
inputSyncToken.value = storage.syncToken || ''
}
// 初始化加载
chrome.runtime.sendMessage({ action: 'get_status' }, (res) => {
refreshStatusView(res)
})
// 切换一键导入框
btnToggleImport.addEventListener('click', (e) => {
e.preventDefault()
if (importArea.style.display === 'none') {
importArea.style.display = 'block'
importJsonInput.focus()
} else {
importArea.style.display = 'none'
}
})
// 执行一键导入解析
btnApplyImport.addEventListener('click', () => {
const raw = importJsonInput.value.trim()
if (!raw) return
try {
const parsed = JSON.parse(raw)
if (parsed.serverUrl) inputServerUrl.value = parsed.serverUrl
if (parsed.shopId) inputShopId.value = parsed.shopId
if (parsed.syncToken) inputSyncToken.value = parsed.syncToken
importArea.style.display = 'none'
showMsg('配置解析成功,请点击下方【保存配置】生效', false)
} catch {
showMsg('JSON 格式不正确,请确保完整复制后台内容', true)
}
})
// 保存配置
btnSaveConfig.addEventListener('click', async () => {
const serverUrl = inputServerUrl.value.trim()
const shopId = inputShopId.value.trim()
const syncToken = inputSyncToken.value.trim()
if (!serverUrl || !shopId || !syncToken) {
showMsg('请完整填写服务器地址、店铺标识和配对密钥', true)
return
}
await chrome.storage.local.set({
serverUrl,
shopId,
syncToken,
})
showMsg('配置已保存!正在尝试初次加密同步...', false)
triggerSync()
})
// 手动触发同步
function triggerSync() {
btnSyncNow.disabled = true
btnSyncNow.textContent = '正在加密上传...'
chrome.runtime.sendMessage({ action: 'trigger_sync' }, (res) => {
btnSyncNow.disabled = false
btnSyncNow.textContent = '立即上传同步 Cookie'
if (res && res.success) {
showMsg(res.message || '同步成功!', false)
} else {
showMsg(res?.message || '同步失败,请检查网络或配置', true)
}
// 刷新界面
chrome.runtime.sendMessage({ action: 'get_status' }, (s) => {
refreshStatusView(s)
})
})
}
btnSyncNow.addEventListener('click', triggerSync)
})