codex-quota-compass.js Based on the provided code, this is a JavaScript utility script designed to be run in the browser console on chatgpt.com to analyze OpenAI Codex usage and quota data. It fetches usage statistics from the `/backend-api/wham/usage` and `/backend-api/wham/analytics/daily-workspace-usage-counts` endpoints, displaying the information in a formatted output with options for UTC or local timezone interpretation. The script includes safety measures to avoid exposing sensitive data like access tokens or user emails, and it requires a manual access token only as a last resort for debugging. Last active May 22, 2026 15:02 - - Save BlueSkyXN/528e810b98affcecca170e6b9d53d7da to your computer and use it in GitHub Desktop. codex-quota-compass.js This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters https://github.co/hiddenchars | async = { | | | 'use strict'; | | | // ============================================================ | | | // codex-quota-compass.js(发布版) | | | // ============================================================ | | | // 用法:在 https://chatgpt.com/codex/cloud/settings/analytics usage | | | // 或任意 chatgpt.com 页面打开 DevTools Console,粘贴运行。 | | | // | | | // 安全: | | | // - 不打印 accessToken / cookie。 | | | // - 不返回 /usage 原始响应,避免泄露 email / user id。 | | | // - MANUAL ACCESS TOKEN 默认留空;只有自动取不到 token 时,才在自己电脑临时填写。 | | | // | | | // 说明: | | | // - /backend-api/wham/usage 的 reset at 是 epoch seconds,不受时区影响。 | | | // - daily-workspace-usage-counts 只接受 YYYY-MM-DD,且 group by 只支持 day/week/month。 | | | // - 本脚本默认把用量日期桶按 UTC 解释;同时输出 UTC / 本地时区诊断。 | | | const CONFIG = { | | | DATE BUCKET MODE: 'utc', // 推荐:'utc';可改为 'local' 对比 | | | USD PER CREDIT: 40 / 1000, // 1000 credits = 40 USD | | | ROLLING DAYS: 30, | | | // 不建议使用。只有自动取不到 accessToken 时,才在自己电脑临时填写 Bearer 后面的内容。 | | | // 发布脚本、截图、复制输出前,必须保持为空。 | | | MANUAL ACCESS TOKEN: '', | | | USAGE PATH: '/backend-api/wham/usage', | | | DAILY USAGE PATH: | | | '/backend-api/wham/analytics/daily-workspace-usage-counts', | | | }; | | | if location.hostname == 'chatgpt.com' { | | | throw new Error '请在 chatgpt.com 页面运行,例如 Codex Usage / Analytics 页面。' ; | | | } | | | // ============================================================ | | | // 基础工具 | | | // ============================================================ | | | const DAY MS = 24 60 60 1000; | | | const n = v = Number.isFinite Number v ? Number v : 0 ; | | | const round = v, d = 2 = Number Number v .toFixed d ; | | | const pad2 = x = String x .padStart 2, '0' ; | | | const last = arr = arr.length ? arr arr.length - 1 : undefined ; | | | const fmtLocal = ms = new Date ms .toLocaleString ; | | | const fmtUTC = ms = | | | new Date ms .toISOString .replace 'T', ' ' .replace '.000Z', ' UTC' ; | | | const ymdUTC = x = { | | | const d = new Date x ; | | | return | | | d.getUTCFullYear , | | | pad2 d.getUTCMonth + 1 , | | | pad2 d.getUTCDate , | | | .join '-' ; | | | }; | | | const ymdLocal = x = { | | | const d = new Date x ; | | | d.setMinutes d.getMinutes - d.getTimezoneOffset ; | | | return d.toISOString .slice 0, 10 ; | | | }; | | | const ymdForApi = ms = | | | CONFIG.DATE BUCKET MODE === 'utc' ? ymdUTC ms : ymdLocal ms ; | | | const addDaysLocalMs = ms, days = { | | | const d = new Date ms ; | | | d.setDate d.getDate + days ; | | | return d.getTime ; | | | }; | | | const addDaysForApi = ms, days = | | | CONFIG.DATE BUCKET MODE === 'utc' | | | ? ms + days DAY MS | | | : addDaysLocalMs ms, days ; | | | const firstDayOfMonthUTC = ms = { | | | const d = new Date ms ; | | | return ${d.getUTCFullYear }-${pad2 d.getUTCMonth + 1 }-01 ; | | | }; | | | const firstDayOfMonthLocal = ms = { | | | const d = new Date ms ; | | | return ymdLocal new Date d.getFullYear , d.getMonth , 1 .getTime ; | | | }; | | | const firstDayOfMonthForApi = ms = | | | CONFIG.DATE BUCKET MODE === 'utc' | | | ? firstDayOfMonthUTC ms | | | : firstDayOfMonthLocal ms ; | | | const utcOffsetLabel = ms = { | | | const offsetMinutes = -new Date ms .getTimezoneOffset ; | | | const sign = offsetMinutes = 0 ? '+' : '-'; | | | const abs = Math.abs offsetMinutes ; | | | return UTC${sign}${pad2 Math.floor abs / 60 }:${pad2 abs % 60 } ; | | | }; | | | const tokenTotal = obj = {} = | | | n obj.text total tokens || | | | n obj.cached text input tokens + | | | n obj.uncached text input tokens + | | | n obj.text output tokens ; | | | const stripBearer = s = | | | String s || '' | | | .replace /^Bearer\s+/i, '' | | | .trim ; | | | const looksLikeJwt = s = | | | typeof s === 'string' && s.length 100 && s.split '.' .length = 3; | | | // ============================================================ | | | // Auth:自动从 session 中找 accessToken,不打印敏感信息 | | | // ============================================================ | | | function findAccessToken obj, depth = 0 { | | | if obj || typeof obj == 'object' || depth 8 return ''; | | | for const key, value of Object.entries obj { | | | if | | | typeof value === 'string' && | | | /access/i.test key && | | | looksLikeJwt value | | | { | | | return value; | | | } | | | if value && typeof value === 'object' { | | | const found = findAccessToken value, depth + 1 ; | | | if found return found; | | | } | | | } | | | return ''; | | | } | | | async function getAccessToken { | | | const manual = stripBearer CONFIG.MANUAL ACCESS TOKEN ; | | | if manual return manual; | | | try { | | | const res = await fetch '/api/auth/session', { | | | credentials: 'include', | | | headers: { accept: 'application/json' }, | | | } ; | | | if res.ok return ''; | | | return findAccessToken await res.json ; | | | } catch { | | | return ''; | | | } | | | } | | | const accessToken = await getAccessToken ; | | | const headers = { | | | accept: 'application/json', | | | }; | | | if accessToken { | | | headers.authorization = Bearer ${accessToken} ; | | | } | | | async function apiGet path { | | | const res = await fetch path, { | | | method: 'GET', | | | credentials: 'include', | | | headers, | | | } ; | | | if res.ok { | | | const text = await res.text .catch = '' ; | | | if res.status === 401 { | | | throw new Error | | | | | | HTTP 401 Unauthorized: ${path} , | | | '', | | | '没有拿到有效 Authorization。', | | | '处理方式:', | | | '1. 先确认你已经登录 chatgpt.com,并在同一个页面运行脚本。', | | | '2. 刷新 Codex Usage / Analytics 页面后重试。', | | | '3. 仍失败时,可在 Network 面板找到成功的 /backend-api/wham/usage 请求,', | | | ' 复制 Authorization: Bearer 后面的 token,只在自己电脑临时填到 CONFIG.MANUAL ACCESS TOKEN。', | | | '', | | | '不要把 token、Cookie、填过 token 的脚本或截图发给任何人。', | | | .join '\n' | | | ; | | | } | | | throw new Error | | | HTTP ${res.status} ${res.statusText}: ${path}\n${text.slice 0, 800 } | | | ; | | | } | | | return res.json ; | | | } | | | // ============================================================ | | | // /usage 解析:刷新周期、重置时间、已用百分比 | | | // ============================================================ | | | function parseWindow label, w { | | | const usedPercent = n w?.used percent ; | | | const windowSeconds = n w?.limit window seconds ; | | | const resetAfterSeconds = n w?.reset after seconds ; | | | const resetAtSeconds = n w?.reset at ; | | | const resetAtMs = resetAtSeconds 1000; | | | const windowStartMs = resetAtMs - windowSeconds 1000; | | | const serverNowMs = resetAtMs - resetAfterSeconds 1000; | | | return { | | | 名称: label, | | | 已用百分比: usedPercent, | | | 已用比例小数: round usedPercent / 100, 4 , | | | 窗口秒数: windowSeconds, | | | 窗口天数: round windowSeconds / 86400, 4 , | | | 本轮开始 UTC: fmtUTC windowStartMs , | | | 本轮开始 本地: fmtLocal windowStartMs , | | | 下次重置 UTC: fmtUTC resetAtMs , | | | 下次重置 本地: fmtLocal resetAtMs , | | | 后端当前 UTC: fmtUTC serverNowMs , | | | 后端当前 本地: fmtLocal serverNowMs , | | | 距离重置小时: round resetAfterSeconds / 3600, 2 , | | | windowStartMs: windowStartMs, | | | resetAtMs: resetAtMs, | | | serverNowMs: serverNowMs, | | | }; | | | } | | | function collectWindows usage { | | | const windows = ; | | | if usage?.rate limit?.primary window { | | | windows.push | | | parseWindow '主限制 - 5小时窗口', usage.rate limit.primary window | | | ; | | | } | | | if usage?.rate limit?.secondary window { | | | windows.push | | | parseWindow '主限制 - 7天窗口', usage.rate limit.secondary window | | | ; | | | } | | | for const item of usage?.additional rate limits ?? { | | | const name = item.limit name || item.metered feature || '额外限制'; | | | if item?.rate limit?.primary window { | | | windows.push | | | parseWindow ${name} - 5小时窗口 , item.rate limit.primary window | | | ; | | | } | | | if item?.rate limit?.secondary window { | | | windows.push | | | parseWindow ${name} - 7天窗口 , item.rate limit.secondary window | | | ; | | | } | | | } | | | return windows; | | | } | | | // ============================================================ | | | // daily-workspace-usage-counts 解析 | | | // ============================================================ | | | function parseDailyRows json { | | | return json.data ?? | | | .slice | | | .sort a, b = String a.date .localeCompare String b.date | | | .map d = { | | | const t = d.totals ?? {}; | | | const credits = n t.credits ; | | | return { | | | 日期桶: d.date, | | | Credits: round credits, 6 , | | | 折算USD: round credits CONFIG.USD PER CREDIT, 2 , | | | 用户数: n t.users , | | | 线程数: n t.threads , | | | 轮数: n t.turns , | | | Token总量: tokenTotal t , | | | 缓存输入Token: n t.cached text input tokens , | | | 非缓存输入Token: n t.uncached text input tokens , | | | 输出Token: n t.text output tokens , | | | 客户端数量: Array.isArray d.clients ? d.clients.length : 0, | | | 客户端Credits: d.clients ?? | | | .map c = ${c.client id ?? 'UNKNOWN'}:${round n c.credits , 2 } | | | .join ' | ' , | | | }; | | | } ; | | | } | | | function summarizeClients json { | | | const map = new Map ; | | | for const day of json.data ?? { | | | for const c of day.clients ?? { | | | const id = c.client id ?? 'UNKNOWN'; | | | const row = map.get id ?? { | | | 客户端: id, | | | Credits: 0, | | | 折算USD: 0, | | | 线程数: 0, | | | 轮数: 0, | | | Token总量: 0, | | | 缓存输入Token: 0, | | | 非缓存输入Token: 0, | | | 输出Token: 0, | | | }; | | | const credits = n c.credits ; | | | row.Credits += credits; | | | row.折算USD += credits CONFIG.USD PER CREDIT; | | | row.线程数 += n c.threads ; | | | row.轮数 += n c.turns ; | | | row.Token总量 += tokenTotal c ; | | | row.缓存输入Token += n c.cached text input tokens ; | | | row.非缓存输入Token += n c.uncached text input tokens ; | | | row.输出Token += n c.text output tokens ; | | | map.set id, row ; | | | } | | | } | | | return ...map.values | | | .map r = { | | | ...r, | | | Credits: round r.Credits, 6 , | | | 折算USD: round r.折算USD, 2 , | | | } | | | .sort a, b = b.Credits - a.Credits ; | | | } | | | async function fetchDailyUsage startDate, endExclusiveDate { | | | const qs = new URLSearchParams { | | | start date: startDate, | | | end date: endExclusiveDate, | | | group by: 'day', | | | } ; | | | const url = ${CONFIG.DAILY USAGE PATH}?${qs} ; | | | const json = await apiGet url ; | | | return { | | | url: location.origin + url, | | | rows: parseDailyRows json , | | | clients: summarizeClients json , | | | }; | | | } | | | function summarizeRows rangeName, rows, startDate, endExclusiveDate { | | | const credits = rows.reduce s, r = s + n r.Credits , 0 ; | | | return { | | | 范围: rangeName, | | | 日期桶口径: | | | CONFIG.DATE BUCKET MODE === 'utc' ? 'UTC日期桶' : '本地日期桶', | | | API start date: startDate, | | | API end date 排他: endExclusiveDate, | | | 返回日期桶数: rows.length, | | | 首个返回日期桶: rows 0 ?.日期桶 ?? '', | | | 最后返回日期桶: last rows ?.日期桶 ?? '', | | | 累计Credits: round credits, 6 , | | | 累计折算USD: round credits CONFIG.USD PER CREDIT, 2 , | | | 累计Token: rows.reduce s, r = s + n r.Token总量 , 0 , | | | 累计线程数: rows.reduce s, r = s + n r.线程数 , 0 , | | | 累计轮数: rows.reduce s, r = s + n r.轮数 , 0 , | | | }; | | | } | | | function publicWindowRow w { | | | const { windowStartMs, resetAtMs, serverNowMs, ...visible } = w; | | | return visible; | | | } | | | function printTimezoneDiagnostics { | | | apiNowMs, | | | windowStartMs, | | | resetAtMs, | | | sinceResetStartDate, | | | monthStartDate, | | | rollingStartDate, | | | endExclusiveDate, | | | } { | | | const browserTimeZone = | | | Intl.DateTimeFormat .resolvedOptions .timeZone || '未知'; | | | console.log '0)时区诊断:刷新周期与用量日期桶' ; | | | console.table | | | { 项目: '浏览器本地时区', 值: browserTimeZone }, | | | { 项目: '浏览器UTC偏移', 值: utcOffsetLabel apiNowMs }, | | | { | | | 项目: '当前脚本日期桶模式', | | | 值: CONFIG.DATE BUCKET MODE === 'utc' ? 'UTC日期桶' : '本地日期桶', | | | }, | | | { 项目: '浏览器当前时间 本地', 值: fmtLocal Date.now }, | | | { 项目: '浏览器当前时间 UTC', 值: fmtUTC Date.now }, | | | { 项目: '后端当前时间 本地', 值: fmtLocal apiNowMs }, | | | { 项目: '后端当前时间 UTC', 值: fmtUTC apiNowMs }, | | | { | | | 项目: '浏览器时间与后端时间差 秒', | | | 值: round Date.now - apiNowMs / 1000, 2 , | | | }, | | | { 项目: '7天窗口开始 本地', 值: fmtLocal windowStartMs }, | | | { 项目: '7天窗口开始 UTC', 值: fmtUTC windowStartMs }, | | | { 项目: '下次重置时间 本地', 值: fmtLocal resetAtMs }, | | | { 项目: '下次重置时间 UTC', 值: fmtUTC resetAtMs }, | | | { 项目: '7天窗口开始日期 本地口径', 值: ymdLocal windowStartMs }, | | | { 项目: '7天窗口开始日期 UTC口径', 值: ymdUTC windowStartMs }, | | | { 项目: '后端当前日期 本地口径', 值: ymdLocal apiNowMs }, | | | { 项目: '后端当前日期 UTC口径', 值: ymdUTC apiNowMs }, | | | { 项目: '本月月初 本地口径', 值: firstDayOfMonthLocal apiNowMs }, | | | { 项目: '本月月初 UTC口径', 值: firstDayOfMonthUTC apiNowMs }, | | | { 项目: 'API start date 上次重置至今', 值: sinceResetStartDate }, | | | { 项目: 'API start date 本月初至今', 值: monthStartDate }, | | | { 项目: API start date 近${CONFIG.ROLLING DAYS}天 , 值: rollingStartDate }, | | | { 项目: 'API end date 排他', 值: endExclusiveDate }, | | | ; | | | } | | | function buildWeeklyEstimate { | | | mainSecondary, | | | sinceResetRows, | | | sinceResetSummary, | | | sinceResetStartDate, | | | } { | | | const usedPercent = n mainSecondary.已用百分比 ; | | | const usedRatio = usedPercent / 100; | | | const includedCredits = n sinceResetSummary.累计Credits ; | | | const resetDayRow = sinceResetRows.find | | | r = r.日期桶 === sinceResetStartDate | | | ; | | | const resetDayCredits = n resetDayRow?.Credits ; | | | const excludedCredits = Math.max 0, includedCredits - resetDayCredits ; | | | if usedRatio <= 0 { | | | return { | | | 依据: '主限制 - 7天窗口 secondary window', | | | 已用百分比: usedPercent, | | | 说明: '已用比例为 0,无法反推总额度。', | | | }; | | | } | | | const totalWithResetDay = includedCredits / usedRatio; | | | const totalWithoutResetDay = excludedCredits / usedRatio; | | | const remainingWithResetDay = Math.max | | | 0, | | | totalWithResetDay - includedCredits | | | ; | | | const remainingWithoutResetDay = Math.max | | | 0, | | | totalWithoutResetDay - excludedCredits | | | ; | | | return { | | | 依据: '主限制 - 7天窗口 secondary window', | | | 已用百分比: usedPercent, | | | 已用比例小数: round usedRatio, 4 , | | | 剩余比例小数: round 1 - usedRatio, 4 , | | | 说明: | | | 'used percent 表示已经用掉的比例;例如 45 = 已用 45%,不是剩余 45%。', | | | 日期桶口径: | | | CONFIG.DATE BUCKET MODE === 'utc' ? 'UTC日期桶' : '本地日期桶', | | | 包含重置日 已用Credits: round includedCredits, 6 , | | | 包含重置日 已用折算USD: round | | | includedCredits CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 重置日整天Credits: round resetDayCredits, 6 , | | | 重置日整天折算USD: round | | | resetDayCredits CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 排除重置日 已用Credits: round excludedCredits, 6 , | | | 排除重置日 已用折算USD: round | | | excludedCredits CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 反推周总Credits 包含重置日: round totalWithResetDay, 2 , | | | 反推周总USD 包含重置日: round | | | totalWithResetDay CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 反推周总Credits 排除重置日: round totalWithoutResetDay, 2 , | | | 反推周总USD 排除重置日: round | | | totalWithoutResetDay CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 剩余Credits 包含重置日口径: round remainingWithResetDay, 2 , | | | 剩余USD 包含重置日口径: round | | | remainingWithResetDay CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 剩余Credits 排除重置日口径: round remainingWithoutResetDay, 2 , | | | 剩余USD 排除重置日口径: round | | | remainingWithoutResetDay CONFIG.USD PER CREDIT, | | | 2 | | | , | | | 误差说明: | | | 'daily analytics 只能按天聚合,不能切到具体小时分钟;实际值通常介于“排除重置日”和“包含重置日”之间。used percent 也是整数,存在四舍五入或截断误差。', | | | }; | | | } | | | // ============================================================ | | | // 主流程 | | | // ============================================================ | | | const usage = await apiGet CONFIG.USAGE PATH ; | | | const windows = collectWindows usage ; | | | if usage?.rate limit?.secondary window { | | | throw new Error | | | '没有找到 usage.rate limit.secondary window,无法反推主 7 天窗口。' | | | ; | | | } | | | const mainSecondary = parseWindow | | | '主限制 - 7天窗口', | | | usage.rate limit.secondary window | | | ; | | | const apiNowMs = mainSecondary. serverNowMs || Date.now ; | | | const apiTodayDate = ymdForApi apiNowMs ; | | | // daily-workspace-usage-counts 的 end date 是排他边界。 | | | // 要尽量包含当前日期桶,所以传“后端当前日期 + 1天”。 | | | const endExclusiveDate = ymdForApi addDaysForApi apiNowMs, 1 ; | | | // 7天窗口:用 UTC 日期桶取 windowStart 所在日期。 | | | // 注意:因为接口只能按天,windowStart 当天只能整天纳入。 | | | const sinceResetStartDate = ymdForApi mainSecondary. windowStartMs ; | | | // 本月初至今:按 DATE BUCKET MODE 取月初。 | | | const monthStartDate = firstDayOfMonthForApi apiNowMs ; | | | // 近 N 天:包含今天,往前 N-1 个日期桶。 | | | const rollingStartDate = ymdForApi | | | addDaysForApi apiNowMs, - CONFIG.ROLLING DAYS - 1 | | | ; | | | printTimezoneDiagnostics { | | | apiNowMs, | | | windowStartMs: mainSecondary. windowStartMs, | | | resetAtMs: mainSecondary. resetAtMs, | | | sinceResetStartDate, | | | monthStartDate, | | | rollingStartDate, | | | endExclusiveDate, | | | } ; | | | const sinceReset = await fetchDailyUsage | | | sinceResetStartDate, | | | endExclusiveDate | | | ; | | | const sinceResetSummary = summarizeRows | | | 上次重置至今近似 ${sinceResetStartDate} ~ ${apiTodayDate} , | | | sinceReset.rows, | | | sinceResetStartDate, | | | endExclusiveDate | | | ; | | | const weeklyEstimate = buildWeeklyEstimate { | | | mainSecondary, | | | sinceResetRows: sinceReset.rows, | | | sinceResetSummary, | | | sinceResetStartDate, | | | } ; | | | const monthToDate = await fetchDailyUsage monthStartDate, endExclusiveDate ; | | | const monthToDateSummary = summarizeRows | | | 本月初至今 ${monthStartDate} ~ ${apiTodayDate} , | | | monthToDate.rows, | | | monthStartDate, | | | endExclusiveDate | | | ; | | | const rolling = await fetchDailyUsage rollingStartDate, endExclusiveDate ; | | | const rollingSummary = summarizeRows | | | 近${CONFIG.ROLLING DAYS}天 ${rollingStartDate} ~ ${apiTodayDate} , | | | rolling.rows, | | | rollingStartDate, | | | endExclusiveDate | | | ; | | | // ============================================================ | | | // 输出 | | | // ============================================================ | | | console.log '1)限制窗口概览:刷新周期 UTC / 本地对照' ; | | | console.table windows.map publicWindowRow ; | | | console.log '2)主 7 天窗口:上次重置至今,按 daily analytics 近似' ; | | | console.log 'GET', sinceReset.url ; | | | console.table sinceResetSummary ; | | | console.log '3)用 used percent 反推周额度' ; | | | console.table weeklyEstimate ; | | | console.log '4)上次重置至今每日明细' ; | | | console.table sinceReset.rows ; | | | console.log '4.1)上次重置至今客户端汇总' ; | | | console.table sinceReset.clients ; | | | console.log '5)本月初至今汇总' ; | | | console.log 'GET', monthToDate.url ; | | | console.table monthToDateSummary ; | | | console.log '6)本月初至今日明细' ; | | | console.table monthToDate.rows ; | | | console.log '6.1)本月初至今客户端汇总' ; | | | console.table monthToDate.clients ; | | | console.log 7)近${CONFIG.ROLLING DAYS}天汇总 ; | | | console.log 'GET', rolling.url ; | | | console.table rollingSummary ; | | | console.log 8)近${CONFIG.ROLLING DAYS}天每日明细 ; | | | console.table rolling.rows ; | | | console.log 8.1)近${CONFIG.ROLLING DAYS}天客户端汇总 ; | | | console.table rolling.clients ; | | | console.log | | | '说明:end date 是排他边界;如果今天没有返回,通常是 daily analytics 尚未刷新或当天暂无统计。' | | | ; | | | return { | | | 配置: { | | | 日期桶模式: CONFIG.DATE BUCKET MODE, | | | USD PER CREDIT: CONFIG.USD PER CREDIT, | | | ROLLING DAYS: CONFIG.ROLLING DAYS, | | | }, | | | 时区诊断: { | | | 浏览器本地时区: | | | Intl.DateTimeFormat .resolvedOptions .timeZone || '未知', | | | 浏览器UTC偏移: utcOffsetLabel apiNowMs , | | | 后端当前 UTC: fmtUTC apiNowMs , | | | 后端当前 本地: fmtLocal apiNowMs , | | | 七天窗口开始 UTC: fmtUTC mainSecondary. windowStartMs , | | | 七天窗口开始 本地: fmtLocal mainSecondary. windowStartMs , | | | 下次重置 UTC: fmtUTC mainSecondary. resetAtMs , | | | 下次重置 本地: fmtLocal mainSecondary. resetAtMs , | | | API start date 上次重置至今: sinceResetStartDate, | | | API start date 本月初至今: monthStartDate, | | | API start date 近${CONFIG.ROLLING DAYS}天 : rollingStartDate, | | | API end date 排他: endExclusiveDate, | | | }, | | | 限制窗口概览: windows.map publicWindowRow , | | | 主7天窗口 上次重置至今: { | | | 汇总: sinceResetSummary, | | | 反推周额度: weeklyEstimate, | | | 每日明细: sinceReset.rows, | | | 客户端汇总: sinceReset.clients, | | | }, | | | 本月初至今: { | | | 汇总: monthToDateSummary, | | | 每日明细: monthToDate.rows, | | | 客户端汇总: monthToDate.clients, | | | }, | | | 近${CONFIG.ROLLING DAYS}天 : { | | | 汇总: rollingSummary, | | | 每日明细: rolling.rows, | | | 客户端汇总: rolling.clients, | | | }, | | | }; | | | } ; | 似乎获取不了点数和金额了