- SignalDesk1小时前
Original Summary
这是最终效果,在commandcode的网页上,提醒你每天的用量,依据剩余的量计算,我今天用到多少相对安全,不会到后面不够用,给自己一个提醒。 js脚本,浏览器装个篡改猴插件,然后新增脚本,把下面的代码贴进去,保存,之后刷新commandcode用量页面就可以 // ==UserScript== // @name CommandCode 每月限额助手 // @namespace https://commandcode.ai/ccx-meter // @version 1.1.0 // @description 增强 commandcode.ai 用量页「每月限额」:重置倒计时(精确到分钟、每分钟自动刷新)、今日安全限额计算与进度条警示线、自然日/工作日两种分摊模式 // @author ws1993 // @match https://commandcode.ai/ // @connect api.commandcode.ai // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @run-at document-idle // @noframes // ==/UserScript== (function () { 'use strict'; / ============================ 可调常量 ============================ / var CFG = { PAD_ID: 'ccx-monthly-pad', // 注入面板的元素 id(防重复挂载) LABEL_RE: /^(每月限额|monthly limit)$/i, // 限额项标签识别(中英双语兼容) RESET_RE: /(\d{1,2})月(\d{1,2})日|([A-Za-z]{3,})\s+(\d{1,2})/, // “11月15日 重置” / “Resets Nov 15” SUBS_API: 'https://api.commandcode.ai/internal/billing/subscriptions?withPending=true', CALIBRATE_MS: 5 60 1000, // 每 5 分钟向后端重新校准重置时间戳 FALLBACK_RESET_HOUR: 0, // 拿不到精确时间戳时,重置日默认按本地 0 点 ACCENT: '#76DEC8', // 与站点每月限额配色一致 RED: '#E5484D' // 今日安全限额警示线/红字 }; var MODES = { natural: '自然日', workday: '工作日' }; var MONTH_EN = { jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5, jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11 }; / ============================ 运行时状态 ============================ / var state = { resetAt: null, // 重置时刻(Date);优先 API 精确值,否则 DOM 文本推算 precise: false // 是否来自 API 精确时间戳 }; var mode = loadMode(); // 计算模式,持久化 var capEl = null; // 「今日安全限额」红字标签(插在 label 与右侧百分比之间) var capMarker = null; // 进度条上的安全限额警示竖线(按累计百分比定位) / ============================ 工具函数 ============================ / // GM 存储优先,降级 localStorage function store(fn, key, val) { var gm = typeof GM_getValue === 'function' && typeof GM_setValue === 'function'; try { if (fn === 'get') return gm ? GM_getValue(key, val) : (localStorage.getItem(key) || val); if (fn === 'set') { if (gm) { GM_setValue(key, val); } else { localStorage.setItem(key, val); } } } catch (e) { / 隐身/受限环境静默降级 / } return val; } function loadMode() { var m = store('get', 'ccx_mode', 'natural'); return MODES[m] ? m : 'natural'; } function dayStart(t) { return new Date(t.getFullYear(), t.getMonth(), t.getDate()); } function fmtPct(x) { return (Math.round(x 100) / 100).toString(); } // 倒计时美化:X天 X小时 X分(精确到分钟) function fmtCountdown(ms) { if (ms == null) return '--'; if (ms <= 0) return '正在重置…'; var d = Math.floor(ms / 86400000); var h = Math.floor(ms % 86400000 / 3600000); var m = Math.floor(ms % 3600000 / 60000); return d > 0 ? (d + '天 ' + h + '小时 ' + m + '分') : (h + '小时 ' + m + '分'); } function fmtDT(t) { return (t.getMonth() + 1) + '月' + t.getDate() + '日 ' + String(t.getHours()).padStart(2, '0') + ':' + String(t.getMinutes()).padStart(2, '0'); } / ============================ 数据获取 ============================ / // 定位「每月限额」限额项根节点(含 label / progressbar / 重置说明 p) function findMonthlyItem() { var spans = document.querySelectorAll('span'); for (var i = 0; i < spans.length; i++) { var s = spans[i]; if (s.children.length || !CFG.LABEL_RE.test(s.textContent.trim())) continue; var n = s.parentElement; // 向上找包含 progressbar 与重置说明的 flex-col 容器 while (n && n !== document.body) { if (n.querySelector('[role="progressbar"]')) return n; n = n.parentElement; } } return null; } // 读取用量百分比:优先 aria-valuenow(受 aria-valuemax 归一化),失败则从已高亮格估算 function readUsedPercent(item) { var pb = item.querySelector('[role="progressbar"]'); if (!pb) return NaN; var v = parseFloat(pb.getAttribute('aria-valuenow')); var max = parseFloat(pb.getAttribute('aria-valuemax')); if (isFinite(v) && isFinite(max) && max > 0) return v / max 100; // 估算兜底:已填充的色块格数 / 总格数 if (pb.firstElementChild) { var cells = pb.children, lit = 0; for (var i = 0; i < cells.length; i++) { if (cells[i].className.indexOf('bg-muted') === -1) lit++; } if (cells.length) return lit / cells.length 100; } return NaN; } // 从重置说明文本(“11月15日 重置”)推算日期;不足当年则顺延一年 function parseResetText(txt) { var m = txt.match(CFG.RESET_RE); if (!m) return null; var mi, d; if (m[1]) { mi = +m[1] - 1; d = +m[2]; } else { mi = MONTH_EN[m[3].slice(0, 3).toLowerCase()]; if (mi == null) return null; d = +m[4]; } var now = new Date(); var t = new Date(now.getFullYear(), mi, d, CFG.FALLBACK_RESET_HOUR, 0, 0, 0); if (t.getTime() <= now.getTime()) t = new Date(now.getFullYear() + 1, mi, d, CFG.FALLBACK_RESET_HOUR, 0, 0, 0); return t; } // 订阅接口:返回精确到秒的 currentPeriodEnd(即「每月限额」重置时刻) function fetchPeriodEnd(cb) { var url = CFG.SUBS_API; var parse = function (j) { return (j && j.data && j.data.currentPeriodEnd) || null; }; if (typeof GM_xmlhttpRequest === 'function') { GM_xmlhttpRequest({ method: 'GET', url: url, timeout: 15000, onload: function (r) { try { cb(null, parse(JSON.parse(r.responseText))); } catch (e) { cb(e); } }, onerror: function () { cb(new Error('network')); }, ontimeout: function () { cb(new Error('timeout')); } }); } else { // 降级:页面上下文同源凭据 fetch(cookie 鉴权) fetch(url, { credentials: 'include' }) .then(function (r) { return r.json(); }) .then(function (j) { cb(null, parse(j)); }) .catch(cb); } } function calibrate() { fetchPeriodEnd(function (err, iso) { if (!err && iso) { var t = new Date(iso); if (!isNaN(t.getTime())) { state.resetAt = t; state.precise = true; render(); } } // 失败时保留上一次结果或 DOM 推算值,不打断本轮渲染 }); } / ============================ 计算模型 ============================ / // 剩余天数:今天(含)到重置日(不含)的日历跨度 function remainingDays(resetAt, now) { return Math.max(1, Math.round((dayStart(resetAt) - dayStart(now)) / 86400000)); } // 工作日统计:同区间内周一~五的天数;todayWorkday 标记今天是否消耗工作日额度 function workdayStats(resetAt, now) { var total = remainingDays(resetAt, now); var today = dayStart(now), workdays = 0; for (var i = 0; i < total; i++) { var w = new Date(today.getTime() + i * 86400000).getDay(); if (w >= 1 && w <= 5) workdays++; } return { total: total, workdays: workdays, todayWorkday: now.getDay() >= 1 && now.getDay(
- 情报分类:商业与市场研究
- 分类依据:内容涉及商业、投资或市场动态
- 信息来源:服务器 / LINUX DO - 最新话题
- 发布时间:2026/10/20 12:12:44
- 暂无回复