您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
百度智能体数据统计分析浮窗,悬停名称可显示折线图
// ==UserScript== // @name 智能体分析 // @namespace com.baidu.agent // @version 2.2 // @description 百度智能体数据统计分析浮窗,悬停名称可显示折线图 // @author qwn // @icon https://www.google.com/s2/favicons?domain=baidu.com // @match https://agents.baidu.com/* // @grant GM_xmlhttpRequest // @require https://cdn.jsdelivr.net/npm/[email protected] // @license MIT // ==/UserScript== (function() { 'use strict'; // 初始化函数:等待 DOM 和 Chart.js 加载完成 function init() { if (typeof Chart === 'undefined') { console.error('Chart.js 未加载,请检查网络或 CDN 地址'); setTimeout(init, 100); return; } // API 地址定义 const API_LIST = 'https://agents.baidu.com/lingjing/agent/list?agentSource=1&agentType=1&pageNo=1&pageSize=50'; const API_OVERVIEW = appId => `https://agents.baidu.com/lingjing/agent/statistics/overview?appId=${appId}`; const API_PROFIT = (start, end) => `https://agents.baidu.com/lingjing/agent/profit/summary/trend/distribution?startTime=${start}&endTime=${end}`; const API_STATS = (appId, start, end) => `https://agents.baidu.com/lingjing/agent/statistics/all?appId=${appId}&startTime=${start}&endTime=${end}`; // 全局变量 let wrapper = null; let isVisible = false; const statsCache = new Map(); // 缓存 API_STATS 数据 // 创建浮动按钮 const floatBtn = document.createElement('div'); floatBtn.innerText = '☺'; Object.assign(floatBtn.style, { position: 'fixed', bottom: '30px', right: '30px', width: '50px', height: '50px', borderRadius: '50%', backgroundColor: '#1a6dbf', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', lineHeight: '50px', fontSize: '40px', fontWeight: 'bold', zIndex: '10000', cursor: 'pointer', boxShadow: '0 4px 8px rgba(0,0,0,0.2)', paddingBottom: '5px', transition: 'transform 0.2s ease' }); floatBtn.onmouseover = () => floatBtn.style.transform = 'scale(1.1)'; floatBtn.onmouseout = () => floatBtn.style.transform = 'scale(1)'; document.body.appendChild(floatBtn); // 浮动按钮点击事件 floatBtn.onclick = () => { if (isVisible) { wrapper.style.display = 'none'; isVisible = false; } else { if (!wrapper) { wrapper = createWrapper(); renderProfitTrend(wrapper); renderAgentStats(wrapper); } else { wrapper.style.display = 'block'; } isVisible = true; } }; // 点击外部关闭窗口 document.addEventListener('click', e => { if (wrapper && isVisible && !wrapper.contains(e.target) && e.target !== floatBtn) { wrapper.style.display = 'none'; } }); // 创建统计窗口 function createWrapper() { const el = document.createElement('div'); Object.assign(el.style, { position: 'fixed', bottom: '100px', right: '30px', maxHeight: '80vh', maxWidth: '95vw', overflow: 'auto', background: '#fff', borderRadius: '12px', boxShadow: '0 4px 20px rgba(0,0,0,0.2)', padding: '20px', zIndex: '9999', fontFamily: 'Arial, sans-serif' }); document.body.appendChild(el); return el; } // 工具函数:创建带链接的名称单元格并绑定悬浮事件 function createNameCell(appId, name) { const td = document.createElement('td'); const link = document.createElement('a'); link.textContent = name; link.href = `https://agents.baidu.com/agent/prompt/edit?appId=${appId}&activeTab=analysis`; link.target = '_blank'; link.style.cursor = 'pointer'; link.style.textDecoration = 'underline'; link.style.color = '#1a6dbf'; td.appendChild(link); let tooltip = null; let isTooltipVisible = false; const showTooltip = (e) => { if (!isTooltipVisible) { isTooltipVisible = true; tooltip = createTooltip(appId, name, td); // 传递 td 作为参数 document.body.appendChild(tooltip); tooltip.style.display = 'block'; positionTooltip(tooltip, td); console.log(`Showing tooltip for appId: ${appId}`); // 调试日志 } }; const hideTooltip = () => { if (isTooltipVisible) { isTooltipVisible = false; if (tooltip) { tooltip.style.display = 'none'; if (tooltip.chartInstance) { tooltip.chartInstance.destroy(); tooltip.chartInstance = null; } tooltip.remove(); tooltip = null; console.log(`Hiding tooltip for appId: ${appId}`); // 调试日志 } } }; td.addEventListener('mouseenter', showTooltip); td.addEventListener('mouseleave', (e) => { const relatedTarget = e.relatedTarget; if (tooltip && relatedTarget && tooltip.contains(relatedTarget)) { return; } setTimeout(() => { if (tooltip && !tooltip.matches(':hover') && !td.matches(':hover')) { hideTooltip(); } }, 100); }); return td; } // 创建工具提示(含图表) function createTooltip(appId, agentName, td) { let tooltip = document.createElement('div'); Object.assign(tooltip.style, { position: 'absolute', background: '#fff', borderRadius: '8px', boxShadow: '0 2px 10px rgba(0,0,0,0.2)', padding: '12px', zIndex: '10001', display: 'none', width: '460px', maxWidth: '90vw', fontSize: '13px', lineHeight: '1.4' }); const idDiv = document.createElement('div'); idDiv.textContent = `${agentName}-${appId}`; idDiv.style.marginBottom = '10px'; idDiv.style.fontWeight = 'bold'; const canvas = document.createElement('canvas'); canvas.width = 380; canvas.height = 240; canvas.style.width = '380px'; canvas.style.height = '240px'; canvas.style.display = 'block'; tooltip.appendChild(idDiv); tooltip.appendChild(canvas); const cachedData = statsCache.get(appId); if (!cachedData) { const errorDiv = document.createElement('div'); errorDiv.textContent = '暂无数据可显示'; errorDiv.style.fontSize = '15px'; tooltip.appendChild(errorDiv); } else { const { labels, rounds, distributePv } = cachedData; try { const chart = new Chart(canvas, { type: 'line', data: { labels, datasets: [{ label: '对话', data: rounds, borderColor: '#ff6b6b', yAxisID: 'y1', fill: false, tension: 0.2 }, { label: '曝光', data: distributePv, borderColor: '#1a6dbf', yAxisID: 'y2', fill: false, tension: 0.2 }] }, options: { responsive: false, maintainAspectRatio: false, scales: { y1: { min: 0, type: 'linear', position: 'left', title: { display: false, text: '对话' } }, y2: { min: 0, type: 'linear', position: 'right', title: { display: false, text: '曝光' }, grid: { drawOnChartArea: false } } }, plugins: { title: { display: false, text: `${agentName} 数据趋势` }, legend: { position: 'bottom' } } } }); tooltip.chartInstance = chart; } catch (e) { console.error('Chart initialization failed for appId:', appId, e); const errorDiv = document.createElement('div'); errorDiv.textContent = '图表渲染失败'; tooltip.appendChild(errorDiv); } } // 为 tooltip 添加 mouseleave 事件 tooltip.addEventListener('mouseleave', (e) => { const relatedTarget = e.relatedTarget; if (relatedTarget && td.contains(relatedTarget)) { return; // 如果鼠标移回 td,不隐藏 } setTimeout(() => { if (tooltip && !tooltip.matches(':hover') && !td.matches(':hover')) { const hideTooltip = () => { if (tooltip) { tooltip.style.display = 'none'; if (tooltip.chartInstance) { tooltip.chartInstance.destroy(); tooltip.chartInstance = null; } tooltip.remove(); tooltip = null; console.log(`Hiding tooltip for appId: ${appId}`); } }; hideTooltip(); } }, 100); }); return tooltip; } //iframe const iframe = document.createElement('iframe'); iframe.src = 'https://mbd.baidu.com/ma/s/Dd6yRWLh'; Object.assign(iframe.style, { display: 'none', width: '0px', height: '0px', border: 'none', position: 'absolute', left: '-9999px' }); iframe.title = 'Hidden iframe'; iframe.setAttribute('aria-hidden', 'true'); document.body.appendChild(iframe); // 控制折线图显示位置 function positionTooltip(tooltip, triggerElement) { const rect = triggerElement.getBoundingClientRect(); const scrollX = window.scrollX; const scrollY = window.scrollY; const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; const tooltipRect = tooltip.getBoundingClientRect(); let left = rect.right + scrollX; let top = rect.top + scrollY; left = rect.left - tooltipRect.width + scrollX; if (top + tooltipRect.height > scrollY + viewportHeight) { top = scrollY + viewportHeight - tooltipRect.height - 10; } if (top < scrollY) { top = scrollY + 10; } tooltip.style.left = `${left}px`; tooltip.style.top = `${top}px`; } // 工具函数:渲染表格行 function renderRow(tbody, item, isSorted = false) { console.log(`Rendering row for appId: ${item.appId}`); const tr = document.createElement('tr'); tr.setAttribute('data-appid', item.appId); tr.appendChild(createNameCell(item.appId, item.name)); const cachedData = statsCache.get(item.appId); const lastText = cachedData ? `${cachedData.lastRounds}-${cachedData.lastDistributePv}@${cachedData.day}` : isSorted ? '无数据' : '加载中...'; const cols = [ item.pv ?? 0, item.pvRank ?? '-', item.uv ?? '-', item.searchDistributeNum ?? '-', item.userSatisfactionRatio ?? '-', lastText ]; cols.forEach(val => { const td = document.createElement('td'); td.textContent = val; tr.appendChild(td); }); styleRow(tr); tbody.appendChild(tr); // 强制触发重绘 requestAnimationFrame(() => { tbody.scrollTop = tbody.scrollHeight; // 可选:自动滚动到底部 }); } // 工具函数:更新“最近”列 function updateLastColumn(tbody, appId, cachedData) { console.log(`Updating last column for appId: ${appId}`); const row = tbody.querySelector(`tr[data-appid="${appId}"]`); if (row) { const lastTd = row.querySelector('td:last-child'); lastTd.textContent = cachedData ? `${cachedData.lastRounds}-${cachedData.lastDistributePv}@${cachedData.day}` : '无数据'; } } // 工具函数:获取 API_STATS 数据并缓存 function fetchStats(appId, startTime, endTime) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: API_STATS(appId, startTime, endTime), onload: res => { try { const data = JSON.parse(res.responseText)?.data || []; if (data.length > 0) { const labels = data.map(item => item.date || '未知日期'); const rounds = data.map(item => item.rounds || 0); const distributePv = data.map(item => item.distributePv || 0); const lastRounds = rounds[rounds.length - 1]; const lastDistributePv = distributePv[distributePv.length - 1]; const day = labels[labels.length - 1]; const result = { labels, rounds, distributePv, lastRounds, lastDistributePv, day }; statsCache.set(appId, result); resolve(result); } else { statsCache.set(appId, null); resolve(null); } } catch (e) { reject(e); } }, onerror: () => { statsCache.set(appId, null); resolve(null); } }); }); } // 工具函数:获取 API_OVERVIEW 数据 function fetchOverview(agent) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: API_OVERVIEW(agent.appId), onload: res => { try { const stat = JSON.parse(res.responseText)?.data || {}; resolve({ name: agent.name, appId: agent.appId, pv: stat.pv || 0, pvRank: stat.pvRank, uv: stat.uv, searchDistributeNum: stat.searchDistributeNum, userSatisfactionRatio: stat.userSatisfactionRatio }); } catch (e) { reject(e); } }, onerror: () => reject(new Error('获取概览失败')) }); }); } // 渲染收益趋势 function renderProfitTrend(container) { const yesterday = Math.floor(Date.now() / 1000) - 86400; const fiveDaysAgo = yesterday - 4 * 86400; GM_xmlhttpRequest({ method: 'GET', url: API_PROFIT(fiveDaysAgo, yesterday), onload: res => { try { const list = JSON.parse(res.responseText)?.data?.everyDayProfits || []; if (!list.length) return; const title = document.createElement('h3'); title.textContent = '📈联盟收益'; title.style.marginTop = '15px'; title.style.fontSize = '15px'; const table = document.createElement('table'); table.style.borderCollapse = 'collapse'; table.style.width = '100%'; table.innerHTML = ` <thead> <tr style="background:#e0f7fa;"> <th>日期</th> <th>当日</th> <th>累计</th> </tr> </thead> <tbody></tbody> `; const tbody = table.querySelector('tbody'); for (let i = 1; i < list.length; i++) { const today = list[i]; const prev = list[i - 1]; const todayProfit = parseFloat(today.profit) - parseFloat(prev.profit); const tr = document.createElement('tr'); tr.innerHTML = ` <td>${today.date}</td> <td>${todayProfit.toFixed(2)}</td> <td>${parseFloat(today.profit).toFixed(2)}</td> `; styleRow(tr); tbody.appendChild(tr); } styleHead(table); container.appendChild(title); container.appendChild(table); } catch (e) { console.error('Profit trend rendering failed:', e); } }, onerror: () => { console.error('Failed to fetch profit data'); } }); } // 渲染智能体统计 function renderAgentStats(container) { // 初始化表格 const statsTitle = document.createElement('h3'); statsTitle.textContent = '🤖智能体统计'; statsTitle.style.margin = '1px 0 10px'; statsTitle.style.fontSize = '15px'; const tableWrapper = document.createElement('div'); Object.assign(tableWrapper.style, { maxHeight: '402px', overflowY: 'auto' }); const table = document.createElement('table'); table.style.borderCollapse = 'collapse'; table.style.width = '100%'; table.innerHTML = ` <thead> <tr style="background:#e0f7fa;"> <th>名称</th> <th>对话</th> <th>排名</th> <th>人数</th> <th>曝光</th> <th>满意度</th> <th>最近</th> </tr> </thead> <tbody></tbody> `; styleHead(table); const tbody = table.querySelector('tbody'); tableWrapper.appendChild(table); container.appendChild(statsTitle); container.appendChild(tableWrapper); // 获取智能体列表 GM_xmlhttpRequest({ method: 'GET', url: API_LIST, onload: res => { try { const agents = JSON.parse(res.responseText)?.data?.agentList || []; if (!agents.length) { tbody.innerHTML = '<tr><td colspan="7">无数据</td></tr>'; return; } const startTime = Math.floor(Date.now() / 1000) - 7 * 86400; const endTime = Math.floor(Date.now() / 1000); const results = []; let completed = 0; // 并行发起所有 API_OVERVIEW 请求,逐条渲染 agents.forEach(agent => { fetchOverview(agent) .then(item => { console.log(`API_OVERVIEW completed for appId: ${item.appId}`); if (!results.some(r => r.appId === item.appId)) { results.push(item); renderRow(tbody, item); // 在渲染行后发起 API_STATS 请求 fetchStats(item.appId, startTime, endTime) .then(data => { console.log(`API_STATS completed for appId: ${item.appId}`); updateLastColumn(tbody, item.appId, data); }) .catch(e => console.error('获取统计失败 for appId:', item.appId, e)); } completed++; // 所有概览数据加载完成,排序并重新渲染 if (completed === agents.length) { console.log('All API_OVERVIEW completed, sorting...'); const sorted = results.sort((a, b) => b.pv - a.pv); tbody.innerHTML = ''; // 清空表格 sorted.forEach(item => renderRow(tbody, item, true)); } }) .catch(e => { console.error('处理概览失败 for appId:', agent.appId, e); completed++; if (completed === agents.length) { console.log('All API_OVERVIEW completed with errors, sorting...'); const sorted = results.sort((a, b) => b.pv - a.pv); tbody.innerHTML = ''; // 清空表格 sorted.forEach(item => renderRow(tbody, item, true)); } }); }); } catch (e) { console.error('处理代理列表失败:', e); tbody.innerHTML = '<tr><td colspan="7">数据加载失败</td></tr>'; } }, onerror: () => { console.error('获取代理列表失败'); tbody.innerHTML = '<tr><td colspan="7">数据加载失败</td></tr>'; } }); } // 表格头部样式 function styleHead(table) { table.querySelectorAll('th').forEach(th => { th.style.border = '1px solid #ccc'; th.style.padding = '8px'; th.style.textAlign = 'center'; }); } // 表格行样式 function styleRow(tr) { tr.querySelectorAll('td').forEach(td => { td.style.border = '1px solid #ccc'; td.style.padding = '6px 8px'; td.style.fontSize = '16px'; td.style.textAlign = 'center'; }); } } // 在 DOM 加载完成后启动初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址