From f33d58af446a33ff59b6cfab5af64d790af7acaa Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 24 Feb 2026 14:51:35 +0000 Subject: [PATCH] =?UTF-8?q?=E6=8A=A5=E8=A1=A82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/js/main.js | 161 +++++++++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 79 deletions(-) diff --git a/assets/js/main.js b/assets/js/main.js index 1103734..259ed5f 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -35,34 +35,16 @@ document.addEventListener('DOMContentLoaded', () => { toast.show(); }; - // Global button click feedback - document.querySelectorAll('button').forEach(btn => { - btn.addEventListener('click', (e) => { - if (btn.id === 'btnBatchParse' || btn.id === 'btnClearBatch' || btn.id === 'btnCopy') return; - - if (btn.classList.contains('carousel-control-prev') || btn.classList.contains('carousel-control-next')) { - showToast('切换轮播图'); - } else if (btn.hasAttribute('data-bs-slide-to')) { - showToast('切换到幻灯片 ' + (parseInt(btn.getAttribute('data-bs-slide-to')) + 1)); - } else if (!btn.classList.contains('btn-close')) { - showToast('功能已触达'); - } - }); - }); - - // Helper to format the final report (Exact format requested) + // Helper to format the final report const formatReport = (stats) => { return `总WS数量: ${stats.totalWS} WS今日封号: ${stats.wsBanned} 总永封WS: ${stats.wsPermBanned} 总XHS数量: ${stats.totalXHS} 总SMS数量: ${stats.totalSMS} -XHS: ${stats.xhs} -回复: ${stats.xhs_reply} -WS: ${stats.ws} -回复: ${stats.ws_reply} -SMS: ${stats.sms} -回复: ${stats.sms_reply} +XHS: ${stats.xhs} 回复: ${stats.xhs_reply} +WS: ${stats.ws} 回复: ${stats.ws_reply} +SMS: ${stats.sms} 回复: ${stats.sms_reply} 总招呼量: ${stats.totalGreeting} 总回复: ${stats.totalReply} 再聊: ${stats.rechat} @@ -70,7 +52,7 @@ SMS: ${stats.sms} 语音: ${stats.voice}`; }; - // Robust Parsing Logic + // Improved Extraction Logic const parseBatchData = () => { const text = batchInput.value.trim(); if (!text) { @@ -84,68 +66,90 @@ SMS: ${stats.sms} totalGreeting: 0, totalReply: 0, rechat: 0, traffic: 0, voice: 0 }; - // Helper to extract a single value from a chunk - const extractVal = (pattern, content) => { - const match = content.match(pattern); - return match ? parseInt(match[1], 10) : 0; + const extractVal = (patterns, content) => { + if (!Array.isArray(patterns)) patterns = [patterns]; + for (const p of patterns) { + const match = content.match(p); + if (match) { + const cleanVal = match[1].replace(/,/g, ''); + return parseInt(cleanVal, 10) || 0; + } + } + return 0; }; - // Identify distinct reports by "总WS数量" delimiter - const reportChunks = text.split(/总WS数量/); - - reportChunks.forEach((chunk, index) => { - if (!chunk.trim() && index === 0) return; + const extractPlatformStats = (platformLabel, content) => { + // Priority: specifically look for "Platform招呼量" + // Second: look for "Platform" if not part of "总...数量" or "...封号" + const regex = new RegExp('(总)?' + platformLabel + '(数量|今日封号|招呼量)?[^0-9]*([0-9,]+)', 'gi'); + let bestMatch = null; + let m; - const fullChunk = (index === 0 && !text.startsWith('总WS数量')) ? chunk : '总WS数量' + chunk; - - // Basic fields - totals.totalWS += extractVal(/总WS数量[::\s]+(\d+)/, fullChunk); - totals.wsBanned += extractVal(/WS今日封号[::\s]+(\d+)/, fullChunk); - totals.wsPermBanned += extractVal(/总永封WS[::\s]+(\d+)/, fullChunk); - totals.totalXHS += extractVal(/总XHS数量[::\s]+(\d+)/, fullChunk); - totals.totalSMS += extractVal(/总SMS数量[::\s]+(\d+)/, fullChunk); - - // XHS & Reply (Targeted extraction) - const xhsMatch = fullChunk.match(/XHS招呼量[::\s]+(\d+)[\s\S]*?回复[::\s]+(\d+)/); - if (xhsMatch) { - totals.xhs += parseInt(xhsMatch[1], 10); - totals.xhs_reply += parseInt(xhsMatch[2], 10); - } else { - totals.xhs += extractVal(/XHS(?:招呼量)?[::\s]+(\d+)/, fullChunk); - const genericXhsReply = fullChunk.match(/XHS[\s\S]*?回复[::\s]+(\d+)/); - if (genericXhsReply) totals.xhs_reply += parseInt(genericXhsReply[1], 10); + while ((m = regex.exec(content)) !== null) { + const isTotal = !!m[1]; + const suffix = m[2] || ''; + const isMeta = suffix === '数量' || suffix === '今日封号'; + + // We want the one that is NOT "总WS数量" and NOT "WS今日封号" + // Ideally it's "WS招呼量" or just "WS" + if (!isTotal && !isMeta) { + bestMatch = m; + if (suffix === '招呼量') break; // Best possible match found + } } - // WS & Reply - const wsMatch = fullChunk.match(/WS招呼量[::\s]+(\d+)[\s\S]*?回复[::\s]+(\d+)/); - if (wsMatch) { - totals.ws += parseInt(wsMatch[1], 10); - totals.ws_reply += parseInt(wsMatch[2], 10); - } else { - totals.ws += extractVal(/WS(?:招呼量)?[::\s]+(\d+)/, fullChunk); - const genericWsReply = fullChunk.match(/WS[\s\S]*?回复[::\s]+(\d+)/); - if (genericWsReply) totals.ws_reply += parseInt(genericWsReply[1], 10); - } + if (!bestMatch) return { count: 0, reply: 0 }; + + const count = parseInt(bestMatch[3].replace(/,/g, ''), 10) || 0; + const afterMatch = content.substring(bestMatch.index + bestMatch[0].length); + + // Look for "回复" after this count, but stop at next major label + const stopLabel = /(XHS|WS|SMS|总招呼量|总回复|再聊|引流|语音|总WS数量|WS今日封号|总永封WS|总XHS数量|总SMS数量)/i.exec(afterMatch); + const searchRange = afterMatch.substring(0, stopLabel ? stopLabel.index : 100); + const rMatch = searchRange.match(/回复[^0-9]*([0-9,]+)/); + + return { + count: count, + reply: rMatch ? (parseInt(rMatch[1].replace(/,/g, ''), 10) || 0) : 0 + }; + }; - // SMS & Reply - const smsMatch = fullChunk.match(/SMS招呼量[::\s]+(\d+)[\s\S]*?回复[::\s]+(\d+)/); - if (smsMatch) { - totals.sms += parseInt(smsMatch[1], 10); - totals.sms_reply += parseInt(smsMatch[2], 10); - } else { - totals.sms += extractVal(/SMS(?:招呼量)?[::\s]+(\d+)/, fullChunk); - const genericSmsReply = fullChunk.match(/SMS[\s\S]*?回复[::\s]+(\d+)/); - if (genericSmsReply) totals.sms_reply += parseInt(genericSmsReply[1], 10); - } + // Split by "总WS数量" + const reportChunks = text.split(/(?=总WS数量)/); + + reportChunks.forEach((chunk) => { + if (!chunk.trim()) return; - // Bottom fields - totals.totalGreeting += extractVal(/总招呼量[::\s]+(\d+)/, fullChunk); - totals.totalReply += extractVal(/总回复[::\s]+(\d+)/, fullChunk); - totals.rechat += extractVal(/再聊[::\s]+(\d+)/, fullChunk); - totals.traffic += extractVal(/引流[::\s]+(\d+)/, fullChunk); - totals.voice += extractVal(/语音[::\s]+(\d+)/, fullChunk); + // Global Metrics + totals.totalWS += extractVal([/总WS数量[::\s]*([0-9,]+)/, /WS数量[::\s]*([0-9,]+)/], chunk); + totals.wsBanned += extractVal([/WS今日封号[::\s]*([0-9,]+)/, /今日封号[::\s]*([0-9,]+)/], chunk); + totals.wsPermBanned += extractVal([/总永封WS[::\s]*([0-9,]+)/, /永封WS[::\s]*([0-9,]+)/], chunk); + totals.totalXHS += extractVal([/总XHS数量[::\s]*([0-9,]+)/, /XHS数量[::\s]*([0-9,]+)/], chunk); + totals.totalSMS += extractVal([/总SMS数量[::\s]*([0-9,]+)/, /SMS数量[::\s]*([0-9,]+)/], chunk); + + // Platform Specifics + const xData = extractPlatformStats('XHS', chunk); + totals.xhs += xData.count; + totals.xhs_reply += xData.reply; + + const wData = extractPlatformStats('WS', chunk); + totals.ws += wData.count; + totals.ws_reply += wData.reply; + + const sData = extractPlatformStats('SMS', chunk); + totals.sms += sData.count; + totals.sms_reply += sData.reply; + + // Bottom Metrics + totals.rechat += extractVal(/再聊[::\s]*([0-9,]+)/, chunk); + totals.traffic += extractVal(/引流[::\s]*([0-9,]+)/, chunk); + totals.voice += extractVal(/语音[::\s]*([0-9,]+)/, chunk); }); + // Calculate Totals by Summing individual platform stats (More accurate than relying on member input) + totals.totalGreeting = totals.xhs + totals.ws + totals.sms; + totals.totalReply = totals.xhs_reply + totals.ws_reply + totals.sms_reply; + outputEl.textContent = formatReport(totals); btnCopy.disabled = false; showToast('报表汇总成功!'); @@ -154,7 +158,7 @@ SMS: ${stats.sms} // Events if (btnBatchParse) { btnBatchParse.addEventListener('click', () => { - showToast('深度解析中...'); + showToast('解析中...'); setTimeout(parseBatchData, 400); }); } @@ -173,9 +177,8 @@ SMS: ${stats.sms} const text = outputEl.textContent; if (text && !text.includes('在此处生成')) { navigator.clipboard.writeText(text).then(() => { - showToast('汇总报表已复制成功!'); + showToast('已复制成功!'); }).catch(err => { - console.error('Copy failed', err); showToast('复制失败', true); }); } else {