למה אין נתונים לקווים? 🤔
-
@קו-המוסיקה נראה לי שלא אבל אני לא יודע
-
@BEN-ZION
בטעות תייגתי אותך
@קו-המוסיקהיצרתי לך קובץ html לניתוח הנתונים.
אשמח שתיתן עליו הערות והארות לשידרוג<!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <title>ניתוח נתוני מערכות | v23</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> :root { --bg: #0f172a; --card: #1e293b; --primary: #38bdf8; --accent: #22c55e; --text: #f1f5f9; --border: #334155; --danger: #ef4444; --warning: #f59e0b; } body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; flex-direction: column; height: 100vh; } header { background: #1e293b; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); } .logo-box { display: flex; align-items: center; gap: 12px; } .logo-icon { background: linear-gradient(135deg, var(--primary), #0ea5e9); color: #0f172a; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; box-shadow: 0 0 15px rgba(56, 189, 248, 0.4); } .logo-text { font-size: 1.4rem; font-weight: 800; color: var(--text); letter-spacing: -0.5px; } .config-box { display: flex; gap: 12px; align-items: center; } input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); cursor: pointer; } input, select { background: #0f172a; border: 1px solid var(--border); color: white; padding: 10px; border-radius: 8px; outline: none; transition: 0.2s; } .btn-run { background: var(--primary); color: #0f172a; border: none; padding: 10px 25px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s; } .nav-tabs { background: #1e293b; display: flex; padding: 0 20px; border-bottom: 1px solid var(--border); } .tab { padding: 15px 25px; cursor: pointer; color: #94a3b8; border-bottom: 3px solid transparent; transition: 0.3s; font-weight: 500; } .tab.active { color: var(--primary); border-bottom-color: var(--primary); background: rgba(56, 189, 248, 0.07); } .main-content { flex: 1; padding: 25px; overflow-y: auto; background: #0f172a; } .card { background: var(--card); padding: 25px; border-radius: 16px; border: 1px solid var(--border); margin-bottom: 25px; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); } .stat-num { font-size: 2.5rem; font-weight: 800; color: var(--primary); } .control-bar { display: flex; gap: 20px; align-items: center; background: #334155; padding: 15px 25px; border-radius: 12px 12px 0 0; border: 1px solid var(--border); border-bottom: none; } .search-input { background: #0f172a; border: 1px solid var(--border); color: white; padding: 8px 15px; border-radius: 8px; width: 250px; outline: none; } table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 0 0 12px 12px; overflow: hidden; border: 1px solid var(--border); } th { text-align: right; padding: 15px; background: #475569; color: white; font-weight: 600; font-size: 0.85rem; } td { padding: 15px; border-bottom: 1px solid var(--border); font-size: 0.95rem; } tr:hover { background: rgba(255,255,255,0.02); } .bar-container { width: 100px; background: #0f172a; height: 10px; border-radius: 10px; display: inline-block; overflow: hidden; vertical-align: middle; border: 1px solid var(--border); margin-left: 8px; } .bar-fill { height: 100%; background: var(--accent); border-radius: 10px; } #debug-console { background: #000; color: #22c55e; font-family: 'Courier New', monospace; padding: 20px; height: 350px; overflow-y: auto; border-radius: 12px; border: 1px solid #22c55e; line-height: 1.6; } .progress-container { width: 100%; background: #1e293b; height: 6px; display: none; } #progress-fill { height: 100%; background: var(--primary); width: 0%; transition: 0.4s; box-shadow: 0 0 10px var(--primary); } .live-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; font-weight: bold; padding: 4px 10px; border-radius: 20px; background: #334155; } .dot { width: 8px; height: 8px; border-radius: 50%; background: #666; } .dot.active { background: var(--accent); box-shadow: 0 0 8px var(--accent); animation: pulse 2s infinite; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } } .hidden { display: none; } </style> </head> <body> <header> <div class="logo-box"> <div class="logo-icon"><i class="fas fa-chart-bar"></i></div> <div class="logo-text">ניתוח נתוני מערכות</div> <div class="live-status"><div id="live-dot" class="dot"></div> <span id="live-text">OFFLINE</span></div> </div> <div class="config-box"> <input type="password" id="apiToken" placeholder="טוקן API"> <input type="date" id="startDate"> <input type="date" id="endDate"> <button class="btn-run" onclick="manualStart()">הפעל ניתוח</button> </div> </header> <div class="progress-container" id="progBar"><div id="progress-fill"></div></div> <div class="nav-tabs"> <div class="tab active" onclick="switchTab(event, 'dash-tab')"><i class="fas fa-th-large"></i> דאשבורד</div> <div class="tab" onclick="switchTab(event, 'ext-tab')"><i class="fas fa-folder-tree"></i> שלוחות</div> <div class="tab" onclick="switchTab(event, 'play-tab')"><i class="fas fa-play-circle"></i> השמעות</div> <div class="tab" onclick="switchTab(event, 'users-tab')"><i class="fas fa-users"></i> מאזינים</div> <div class="tab" style="color: var(--warning)" onclick="switchTab(event, 'debug-tab')"><i class="fas fa-terminal"></i> לוג</div> </div> <div class="main-content"> <div id="dash-tab" class="tab-content"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin-bottom: 25px;"> <div class="card"><span style="color: #94a3b8">מאזינים ייחודיים</span><br><span id="stat-users" class="stat-num">0</span></div> <div class="card"><span style="color: #94a3b8">סה"כ דקות האזנה</span><br><span id="stat-min" class="stat-num">0</span></div> <div class="card"><span style="color: #94a3b8">שיחות שהושלמו</span><br><span id="stat-comp" class="stat-num">0</span></div> </div> <div class="card"><h3>גרף פעילות יומי</h3><canvas id="dailyChart" height="100"></canvas></div> </div> <div id="ext-tab" class="tab-content hidden"> <div class="control-bar"> <label>מיון:</label> <select id="extSort" onchange="renderExts()"><option value="count">כמות כניסות</option><option value="sec">זמן שהייה</option></select> <input type="text" id="extSearch" class="search-input" placeholder="חפש שלוחה..." onkeyup="renderExts()"> </div> <table id="extTable"><thead><tr><th>שם השלוחה</th><th>כניסות</th><th>דקות שהייה</th><th>ממוצע לשהייה</th></tr></thead><tbody></tbody></table> </div> <div id="play-tab" class="tab-content hidden"> <div class="control-bar"> <label>מיון:</label> <select id="playSort" onchange="renderPlays()"><option value="count">פופולריות</option><option value="pct">אחוז השלמה</option></select> <input type="text" id="playSearch" class="search-input" placeholder="חפש קובץ / שלוחה..." onkeyup="renderPlays()"> </div> <table id="playTable"><thead><tr><th>שם קובץ / שלוחה</th><th>השמעות</th><th>סה"כ דקות</th><th>אחוז השלמה ממוצע</th><th>שיעור נטישה</th></tr></thead><tbody></tbody></table> </div> <div id="users-tab" class="tab-content hidden"> <div class="control-bar"> <label>מיון:</label> <select id="userSort" onchange="renderUsers()"><option value="sec">זמן האזנה כולל</option><option value="calls">מספר שיחות גבוה</option></select> <input type="text" id="userSearch" class="search-input" placeholder="חפש טלפון..." onkeyup="renderUsers()"> </div> <table id="usersTable"><thead><tr><th>מספר טלפון</th><th>דקות האזנה</th><th>מספר שיחות</th><th>סטטוס</th></tr></thead><tbody></tbody></table> </div> <div id="debug-tab" class="tab-content hidden"><div class="card"><div id="debug-console"></div></div></div> </div> <script> const API = "https://www.call2all.co.il/ym/api/"; let dataStore = { exts: {}, plays: {}, users: {}, daily: {}, totalSec: 0, completed: 0 }; let dailyChart = null; let autoRefreshTimer = null; function addLog(msg, color = '#22c55e') { const console = document.getElementById('debug-console'); const div = document.createElement('div'); div.style.color = color; div.innerHTML = `<span style="color:#555">[${new Date().toLocaleTimeString()}]</span> ${msg}`; console.appendChild(div); console.scrollTop = console.scrollHeight; } function cleanExt(val) { if (!val) return "ראשית"; let s = val.toString().trim().replace(/^\ufeff/, ""); if (s === "" || s === "/" || s === "." || s.toLowerCase() === "root" || s.toLowerCase() === "main") return "ראשית"; return s; } function parseSec(t) { if (!t) return 0; if (t.toString().includes(':')) { const p = t.split(':').map(Number); return p.length === 3 ? (p[0]*3600)+(p[1]*60)+p[2] : (p[0]*60)+p[1]; } return parseInt(t) || 0; } async function manualStart() { if(autoRefreshTimer) clearInterval(autoRefreshTimer); await startFullAnalysis(); document.getElementById('live-dot').classList.add('active'); document.getElementById('live-text').innerText = "LIVE (עדכון כל דקה)"; autoRefreshTimer = setInterval(startFullAnalysis, 60000); } async function startFullAnalysis() { const token = document.getElementById('apiToken').value; const start = document.getElementById('startDate').value; const end = document.getElementById('endDate').value; if (!token) return alert("הזן טוקן API"); addLog("מרענן נתונים...", "#38bdf8"); dataStore = { exts: {}, plays: {}, users: {}, daily: {}, totalSec: 0, completed: 0 }; document.getElementById('progBar').style.display = 'block'; const month = start.substring(0, 7); try { const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogFolderEnterExit-${month}.ymgr&convertType=json`); const json = await res.json(); if (json.data) { json.data.forEach(row => { const ext = cleanExt(row["שלוחה"]); const sec = parseSec(row["זמן כולל בשלוחה"]); if (!dataStore.exts[ext]) dataStore.exts[ext] = { count: 0, sec: 0 }; dataStore.exts[ext].count++; dataStore.exts[ext].sec += sec; }); } } catch(e) { addLog("שגיאה בטעינת שלוחות", "red"); } let dates = []; for(let d=new Date(start); d<=new Date(end); d.setDate(d.getDate()+1)) dates.push(new Date(d).toISOString().split('T')[0]); for (let day of dates) { updateProgress(dates.indexOf(day)+1, dates.length); try { const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${day}.ymgr&convertType=json`); const json = await res.json(); if (json.data) { if (!dataStore.daily[day]) dataStore.daily[day] = 0; json.data.forEach(row => { const file = row["השמעה"] || "לא ידוע"; const phone = row["טלפון"] || "חסוי"; const sec = parseInt(row["סה\"כ שניות"]) || 0; const len = parseSec(row["אורך הקובץ"]); const isEnd = row["נקודת יציאה"] === "סוף"; dataStore.daily[day]++; dataStore.totalSec += sec; if (isEnd) dataStore.completed++; if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, calls: 0 }; dataStore.users[phone].sec += sec; dataStore.users[phone].calls++; if (!dataStore.plays[file]) dataStore.plays[file] = { count: 0, sec: 0, drops: 0, pcts: [] }; dataStore.plays[file].count++; dataStore.plays[file].sec += sec; dataStore.plays[file].pcts.push(len > 0 ? Math.min(100, Math.round((sec/len)*100)) : 0); if (!isEnd) dataStore.plays[file].drops++; }); } } catch(e) {} } renderUI(); } function renderUI() { document.getElementById('progBar').style.display = 'none'; document.getElementById('stat-users').innerText = Object.keys(dataStore.users).length.toLocaleString(); document.getElementById('stat-min').innerText = Math.floor(dataStore.totalSec / 60).toLocaleString(); document.getElementById('stat-comp').innerText = dataStore.completed.toLocaleString(); renderExts(); renderPlays(); renderUsers(); updateChart(); } function renderExts() { const sort = document.getElementById('extSort').value; const q = document.getElementById('extSearch').value.toLowerCase(); let items = Object.entries(dataStore.exts).map(([name, d]) => ({name, ...d})) .filter(i => i.name.toLowerCase().includes(q)); items.sort((a,b) => b[sort] - a[sort]); document.querySelector('#extTable tbody').innerHTML = items.map(i => ` <tr><td style="color:var(--primary); font-weight:600">${i.name}</td><td>${i.count.toLocaleString()}</td><td>${(i.sec/60).toFixed(1)}</td><td>${i.count ? Math.round(i.sec/i.count) : 0} ש'</td></tr> `).join(''); } function renderPlays() { const sort = document.getElementById('playSort').value; const q = document.getElementById('playSearch').value.toLowerCase(); let items = Object.entries(dataStore.plays).map(([name, d]) => { const avg = d.pcts.length ? Math.round(d.pcts.reduce((a,b)=>a+b,0)/d.pcts.length) : 0; const dropRate = Math.round((d.drops/d.count)*100); return {name, avg, dropRate, ...d}; }).filter(i => i.name.toLowerCase().includes(q)); items.sort((a,b) => sort === 'count' ? b.count - a.count : b.avg - a.avg); document.querySelector('#playTable tbody').innerHTML = items.map(i => ` <tr><td>${i.name}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td> <td><div class="bar-container"><div class="bar-fill" style="width:${i.avg}%"></div></div> <b>${i.avg}%</b></td> <td style="color:${i.dropRate > 50 ? 'var(--danger)' : 'var(--accent)'}; font-weight:bold">${i.dropRate}%</td></tr> `).join(''); } function renderUsers() { const sortKey = document.getElementById('userSort').value; const q = document.getElementById('userSearch').value; let items = Object.entries(dataStore.users).map(([phone, d]) => ({phone, ...d})) .filter(i => i.phone.includes(q)); items.sort((a,b) => b[sortKey] - a[sortKey]); document.querySelector('#usersTable tbody').innerHTML = items.map((i, idx) => ` <tr><td style="font-weight:bold">${i.phone}</td><td style="color:var(--primary); font-weight:bold">${(i.sec/60).toFixed(1)}</td><td>${i.calls}</td><td>${idx < 3 ? '🏆 מוביל' : 'מאזין'}</td></tr> `).join(''); } function updateChart() { if (dailyChart) dailyChart.destroy(); const ctx = document.getElementById('dailyChart').getContext('2d'); dailyChart = new Chart(ctx, { type: 'line', data: { labels: Object.keys(dataStore.daily), datasets: [{ label: 'שיחות', data: Object.values(dataStore.daily), borderColor: '#38bdf8', tension: 0.4, fill: true, backgroundColor: 'rgba(56, 189, 248, 0.1)' }] }, options: { plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true } } } }); } function updateProgress(c, t) { document.getElementById('progress-fill').style.width = (c/t*100) + '%'; } function switchTab(e, id) { document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden')); document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); document.getElementById(id).classList.remove('hidden'); e.currentTarget.classList.add('active'); } document.getElementById('startDate').value = document.getElementById('endDate').value = new Date().toISOString().split('T')[0]; </script> </body> </html> -
@אA
אין שום נתונים, או שהבעיה אצלי ששמרתי את הזה ששומר את הlog ב ivr...

-
@קו-המוסיקה לא אמורה להיות בעיה בהגדרת השלוחה ב-
ivr.ini -
-
@קו-המוסיקה
זה מוגדר שלוקח את הנתונים מהקבצים שבתקיית הלוג.
אצלי זה עבד מצויין.
וההגדרה עצמה לא קשרוה לקבצי הלוג. -
פוסט זה נמחק! -
@lavitoren-הטי-ל
מאיפה הבאת את זה? -
@אA ארגון מסוים אני עובד שם נראה לי שזה של שניאור אבל הוא לא אמר לא לפרסם או שזה פרטי ואגב אתה זריז
אבל מאוד(??)
-
@lavitoren-הטי-ל
תודה על המחמאה, אבל מה זה ה? בסוף?
בכל מקרה בדיוק הייתי על השירשור וכתבתי תגובה... -
@אA @lavitoren-הטי-ל
לא יודע מה בדיוק פיספסתי,
אבל אממ... יש למשהו הסבר למה זה לא עובד לי עכשיו,
אולי זה לא צבר מספיק נתונים יש כזה דבר?
כי אני מנסה לחשוב על משהו שיכול להיות בעיייתי ולא מוצא... -
@קו-המוסיקה
יש קבצי לוג בתקיית הלוג?
הכנסת מספר מערכת:סיסמא תקינים? -
@אA וואלה אתה אלוף!!!!
זה ממשק מאוד יפה ומטורף! -
@אA כתב בלמה אין נתונים לקווים?
:אשמח שתיתן עליו הערות והארות לשידרוג
אני יכול גם לתת הארות?
הייתי אומר היה עדיף אם היה אפשר ללחוץ על מאזין ולראות את שעות השיחה שלו וכמה זמן וכו'...
תודה רבה. -
-
@מוטי-מוטי-מוטי
בטח, אני אשמח לכל הערה הארה.
משתמשים יחודיים הכוונה שגם אם משתמש חייג 20 פעמים הוא יחשב כמאזין אחד ושם הוא רושם את כל המאזינים שחייגו ולא את מספר השיחות שנכנסו.
ההגדרה היא של הבינה, אני תכננתי להחליף... -
@מוטי-מוטי-מוטי
סתם מעניין, לך זה עובד? -
@אA אהה... אוקיי.
ויש לך מושג אילו הגדרות לשים בקובץ IVR כדי שישמר לי כל לוג אפשרי?
מה שיכול להיות ממנו לוג
אני מדבר בכללי אתה יודע... לא לוג הקלטות... -
@אA כתב בלמה אין נתונים לקווים?
:סתם מעניין, לך זה עובד?

עובד!!!!!!!!!
הכי אהבתי את הגרף פעילות יומי,
זה נותן לי לראות מה היה באותו היום. -
@מוטי-מוטי-מוטי
אלו סוגי לוגים אתה רוצה?
אלו שרלוונטים לקובץ הזה, או בלי קשר?!