186 lines
7.6 KiB
JavaScript
186 lines
7.6 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
||
// Elements
|
||
const clockEl = document.getElementById('real-time-clock');
|
||
const outputEl = document.getElementById('reportOutput');
|
||
const btnCopy = document.getElementById('btnCopy');
|
||
const btnBatchParse = document.getElementById('btnBatchParse');
|
||
const btnClearBatch = document.getElementById('btnClearBatch');
|
||
const batchInput = document.getElementById('batchInput');
|
||
const toastMessage = document.getElementById('toastMessage');
|
||
const toastEl = document.getElementById('liveToast');
|
||
const toast = new bootstrap.Toast(toastEl);
|
||
|
||
// Initialize Real-time Clock
|
||
const updateClock = () => {
|
||
const now = new Date();
|
||
const options = {
|
||
year: 'numeric', month: '2-digit', day: '2-digit',
|
||
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
||
hour12: false
|
||
};
|
||
const formatted = now.toLocaleString('zh-CN', options).replace(/\//g, '-');
|
||
if (clockEl) clockEl.textContent = formatted;
|
||
};
|
||
setInterval(updateClock, 1000);
|
||
updateClock();
|
||
|
||
// Show Toast Helper
|
||
const showToast = (msg, isError = false) => {
|
||
toastMessage.textContent = msg;
|
||
const iconContainer = toastMessage.previousElementSibling;
|
||
if (iconContainer) {
|
||
const icon = isError ? 'fa-circle-xmark text-danger' : 'fa-circle-check text-success';
|
||
iconContainer.className = `fa-solid ${icon} me-2`;
|
||
}
|
||
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)
|
||
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}
|
||
总招呼量: ${stats.totalGreeting}
|
||
总回复: ${stats.totalReply}
|
||
再聊: ${stats.rechat}
|
||
引流: ${stats.traffic}
|
||
语音: ${stats.voice}`;
|
||
};
|
||
|
||
// Robust Parsing Logic
|
||
const parseBatchData = () => {
|
||
const text = batchInput.value.trim();
|
||
if (!text) {
|
||
showToast('请先粘贴报表内容!', true);
|
||
return;
|
||
}
|
||
|
||
const totals = {
|
||
totalWS: 0, wsBanned: 0, wsPermBanned: 0, totalXHS: 0, totalSMS: 0,
|
||
xhs: 0, xhs_reply: 0, ws: 0, ws_reply: 0, sms: 0, sms_reply: 0,
|
||
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;
|
||
};
|
||
|
||
// Identify distinct reports by "总WS数量" delimiter
|
||
const reportChunks = text.split(/总WS数量/);
|
||
|
||
reportChunks.forEach((chunk, index) => {
|
||
if (!chunk.trim() && index === 0) return;
|
||
|
||
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);
|
||
}
|
||
|
||
// 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);
|
||
}
|
||
|
||
// 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);
|
||
}
|
||
|
||
// 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);
|
||
});
|
||
|
||
outputEl.textContent = formatReport(totals);
|
||
btnCopy.disabled = false;
|
||
showToast('报表汇总成功!');
|
||
};
|
||
|
||
// Events
|
||
if (btnBatchParse) {
|
||
btnBatchParse.addEventListener('click', () => {
|
||
showToast('深度解析中...');
|
||
setTimeout(parseBatchData, 400);
|
||
});
|
||
}
|
||
|
||
if (btnClearBatch) {
|
||
btnClearBatch.addEventListener('click', () => {
|
||
batchInput.value = '';
|
||
outputEl.textContent = '数据结果将在此处生成...';
|
||
btnCopy.disabled = true;
|
||
showToast('输入区域已清空');
|
||
});
|
||
}
|
||
|
||
if (btnCopy) {
|
||
btnCopy.addEventListener('click', () => {
|
||
const text = outputEl.textContent;
|
||
if (text && !text.includes('在此处生成')) {
|
||
navigator.clipboard.writeText(text).then(() => {
|
||
showToast('汇总报表已复制成功!');
|
||
}).catch(err => {
|
||
console.error('Copy failed', err);
|
||
showToast('复制失败', true);
|
||
});
|
||
} else {
|
||
showToast('无可复制内容', true);
|
||
}
|
||
});
|
||
}
|
||
}); |