您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
在标题栏中显示页面上的花费时间,按域名分组,显示摘要并包括百分比的饼图,并允许删除数据
当前为
// ==UserScript== // @name 页面时间追踪器及摘要与饼图 // @name:zh 页面时间追踪器及摘要与饼图 // @name:en Page Time Tracker with Summary and Pie Chart // @namespace http://tampermonkey.net/ // @license MIT // @version 1.6 // @description 在标题栏中显示页面上的花费时间,按域名分组,显示摘要并包括百分比的饼图,并允许删除数据 // @description:en Track and display time spent on the page in the title bar, group by domain, show a summary with a pie chart including percentages, and allow data deletion // @author lbihhe // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_openInTab // @grant GM_registerMenuCommand // ==/UserScript== (function() { 'use strict'; // 初始化开始时间和原始标题 const startTime = new Date(); const originalTitle = document.title; // 格式化时间为分钟和秒 function formatTimeMS(seconds) { const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; return `${minutes}m ${remainingSeconds}s`; } // 更新标题栏中的时间 function updateTitle() { const currentTime = new Date(); const timeSpent = Math.floor((currentTime - startTime) / 1000); const formattedTime = formatTimeMS(timeSpent); document.title = `${originalTitle} - ${formattedTime}`; } // 存储访问数据 function storeVisit() { const endTime = new Date(); const timeSpent = Math.floor((endTime - startTime) / 1000); const pageData = { url: window.location.href, title: originalTitle, timeSpent: timeSpent, date: startTime.toDateString() }; let visits = GM_getValue('pageVisits', []); visits.push(pageData); GM_setValue('pageVisits', visits); } // 获取域名 function getDomain(url) { const a = document.createElement('a'); a.href = url; return a.hostname; } // 清除旧数据(仅保留当天的数据) function clearOldData() { const today = new Date().toDateString(); let visits = GM_getValue('pageVisits', []); visits = visits.filter(visit => visit.date === today); GM_setValue('pageVisits', visits); } // 删除所有数据 function deleteAllData() { GM_setValue('pageVisits', []); alert('所有访问数据已被删除。'); } // 每天清除一次旧数据 const lastClearTime = GM_getValue('lastClearTime', ''); const today = new Date().toDateString(); if (lastClearTime !== today) { clearOldData(); GM_setValue('lastClearTime', today); } // 在页面卸载时存储访问数据 window.addEventListener('beforeunload', storeVisit); // 每秒更新一次标题栏中的时间 setInterval(() => { updateTitle(); }, 1000); // 注册菜单命令以显示每日摘要 GM_registerMenuCommand('显示每日摘要', function() { const summaryPageContent = generateSummaryPage(); const summaryWindow = window.open('', '_blank'); summaryWindow.document.write(summaryPageContent); summaryWindow.document.close(); }); // 注册菜单命令以删除所有数据 GM_registerMenuCommand('删除所有数据', deleteAllData); // 生成摘要页面 function generateSummaryPage() { const visits = GM_getValue('pageVisits', []); const today = new Date().toDateString(); const todayVisits = visits.filter(visit => visit.date === today); // 按域名分组访问数据 const domainVisits = todayVisits.reduce((acc, visit) => { const domain = getDomain(visit.url); if (!acc[domain]) { acc[domain] = { domain, timeSpent: 0, pages: [] }; } acc[domain].timeSpent += visit.timeSpent; acc[domain].pages.push(visit); return acc; }, {}); const totalSeconds = Object.values(domainVisits).reduce((sum, domain) => sum + domain.timeSpent, 0); let summaryHTML = '<html><head><title>每日摘要</title><style>'; summaryHTML += 'canvas { max-width: 800px; max-height: 600px; }'; summaryHTML += '</style></head><body>'; summaryHTML += '<h1>每日摘要</h1>'; summaryHTML += '<table border="1"><tr><th>域名</th><th>花费时间</th><th>百分比</th></tr>'; Object.values(domainVisits).forEach(domain => { const percentage = ((domain.timeSpent / totalSeconds) * 100).toFixed(2); summaryHTML += `<tr><td>${domain.domain}</td><td>${formatTimeMS(domain.timeSpent)}</td><td>${percentage}%</td></tr>`; }); summaryHTML += '</table><canvas id="timeChart" width="800" height="600"></canvas>'; summaryHTML += '<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>'; summaryHTML += '<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>'; summaryHTML += '<script>'; summaryHTML += 'const ctx = document.getElementById("timeChart").getContext("2d");'; summaryHTML += 'const data = {'; summaryHTML += 'labels: ' + JSON.stringify(Object.keys(domainVisits)) + ','; summaryHTML += 'datasets: [{'; summaryHTML += 'label: "花费时间",'; summaryHTML += 'data: ' + JSON.stringify(Object.values(domainVisits).map(domain => domain.timeSpent)) + ','; summaryHTML += 'backgroundColor: ' + JSON.stringify(Object.values(domainVisits).map((_, i) => `hsl(${i * 360 / Object.values(domainVisits).length}, 100%, 75%)`)) + ','; summaryHTML += '}]'; summaryHTML += '};'; summaryHTML += 'const config = { type: "pie", data: data, options: { plugins: { datalabels: { formatter: (value, ctx) => {'; summaryHTML += 'let total = ctx.chart.data.datasets[0].data.reduce((a, b) => a + b, 0);'; summaryHTML += 'let percentage = (value / total * 100).toFixed(2) + "%";'; summaryHTML += 'return percentage; } } } } };'; summaryHTML += 'Chart.register(ChartDataLabels);'; summaryHTML += 'new Chart(ctx, config);'; summaryHTML += '</script>'; summaryHTML += '</body></html>'; return summaryHTML; } })();