国模Coding Plan包含GLM-5.1/5.2套餐分析/对比工具

JOJOBA 2026-06-24 22:11 1

之前找GLM 5.1套餐,选中讯飞星辰,而现在出了GLM 5.2,但讯飞还没跟上。



背景
公司试了几个模型,比如ds,mimo,minimax,现在想试一下GLM5.1,感觉GLM5.1的口碑挺不错的,可能会长期使用,对比计划的工作落到我头上,想问问佬友们,给给参考,佬友的GLM5.1是买哪里的套餐?
需求

能用GLM5.1,主要用GLM5.1
需要给4个人用
最好高峰期不要排队限流


但又心痒痒的,想用上GLM 5.2,因此又调研了一下一些平台的套餐,看看哪里有GLM5.2,并弄了个 html,便于对比。


数据来源: 火山方舟 | 百度千帆 | 优云智算 | 讯飞星辰 | 智谱GLM | OpenCode Go


(听说联通云Coding Plan没有了,所以去掉联通云渠道了)







弄了个费用计算器,可以根据模型使用情况,计算出推荐的套餐。


部署到了cloudflare: 链接


以下是html,细节与逻辑可以从中查阅


<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coding Plan 计算器 - 平台对比与费用估算</title>
<style>
:root {
--bg: #0f0f1a;
--card: #1a1a2e;
--card-hover: #222244;
--text: #e0e0f0;
--text-dim: #8888aa;
--accent: #6366f1;
--accent-light: #818cf8;
--success: #22c55e;
--warning: #f59e0b;
--danger: #ef4444;
--border: #2a2a4a;
--input-bg: #13132a;
--radius: 12px;
--shadow: 0 4px 24px rgba(0,0,0,0.4);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans SC", sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.6;
min-height: 100vh;
}
.container { max-width: 1400px; margin: 0 auto; padding: 24px; }
header {
text-align: center;
padding: 40px 0 30px;
border-bottom: 1px solid var(--border);
margin-bottom: 30px;
}
header h1 {
font-size: 2.2rem;
background: linear-gradient(135deg, var(--accent), var(--accent-light));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 8px;
}
header p { color: var(--text-dim); font-size: 1rem; }
.last-update { color: var(--text-dim); font-size: 0.85rem; margin-top: 8px; }
.tabs { display: flex; gap: 8px; margin-bottom: 24px; flex-wrap: wrap; }
.tab-btn {
padding: 10px 24px;
border: 1px solid var(--border);
background: var(--card);
color: var(--text-dim);
border-radius: var(--radius);
cursor: pointer;
font-size: 0.95rem;
transition: all 0.2s;
}
.tab-btn:hover { background: var(--card-hover); color: var(--text); }
.tab-btn.active { background: var(--accent); color: white; border-color: var(--accent); }
.section { display: none; }
.section.active { display: block; }
.platforms-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); gap: 20px; }
.platform-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; transition: all 0.2s; }
.platform-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); }
.platform-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; flex-wrap: wrap; gap: 8px; }
.platform-name { font-size: 1.25rem; font-weight: 600; color: var(--text); }
.platform-badges { display: flex; gap: 6px; flex-wrap: wrap; }
.platform-tag { font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; background: var(--accent); color: white; }
.platform-tag.warn { background: var(--warning); color: #000; }
.platform-tag.danger { background: var(--danger); }
.platform-tag.info { background: #0ea5e9; }
.platform-url { font-size: 0.8rem; color: var(--accent-light); text-decoration: none; word-break: break-all; }
.platform-url:hover { text-decoration: underline; }
.docs-link { font-size: 0.8rem; color: var(--text-dim); margin-left: 8px; }
.tier-list { margin: 16px 0; }
.tier-item { background: var(--input-bg); border-radius: 8px; padding: 12px 16px; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; }
.tier-name { font-weight: 600; color: var(--accent-light); }
.tier-price { font-size: 1.1rem; font-weight: 700; color: var(--success); }
.tier-price .first-month { font-size: 0.8rem; color: var(--warning); font-weight: 400; }
.tier-price .period-options { font-size: 0.75rem; color: var(--text-dim); font-weight: 400; }
.tier-limits { width: 100%; font-size: 0.85rem; color: var(--text-dim); margin-top: 4px; }
.tier-limits .limit-item { display: inline-block; margin-right: 12px; }
.model-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0; }
.model-tag { font-size: 0.8rem; padding: 4px 10px; border-radius: 6px; background: rgba(99,102,241,0.15); color: var(--accent-light); border: 1px solid rgba(99,102,241,0.3); }
.model-tag.deprecated { background: rgba(239,68,68,0.15); color: var(--danger); border-color: rgba(239,68,68,0.3); text-decoration: line-through; }
.model-tag.tool-only { background: rgba(99,102,241,0.08); border-style: dashed; opacity: 0.7; }
.model-tag .multiplier { font-size: 0.7rem; opacity: 0.7; margin-left: 4px; }
.model-tag .note { font-size: 0.7rem; opacity: 0.6; margin-left: 4px; font-style: italic; }
.pros-cons { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; font-size: 0.85rem; }
.pros-cons .pro { color: var(--success); }
.pros-cons .con { color: var(--danger); }
.pros-cons strong { display: block; margin-bottom: 4px; color: var(--text); }
.notes { margin-top: 12px; padding: 10px 14px; background: rgba(245,158,11,0.1); border-left: 3px solid var(--warning); border-radius: 0 6px 6px 0; font-size: 0.85rem; color: var(--text-dim); }
.notes.info { background: rgba(99,102,241,0.1); border-left-color: var(--accent); }
.notes.success { background: rgba(34,197,94,0.1); border-left-color: var(--success); }
.notes.danger { background: rgba(239,68,68,0.1); border-left-color: var(--danger); }
.calc-options { background: var(--input-bg); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 20px; margin-bottom: 20px; display: flex; flex-wrap: wrap; gap: 20px; align-items: center; }
.calc-options-title { font-size: 0.9rem; font-weight: 600; color: var(--accent-light); margin-right: 8px; }
.calc-option { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 0.9rem; color: var(--text); user-select: none; padding: 6px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--card); transition: all 0.2s; }
.calc-option:hover { border-color: var(--accent); }
.calc-option input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer; }
.calc-option.active { border-color: var(--accent); background: rgba(99,102,241,0.1); }
.calc-option .option-label { font-weight: 500; }
.calc-option .option-desc { font-size: 0.75rem; color: var(--text-dim); margin-left: 4px; }
.calc-options-note { width: 100%; font-size: 0.8rem; color: var(--text-dim); margin-top: 4px; }
.calc-section { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; margin-bottom: 24px; }
.calc-section h2 { font-size: 1.3rem; margin-bottom: 20px; color: var(--accent-light); }
.usage-rows { display: grid; gap: 12px; }
.usage-row { background: var(--input-bg); border-radius: 10px; padding: 16px; border: 1px solid var(--border); }
.form-row { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr auto; gap: 12px; align-items: end; }
@media (max-width: 900px) {
.form-row { grid-template-columns: 1fr 1fr; }
.form-row .form-group:nth-child(1) { grid-column: 1 / -1; }
}
.form-group label { display: block; font-size: 0.85rem; color: var(--text-dim); margin-bottom: 6px; }
.form-group input, .form-group select { width: 100%; padding: 10px 14px; background: var(--input-bg); border: 1px solid var(--border); border-radius: 8px; color: var(--text); font-size: 0.95rem; transition: border-color 0.2s; }
.form-group input:focus, .form-group select:focus { outline: none; border-color: var(--accent); }
.token-hint { font-size: 0.75rem; color: var(--text-dim); margin-top: 4px; }
.btn { padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-size: 0.9rem; transition: all 0.2s; font-weight: 500; }
.btn-primary { background: var(--accent); color: white; }
.btn-primary:hover { background: var(--accent-light); }
.btn-danger { background: rgba(239,68,68,0.2); color: var(--danger); }
.btn-danger:hover { background: rgba(239,68,68,0.3); }
.btn-success { background: var(--success); color: white; }
.btn-success:hover { opacity: 0.9; }
.results-section { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; }
.results-section h2 { font-size: 1.3rem; margin-bottom: 20px; color: var(--accent-light); }
.results-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.results-table th, .results-table td { padding: 12px 16px; text-align: left; border-bottom: 1px solid var(--border); }
.results-table th { color: var(--text-dim); font-weight: 500; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.5px; }
.results-table tr:hover { background: var(--card-hover); }
.results-table .rank { font-weight: 700; font-size: 1.1rem; }
.results-table .rank-1 { color: #ffd700; }
.results-table .rank-2 { color: #c0c0c0; }
.results-table .rank-3 { color: #cd7f32; }
.results-table .over-limit { color: var(--danger); font-weight: 600; }
.results-table .within-limit { color: var(--success); font-weight: 600; }
.results-table .recommend { background: rgba(34,197,94,0.1); }
.results-table .not-recommend { background: rgba(239,68,68,0.05); }
.results-table .multi-account-badge { display: inline-block; background: rgba(99,102,241,0.2); color: var(--accent-light); padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: 600; margin-left: 6px; }
.results-table .first-month-badge { display: inline-block; background: rgba(245,158,11,0.2); color: var(--warning); padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: 600; margin-left: 6px; }
.detail-btn { background: none; border: 1px solid var(--border); color: var(--accent-light); padding: 4px 12px; border-radius: 6px; cursor: pointer; font-size: 0.8rem; }
.detail-btn:hover { border-color: var(--accent); }
.detail-panel { display: none; margin-top: 12px; padding: 16px; background: var(--input-bg); border-radius: 8px; font-size: 0.85rem; }
.detail-panel.show { display: block; }
.detail-panel table { width: 100%; border-collapse: collapse; }
.detail-panel td { padding: 6px 8px; border-bottom: 1px solid var(--border); }
.detail-panel td:first-child { color: var(--text-dim); width: 40%; }
.summary-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; }
.summary-card { background: var(--input-bg); border-radius: 10px; padding: 20px; text-align: center; border: 1px solid var(--border); }
.summary-card .value { font-size: 1.8rem; font-weight: 700; color: var(--accent-light); }
.summary-card .label { font-size: 0.85rem; color: var(--text-dim); margin-top: 4px; }
.empty-state { text-align: center; padding: 60px 20px; color: var(--text-dim); }
.empty-state svg { width: 64px; height: 64px; margin-bottom: 16px; opacity: 0.5; }
.footer { text-align: center; padding: 40px 0; color: var(--text-dim); font-size: 0.85rem; border-top: 1px solid var(--border); margin-top: 40px; }
.footer a { color: var(--accent-light); }
.multiplier-note { background: rgba(245,158,11,0.08); border: 1px dashed var(--warning); border-radius: 8px; padding: 12px 16px; margin: 12px 0; font-size: 0.85rem; color: var(--text-dim); }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.platform-card, .calc-section, .results-section { animation: fadeIn 0.3s ease-out; }
</style>
</head>
<body>
<div class="container">
<header>
<h1>🤖 Coding Plan 计算器</h1>
<p>国内主流 AI Coding Plan 平台对比与费用估算工具</p>
<div class="last-update">📅 数据更新时间:2026年6月24日 | 基于官方文档及社区整理</div>
</header>
<div class="tabs">
<button class="tab-btn active" data-tab="overview">📊 平台概览</button>
<button class="tab-btn" data-tab="calculator">🧮 费用计算器</button>
</div>
<div id="overview" class="section active">
<div class="platforms-grid" id="platformsGrid"></div>
</div>
<div id="calculator" class="section">
<div class="calc-section">
<h2>📝 输入你的模型使用情况</h2>
<p style="color:var(--text-dim);margin-bottom:16px;font-size:0.9rem;">
添加你日常使用的模型及预估用量。<strong>OpenCode Go 用户建议填写 Token 数以获得精确计算</strong>,其他平台按请求次数计算。
</p>
<div class="calc-options" id="calcOptions">
<span class="calc-options-title">🔧 计算模式</span>
<label class="calc-option" id="opt-first-month">
<input type="checkbox" id="firstMonthCheck" onchange="toggleOptionStyle(this)">
<span>
<span class="option-label">首月优惠</span>
<span class="option-desc">排序时按首月优惠价计算</span>
</span>
</label>
<label class="calc-option" id="opt-multi-account">
<input type="checkbox" id="multiAccountCheck" onchange="toggleOptionStyle(this)">
<span>
<span class="option-label">同套餐多账号</span>
<span class="option-desc">超限时自动计算所需账号数</span>
</span>
</label>
<label class="calc-option" id="opt-on-peak">
<input type="checkbox" id="onPeakCheck" onchange="toggleOptionStyle(this)">
<span>
<span class="option-label">高峰使用</span>
<span class="option-desc">排序时按全高峰价计算</span>
</span>
</label>
<label class="calc-option" id="opt-off-peak">
<input type="checkbox" id="offPeakCheck" onchange="toggleOptionStyle(this)">
<span>
<span class="option-label">低峰使用</span>
<span class="option-desc">排序时按全低峰价计算</span>
</span>
</label>
<div class="calc-options-note">
💡 三种模式可以叠加使用。开启「首月优惠」后,有首月价的套餐会按首月价排序;开启「多账号」后,单账号超限的方案会显示所需账号数量及总价。
</div>
</div>
<div class="usage-rows" id="usageRows"></div>
<div style="display:flex;gap:12px;margin-top:16px;flex-wrap:wrap;">
<button class="btn btn-primary" onclick="addUsageRow()">➕ 添加模型</button>
<button class="btn btn-success" onclick="calculate()">🚀 计算费用</button>
<button class="btn btn-danger" onclick="clearAll()">🗑️ 清空</button>
</div>
</div>
<div class="results-section" id="resultsSection" style="display:none;">
<h2>📈 计算结果与排名</h2>
<div class="summary-cards" id="summaryCards"></div>
<div style="overflow-x:auto;">
<table class="results-table" id="resultsTable">
<thead>
<tr>
<th>排名</th>
<th>平台</th>
<th>套餐</th>
<th>月费</th>
<th>预估消耗</th>
<th>是否超限</th>
<th>性价比</th>
<th>详情</th>
</tr>
</thead>
<tbody id="resultsBody"></tbody>
</table>
</div>
</div>
<div class="empty-state" id="emptyState">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M9 7h6m0 10v-3m-3 3h.01M9 17h.01M9 14h.01M12 14h.01M15 11h.01M12 11h.01M9 11h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z"/>
</svg>
<p>添加模型使用情况后,点击「计算费用」查看各平台对比排名</p>
</div>
</div>
<div class="footer">
<p>⚠️ 数据来源于各平台官方文档及公开渠道,仅供参考。实际价格与限制请以官方最新信息为准。</p>
<p style="margin-top:8px;">
数据来源:
<a href="https://www.volcengine.com/docs/82379/1928220" target="_blank">火山方舟</a> |
<a href="https://cloud.baidu.com/doc/qianfan/s/imlg0beiu" target="_blank">百度千帆</a> |
<a href="https://www.uyuncloud.com/" target="_blank">优云智算</a> |
<a href="https://www.xfyun.cn/doc/spark/CodingPlan.html" target="_blank">讯飞星辰</a> |
<a href="https://docs.bigmodel.cn/cn/coding-plan/overview" target="_blank">智谱GLM</a> |
<a href="https://opencode.ai/docs/go/" target="_blank">OpenCode Go</a>
</p>
</div>
</div>
<script>
// ===== OpenCode Go 模型 Token 定价(每 1M tokens) =====
const OPCODE_TOKEN_PRICING = {
"GLM-5.2": { input: 1.40, output: 4.40, cachedRead: 0.26 },
"GLM-5.1": { input: 1.40, output: 4.40, cachedRead: 0.26 },
"Kimi-K2.7-Code": { input: 0.95, output: 4.00, cachedRead: 0.19 },
"Kimi-K2.6": { input: 0.95, output: 4.00, cachedRead: 0.16 },
"MiMo-V2.5": { input: 0.14, output: 0.28, cachedRead: 0.0028 },
"MiMo-V2.5-Pro": { input: 1.74, output: 3.48, cachedRead: 0.0145 },
"MiniMax-M3": { input: 0.30, output: 1.20, cachedRead: 0.06 },
"MiniMax-M2.7": { input: 0.30, output: 1.20, cachedRead: 0.06, cachedWrite: 0.375 },
"MiniMax-M2.5": { input: 0.30, output: 1.20, cachedRead: 0.06, cachedWrite: 0.375 },
"Qwen3.7-Max": { input: 2.50, output: 7.50, cachedRead: 0.50 },
"Qwen3.7-Plus": { input: 0.40, output: 1.60, cachedRead: 0.04, cachedWrite: 0.50 },
"Qwen3.6-Plus": { input: 0.50, output: 3.00, cachedRead: 0.05, cachedWrite: 0.625 },
"Qwen3.5-Plus": { input: 0.50, output: 3.00, cachedRead: 0.05, cachedWrite: 0.625 },
"DeepSeek-V4-Pro": { input: 1.74, output: 3.48, cachedRead: 0.0145 },
"DeepSeek-V4-Flash": { input: 0.14, output: 0.28, cachedRead: 0.0028 }
};

const OPCODE_DEFAULT_TOKENS = {
"GLM-5.2": { input: 700, cached: 52000, output: 150 },
"GLM-5.1": { input: 700, cached: 52000, output: 150 },
"Kimi-K2.7-Code": { input: 870, cached: 55000, output: 200 },
"Kimi-K2.6": { input: 870, cached: 55000, output: 200 },
"MiMo-V2.5": { input: 830, cached: 71500, output: 295 },
"MiMo-V2.5-Pro": { input: 790, cached: 86000, output: 305 },
"MiniMax-M3": { input: 510, cached: 56000, output: 190 },
"MiniMax-M2.7": { input: 300, cached: 55000, output: 125 },
"MiniMax-M2.5": { input: 300, cached: 55000, output: 125 },
"Qwen3.7-Max": { input: 420, cached: 66000, output: 200 },
"Qwen3.7-Plus": { input: 500, cached: 57000, output: 190 },
"Qwen3.6-Plus": { input: 500, cached: 57000, output: 190 },
"Qwen3.5-Plus": { input: 500, cached: 57000, output: 190 },
"DeepSeek-V4-Pro": { input: 750, cached: 82000, output: 290 },
"DeepSeek-V4-Flash": { input: 790, cached: 68000, output: 280 }
};

const PLATFORMS = [
{
id: "volc", name: "火山方舟",
url: "https://www.volcengine.com/activity/codingplan",
docsUrl: "https://www.volcengine.com/docs/82379/1928220",
tiers: [
{ name: "Lite", price: 40, priceFirstMonth: 9.9, period: "月",
limits: { per5h: 1200, perWeek: 9000, perMonth: 18000 },
notes: "首月9.9元(优惠状态待确认)。支持多款模型自由切换,Auto模式智能调度。" },
{ name: "Pro", price: 200, priceFirstMonth: 49.9, period: "月",
limits: { per5h: 6000, perWeek: 45000, perMonth: 90000 },
notes: "首月49.9元(优惠状态待确认)。Lite套餐5倍用量。ArkClaw免费体验。" }
],
models: [
{ name: "Auto", multiplier: 1, note: "智能调度最优模型" },
{ name: "Doubao-Seed-Code", multiplier: 1 },
{ name: "Doubao-Seed-2.0-Code", multiplier: 1 },
{ name: "Doubao-Seed-2.0-lite", multiplier: 1 },
{ name: "Doubao-Seed-2.0-pro", multiplier: 2.5 },
{ name: "DeepSeek-V4-Flash", multiplier: 1 },
{ name: "DeepSeek-V4-Pro", multiplier: 5.5 },
{ name: "GLM-5.2", multiplier: 4.5 },
{ name: "GLM-5.1", multiplier: 4.5, note: "即将下线,建议切换至GLM-5.2" },
{ name: "Kimi-K2.6", multiplier: 4.5 },
{ name: "Kimi-K2.7-Code", multiplier: 4.5 },
{ name: "Kimi-K2.5", multiplier: 4.5, note: "即将下线" },
{ name: "MiniMax-M3", multiplier: 2.5 },
{ name: "MiniMax-M2.7", multiplier: 2.5 },
{ name: "MiniMax-M2.5", multiplier: 2.5, note: "即将下线" },
{ name: "Doubao-Embedding-Vision", multiplier: 0.5 }
],
billingUnit: "请求次数(按模型倍率折算)",
refreshRule: "每5小时滑动窗口、每周一00:00重置、每月第1日00:00重置",
multiplierNote: "官方未公开Coding Plan具体模型倍率。以下为参考Agent Plan AFP抵扣系数估算的相对于Doubao-Seed-2.0-lite的倍率,仅供参考。",
pros: "模型最丰富,首月优惠",
cons: "倍率估算仅供参考,有超售问题,响应缓慢,频繁400/429错误"
},
{
id: "qianfan", name: "百度千帆",
url: "https://cloud.baidu.com/product/codingplan.html",
docsUrl: "https://cloud.baidu.com/doc/qianfan/s/imlg0beiu",
tiers: [
{ name: "Lite", price: 40, period: "月",
limits: { per5h: 1200, perWeek: 9000, perMonth: 18000 },
notes: "DeepSeek-V4-Pro 高峰期5倍/低峰期4倍,GLM-5.1 高峰期4倍/低峰期3倍。白天429限流严重。" },
{ name: "Pro", price: 200, period: "月",
limits: { per5h: 6000, perWeek: 45000, perMonth: 90000 },
notes: "Pro建议不超过2个终端。高峰期:每日10:30-12:00, 14:00-18:00(非固定值)。" }
],
models: [
{ name: "DeepSeek-V4-Flash", multiplier: 1 },
{ name: "DeepSeek-V4-Pro", multiplier: 5, offPeakMultiplier: 4, note: "高峰期5倍/低峰期4倍" },
{ name: "GLM-5.1", multiplier: 4, offPeakMultiplier: 3, note: "高峰期4倍/低峰期3倍" },
{ name: "GLM-5", multiplier: 3, offPeakMultiplier: 2, note: "高峰期3倍/低峰期2倍" },
{ name: "Kimi-K2.5", multiplier: 1 },
{ name: "ERNIE-4.5-Turbo-20260402", multiplier: 1 },
{ name: "MiniMax-M2.5", multiplier: 1 },
{ name: "DeepSeek-V3.2", multiplier: 1 }
],
billingUnit: "请求次数",
refreshRule: "每5小时滑动窗口、每周一00:00重置、每月订阅日00:00重置",
peakHours: "每日10:30-12:00, 14:00-18:00(非固定,随流量变化)",
pros: "无自家模型干扰,纯聚合平台,GLM-5/Kimi体验流畅",
cons: "白天429限流严重,无独家优势"
},
{
id: "youyun", name: "优云智算",
url: "https://www.compshare.cn/coding-plan",
docsUrl: "https://www.compshare.cn/docs/modelverse/package_plan/package",
loginRequired: true,
tiers: [
{ name: "Mini", price: 49, period: "月", limits: { per5h: 300, perWeek: 750, perMonth: 1900 }, concurrency: 3, notes: "300次/5h,月1900次,3并发" },
{ name: "Lite", price: 99, period: "月", limits: { per5h: 600, perWeek: 1500, perMonth: 3800 }, concurrency: 5, notes: "600次/5h,月3800次,5并发" },
{ name: "Basic", price: 199, period: "月", limits: { per5h: 1200, perWeek: 3000, perMonth: 7600 }, concurrency: 10, notes: "1200次/5h,月7600次,10并发" },
{ name: "Pro", price: 499, period: "月", limits: { per5h: 3000, perWeek: 7500, perMonth: 19000 }, concurrency: 10, notes: "3000次/5h,月19000次,10并发" },
{ name: "Max", price: 799, period: "月", limits: { per5h: 4800, perWeek: 12000, perMonth: 31000 }, concurrency: 10, notes: "4800次/5h,月31000次,10并发" },
{ name: "Ultra", price: 999, period: "月", limits: { per5h: 6000, perWeek: 15000, perMonth: 39000 }, concurrency: 10, notes: "6000次/5h,月39000次,10并发" }
],
models: [
{ name: "DeepSeek-V3.2", multiplier: 1 },
{ name: "DeepSeek-V4-Flash", multiplier: 1 },
{ name: "GLM-5.2", multiplier: 2, note: '限时2倍率' },
{ name: "GLM-5.1", multiplier: 6 },
{ name: "Kimi-K2.6", multiplier: 5 },
{ name: "MiniMax-M2.7", multiplier: 2 }
],
billingUnit: "请求次数(固定套餐)",
refreshRule: "每5小时滑动窗口、按月固定次数",
pros: "按次数计费,简单直接,倍率透明,支持3-10并发",
cons: "性价比偏低,相同请求次数下价格略高于主流平台。数据待官方确认。"
},
{
id: "xunfei", name: "讯飞星辰",
url: "https://maas.xfyun.cn/packageSubscription",
docsUrl: "https://www.xfyun.cn/doc/spark/CodingPlan.html",
loginRequired: true,
tiers: [
{ name: "无忧版", price: 19, priceQuarterly: 49.9, period: "月",
limits: { per5h: null, perWeek: null, perMonth: null },
notes: "不限次数。仅支持轻量模型:Spark-X2-Flash、Qwen3.6-35B-A3B、Qwen3.5-35B-A3B、Qwen3-Coder-Next-FP8、GLM-4.7-Flash",
supportedModels: ["Spark-X2-Flash", "Qwen3.6-35B-A3B", "Qwen3.5-35B-A3B", "Qwen3-Coder-Next-FP8", "GLM-4.7-Flash"] },
{ name: "专业版", price: 39, priceQuarterly: 111, period: "月",
limits: { per5h: 1200, perWeek: 9000, perMonth: 18000 },
notes: "焕新版(2026年4月9日上线)。DeepSeek-V4-Flash仅高效版可用。V4上下文256K。2026.6.18起波谷系数0.8。",
supportedModels: ["Spark-X2-Flash", "Qwen3.6-35B-A3B", "Qwen3.5-35B-A3B", "Qwen3-Coder-Next-FP8", "GLM-4.7-Flash", "Spark-X2", "GLM-5", "GLM-5.1", "Kimi-K2.6", "Kimi-K2.5", "MiniMax-M2.5", "DeepSeek-V3.2"] },
{ name: "高效版", price: 199, priceQuarterly: 538, period: "月",
limits: { per5h: 6000, perWeek: 45000, perMonth: 90000 },
notes: "包含DeepSeek-V4-Pro、DeepSeek-V4-Flash。2026.6.18起波谷系数0.8。" }
],
models: [
{ name: "Spark-X2", multiplier: 1 },
{ name: "Spark-X2-Flash", multiplier: 1 },
{ name: "GLM-5", multiplier: 1 },
{ name: "GLM-5.1", multiplier: 1 },
{ name: "Kimi-K2.6", multiplier: 1 },
{ name: "Kimi-K2.5", multiplier: 1 },
{ name: "MiniMax-M2.5", multiplier: 1 },
{ name: "DeepSeek-V3.2", multiplier: 1 },
{ name: "DeepSeek-V4-Flash", multiplier: 1, note: "仅高效版可用" },
{ name: "DeepSeek-V4-Pro", multiplier: 1, note: "仅高效版可用" },
{ name: "Qwen3.6-35B-A3B", multiplier: 1 },
{ name: "Qwen3.5-35B-A3B", multiplier: 1 },
{ name: "Qwen3.5-397B-A17B", multiplier: 1 },
{ name: "Qwen3-Coder-Next-FP8", multiplier: 1 },
{ name: "GLM-4.7-Flash", multiplier: 1 }
],
billingUnit: "请求次数(按实际模型调用次数扣额度)",
refreshRule: "按月/按季,每5小时滑动窗口、每周周期(按订单支付时间+7日,每日08:00重置)",
valleyFactor: "2026.6.18起:高峰1.0(工作日8:00-22:00),波谷0.8(夜间22:00-8:00、周末、节假日)",
pros: "量大,模型可分别使用,能当次选,价格低,波谷系数优惠",
cons: "有时或经常降智,DeepSeek-V4-Flash仅高效版可用,部分模型仅限高阶套餐"
},
{
id: "glm", name: "智谱 GLM",
url: "https://www.bigmodel.cn/glm-coding",
docsUrl: "https://docs.bigmodel.cn/cn/coding-plan/overview",
tiers: [
{ name: "Lite", price: 49, priceQuarterly: 132, priceYearly: 411, period: "月",
limits: { per5h: 80, perWeek: 400, perMonth: null },
notes: "约80 prompts/5h,约400 prompts/周。1 prompt ≈ 15-20次模型调用。GLM-5/5.1/5.2逐步灰度开放。每日10:00限量发售,经常秒售罄。",
mcpMonthly: 100 },
{ name: "Pro", price: 149, priceQuarterly: 402, priceYearly: 1251, period: "月",
limits: { per5h: 400, perWeek: 2000, perMonth: null },
notes: "约400 prompts/5h,约2000 prompts/周。支持GLM-5/5.1/5.2(高峰期3倍抵扣,非高峰期2倍抵扣,限时福利非高峰期1倍至9月底)。",
mcpMonthly: 1000 },
{ name: "Max", price: 469, priceQuarterly: 1266, priceYearly: 3939, period: "月",
limits: { per5h: 1600, perWeek: 8000, perMonth: null },
notes: "约1600 prompts/5h,约8000 prompts/周。支持GLM-5/5.1/5.2(高峰期3倍抵扣)。每日10:00限量发售,Max每天仅开放约20%额度。",
mcpMonthly: 4000 }
],
models: [
{ name: "GLM-4.7", multiplier: 1 },
{ name: "GLM-5-Turbo", multiplier: 3, offPeakMultiplier: 1, note: "Pro/Max可用,高峰期3倍,非高峰期2倍(限时1倍至9月底)。调用GLM-5/5.1将自动切换至GLM-5.2" },
{ name: "GLM-5.1", multiplier: 3, offPeakMultiplier: 1, note: "Pro/Max可用,高峰期3倍,非高峰期2倍(限时1倍至9月底)。调用GLM-5/5.1将自动切换至GLM-5.2" },
{ name: "GLM-5.2", multiplier: 3, offPeakMultiplier: 1, note: "Pro/Max可用,高峰期3倍,非高峰期2倍(限时1倍至9月底)" }
],
billingUnit: "prompts(1 prompt ≈ 15-20次模型调用)",
refreshRule: "每5小时滑动窗口、每周自下单时开启7天周期刷新",
peakHours: "每日14:00~18:00(UTC+8)",
pros: "GLM-5.2开源SOTA编程能力,MCP工具链完整,20+工具兼容。ZCode 3.0联合活动:订阅用户享1.5倍配额。",
cons: "涨价50%+,每日限量发售经常秒没,GLM-5/5.1高峰期3倍抵扣,算力紧张,稳定性差,存在封号风险"
},
{
id: "opencode", name: "OpenCode Go",
url: "https://opencode.ai/zh/go",
docsUrl: "https://opencode.ai/docs/go/",
tiers: [
{ name: "Go", price: 10, priceUnit: "USD", priceFirstMonth: 5, period: "月",
limits: { per5h: 12, perWeek: 30, perMonth: 60 }, limitUnit: "USD",
notes: "首月$5,之后$10/月。按等价用量($)限制。每5小时$12、每周$30、每月$60。MiMo-V2.5和DeepSeek-V4-Flash接近小无限。" }
],
models: Object.keys(OPCODE_TOKEN_PRICING).map(name => ({ name, tokenPricing: OPCODE_TOKEN_PRICING[name] })),
billingUnit: "等价用量 ($) — 按 Token 计费",
refreshRule: "每5小时$12、每周$30、每月$60",
tokenPricingNote: "Qwen3.7 Plus / Qwen3.6 Plus 分档定价:≤256K tokens 和 >256K tokens 价格不同,上表为≤256K价格。",
pros: "体验最好,速度和稳定性都还行,上游多为官方,MiMo-V2.5和DeepSeek-V4-Flash接近小无限",
cons: "GLM-5.1/Kimi-K2.6可用量较少,大部分差评集中在这两个模型"
}
];
let usageData = [];

document.addEventListener('DOMContentLoaded', () => {
renderPlatforms();
addUsageRow();
setupTabs();
});

function setupTabs() {
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
btn.classList.add('active');
document.getElementById(btn.dataset.tab).classList.add('active');
});
});
}

function toggleOptionStyle(checkbox) {
const label = checkbox.closest('.calc-option');
if (checkbox.checked) label.classList.add('active');
else label.classList.remove('active');
}

function renderPlatforms() {
const grid = document.getElementById('platformsGrid');
grid.innerHTML = PLATFORMS.map(p => {
const allModels = p.models.map(m => {
let extra = '';
if (m.multiplier) {
extra = '×' + m.multiplier;
if (m.offPeakMultiplier) extra += '(高峰)/' + m.offPeakMultiplier + '(低峰)';
} else if (m.tokenPricing) {
extra = '$' + m.tokenPricing.input + '/1M-in';
}
let note = m.note ? '<span class="note">(' + m.note + ')</span>' : '';
const deprecatedClass = m.note && m.note.includes('即将下线') ? 'deprecated' : '';
const toolOnlyClass = m.toolOnly ? 'tool-only' : '';
return '<span class="model-tag ' + deprecatedClass + ' ' + toolOnlyClass + '">' + m.name + '<span class="multiplier">' + extra + '</span>' + note + '</span>';
}).join('');
const badges = [];
badges.push('<span class="platform-tag">' + p.billingUnit + '</span>');
if (p.loginRequired) badges.push('<span class="platform-tag danger">🔒 需登录查看</span>');
if (p.id === 'opencode') badges.push('<span class="platform-tag info">💰 按Token计费</span>');
if (p.dataVerified === false) badges.push('<span class="platform-tag warn">⚠️ 数据待确认</span>');
const tiers = p.tiers.map(t => {
const limits = [];
if (t.limits.per5h !== null) limits.push('<span class="limit-item">5h: ' + (t.limits.per5h === null ? '不限' : t.limits.per5h.toLocaleString()) + '</span>');
if (t.limits.perWeek !== null) limits.push('<span class="limit-item">周: ' + (t.limits.perWeek === null ? '不限' : t.limits.perWeek.toLocaleString()) + '</span>');
if (t.limits.perMonth !== null) limits.push('<span class="limit-item">月: ' + (t.limits.perMonth === null ? '不限' : t.limits.perMonth.toLocaleString()) + '</span>');
if (t.concurrency) limits.push('<span class="limit-item">并发: ' + t.concurrency + '</span>');
if (t.supportedModels) limits.push('<span class="limit-item" style="color:var(--warning)">限: ' + t.supportedModels.length + '个模型</span>');
let priceExtra = '';
if (t.priceFirstMonth) priceExtra += '<span class="first-month">首月 ' + (t.priceUnit === 'USD' ? '$' : '¥') + t.priceFirstMonth + '</span>';
if (t.priceQuarterly) priceExtra += '<span class="period-options"> | 季¥' + t.priceQuarterly + '</span>';
if (t.priceYearly) priceExtra += '<span class="period-options"> | 年¥' + t.priceYearly + '</span>';
if (t.mcpMonthly) priceExtra += '<span class="period-options"> | MCP月' + t.mcpMonthly + '次</span>';
const unit = t.priceUnit === 'USD' ? '$' : '¥';
return '<div class="tier-item"><span class="tier-name">' + t.name + '</span><span class="tier-price">' + unit + t.price + '/月 ' + priceExtra + '</span><span class="tier-limits">' + limits.join('') + '</span></div>';
}).join('');
let notesHtml = '';
if (p.notes) notesHtml = '<div class="notes">📋 ' + p.notes + '</div>';
if (p.refreshRule) notesHtml += '<div class="notes info">🔄 刷新规则: ' + p.refreshRule + '</div>';
if (p.peakHours) notesHtml += '<div class="notes warn">⏰ 高峰期: ' + p.peakHours + '</div>';
if (p.valleyFactor) notesHtml += '<div class="notes success">🌙 波谷优惠: ' + p.valleyFactor + '</div>';
if (p.multiplierNote) notesHtml += '<div class="multiplier-note">⚠️ ' + p.multiplierNote + '</div>';
if (p.tokenPricingNote) notesHtml += '<div class="multiplier-note">💡 ' + p.tokenPricingNote + '</div>';
return '<div class="platform-card"><div class="platform-header"><span class="platform-name">' + p.name + '</span><div class="platform-badges">' + badges.join('') + '</div></div><div><a href="' + p.url + '" target="_blank" class="platform-url">官网: ' + p.url + '</a>' + (p.docsUrl ? '<a href="' + p.docsUrl + '" target="_blank" class="docs-link">📄 文档</a>' : '') + '</div><div class="tier-list">' + tiers + '</div><div class="model-tags">' + allModels + '</div><div class="pros-cons"><div class="pro"><strong>✅ 优点</strong>' + p.pros + '</div><div class="con"><strong>❌ 缺点</strong>' + p.cons + '</div></div>' + notesHtml + '</div>';
}).join('');
}

function addUsageRow() {
const rows = document.getElementById('usageRows');
const idx = usageData.length;
usageData.push({ model: '', requests: '', inputTokens: '', outputTokens: '', cachedTokens: '' });
const allModels = [...new Set(PLATFORMS.flatMap(p => p.models.map(m => m.name)))];
const row = document.createElement('div');
row.className = 'usage-row';
row.innerHTML = '<div class="form-row"><div class="form-group"><label>模型</label><select id="model-' + idx + '" onchange="updateUsageData(' + idx + '); updateTokenHint(' + idx + ');"><option value="">选择模型...</option>' + allModels.map(m => '<option value="' + m + '">' + m + '</option>').join('') + '<option value="custom">➕ 自定义模型</option></select><input type="text" id="custom-model-' + idx + '" placeholder="输入模型名" style="display:none;margin-top:8px;" onchange="updateUsageData(' + idx + ')"><div class="token-hint" id="token-hint-' + idx + '"></div></div><div class="form-group"><label>请求数 (次/月)</label><input type="number" id="requests-' + idx + '" placeholder="如: 5000" min="0" onchange="updateUsageData(' + idx + ')"></div><div class="form-group"><label>输入Token (可选)</label><input type="number" id="input-' + idx + '" placeholder="如: 100000" min="0" onchange="updateUsageData(' + idx + ')"></div><div class="form-group"><label>输出Token (可选)</label><input type="number" id="output-' + idx + '" placeholder="如: 50000" min="0" onchange="updateUsageData(' + idx + ')"></div><div class="form-group"><label>缓存Token (可选)</label><input type="number" id="cached-' + idx + '" placeholder="如: 20000" min="0" onchange="updateUsageData(' + idx + ')"></div><div class="form-group"><label>&nbsp;</label><button class="btn btn-danger" onclick="removeRow(' + idx + ')" style="padding:10px 14px;">🗑️</button></div></div>';
rows.appendChild(row);
const select = row.querySelector('#model-' + idx);
select.addEventListener('change', (e) => {
const customInput = row.querySelector('#custom-model-' + idx);
customInput.style.display = e.target.value === 'custom' ? 'block' : 'none';
});
}

function updateTokenHint(idx) {
const modelSelect = document.getElementById('model-' + idx);
const hint = document.getElementById('token-hint-' + idx);
const model = modelSelect.value;
if (OPCODE_DEFAULT_TOKENS[model]) {
const d = OPCODE_DEFAULT_TOKENS[model];
hint.innerHTML = '💡 OpenCode Go 预估: 输入' + d.input.toLocaleString() + ' / 缓存' + d.cached.toLocaleString() + ' / 输出' + d.output.toLocaleString() + ' tokens/请求';
} else {
hint.innerHTML = '';
}
}

function updateUsageData(idx) {
const modelSelect = document.getElementById('model-' + idx);
const customModel = document.getElementById('custom-model-' + idx);
usageData[idx] = {
model: modelSelect.value === 'custom' ? customModel.value : modelSelect.value,
requests: parseInt(document.getElementById('requests-' + idx).value) || 0,
inputTokens: parseInt(document.getElementById('input-' + idx).value) || 0,
outputTokens: parseInt(document.getElementById('output-' + idx).value) || 0,
cachedTokens: parseInt(document.getElementById('cached-' + idx).value) || 0
};
}

function removeRow(idx) {
const rows = document.getElementById('usageRows');
const rowEls = rows.querySelectorAll('.usage-row');
if (rowEls[idx]) {
rowEls[idx].remove();
usageData.splice(idx, 1);
const remaining = rows.querySelectorAll('.usage-row');
remaining.forEach((el, i) => {
el.querySelectorAll('[id]').forEach(input => {
const base = input.id.replace(/-\d+$/, '');
input.id = base + '-' + i;
if (input.tagName === 'SELECT') {
input.setAttribute('onchange', 'updateUsageData(' + i + '); updateTokenHint(' + i + ');');
} else if (input.type === 'number' || input.type === 'text') {
input.setAttribute('onchange', 'updateUsageData(' + i + ')');
}
});
const btn = el.querySelector('.btn-danger');
if (btn) btn.setAttribute('onclick', 'removeRow(' + i + ')');
});
}
}

function clearAll() {
usageData = [];
document.getElementById('usageRows').innerHTML = '';
document.getElementById('resultsSection').style.display = 'none';
document.getElementById('emptyState').style.display = 'block';
addUsageRow();
}

function calculateOpenCodeCost(model, requests, inputTokens, outputTokens, cachedTokens) {
const pricing = OPCODE_TOKEN_PRICING[model];
if (!pricing) {
return { cost: requests * 0.01, method: 'unknown-model-default', detail: { input: 0, output: 0, cached: 0, cost: requests * 0.01 } };
}
let totalInput = 0, totalOutput = 0, totalCached = 0;
let method = '';
const hasInput = inputTokens > 0;
const hasOutput = outputTokens > 0;
const hasCached = cachedTokens > 0;
const hasAnyToken = hasInput || hasOutput || hasCached;
if (hasAnyToken) {
const defaults = OPCODE_DEFAULT_TOKENS[model];
totalInput = hasInput ? inputTokens : (defaults ? defaults.input * requests : 0);
totalOutput = hasOutput ? outputTokens : (defaults ? defaults.output * requests : 0);
totalCached = hasCached ? cachedTokens : (defaults ? defaults.cached * requests : 0);
method = 'user-token-with-defaults';
} else {
const defaults = OPCODE_DEFAULT_TOKENS[model];
if (defaults) {
totalInput = defaults.input * requests;
totalOutput = defaults.output * requests;
totalCached = defaults.cached * requests;
method = 'default-tokens-per-request';
} else {
return { cost: requests * 0.01, method: 'no-default-fallback', detail: { input: 0, output: 0, cached: 0, cost: requests * 0.01 } };
}
}
const inputCost = (totalInput / 1000000) * pricing.input;
const outputCost = (totalOutput / 1000000) * pricing.output;
const cachedCost = (totalCached / 1000000) * (pricing.cachedRead || 0);
const totalCost = inputCost + outputCost + cachedCost;
return { cost: totalCost, method: method, detail: { input: totalInput, output: totalOutput, cached: totalCached, inputCost: inputCost, outputCost: outputCost, cachedCost: cachedCost, cost: totalCost } };
}

// ===== 计算单账号消耗 =====
function calculateSingleAccount(platform, tier, usageData) {
const onPeakMode = document.getElementById('onPeakCheck').checked;
const offPeakMode = document.getElementById('offPeakCheck').checked;

let totalEffective = 0;
let totalRequests = 0;
let detailBreakdown = [];
let overLimit = false;
let limitReason = [];
let unsupportedModels = [];

usageData.forEach(usage => {
const modelInfo = platform.models.find(m => m.name === usage.model);
if (!modelInfo) {
overLimit = true;
limitReason.push(usage.model + ' 模型不支持');
unsupportedModels.push(usage.model);
} else if (modelInfo.toolOnly) {
detailBreakdown.push({
model: usage.model, requests: usage.requests, multiplier: null, offPeakMultiplier: null,
costDetail: null, method: 'tool-only', effective: 0, note: '工具调用,不计入套餐额度'
});
} else if (tier.supportedModels && !tier.supportedModels.includes(usage.model)) {
overLimit = true;
limitReason.push(usage.model + ' 不在 ' + tier.name + ' 支持列表中');
unsupportedModels.push(usage.model);
} else {
let effective = 0;
let costDetail = null;
let method = '';
if (platform.id === 'opencode') {
const result = calculateOpenCodeCost(usage.model, usage.requests, usage.inputTokens, usage.outputTokens, usage.cachedTokens);
effective = result.cost;
costDetail = result.detail;
method = result.method;
totalEffective += effective;
} else if (platform.id === 'glm') {
const multiplier = modelInfo ? (modelInfo.multiplier || 1) : 1;
let avgMultiplier = multiplier;
if (modelInfo && modelInfo.offPeakMultiplier) {
avgMultiplier = (modelInfo.multiplier + modelInfo.offPeakMultiplier) / 2;
if (onPeakMode) {
avgMultiplier = modelInfo.multiplier;
} else if (offPeakMode) {
avgMultiplier = modelInfo.offPeakMultiplier;
}
}
effective = Math.ceil(usage.requests / 18 * avgMultiplier);
totalEffective += effective;
} else if (modelInfo && modelInfo.offPeakMultiplier) {
const avgMultiplier = (modelInfo.multiplier + modelInfo.offPeakMultiplier) / 2;
if (onPeakMode) {
avgMultiplier = modelInfo.multiplier;
} else if (offPeakMode) {
avgMultiplier = modelInfo.offPeakMultiplier;
}
effective = Math.ceil(usage.requests * avgMultiplier);
totalEffective += effective;
} else {
const multiplier = modelInfo ? (modelInfo.multiplier || 1) : 1;
effective = Math.ceil(usage.requests * multiplier);
totalEffective += effective;
}
totalRequests += usage.requests;
detailBreakdown.push({
model: usage.model, requests: usage.requests, inputTokens: usage.inputTokens,
outputTokens: usage.outputTokens, cachedTokens: usage.cachedTokens,
multiplier: platform.id === 'opencode' ? null : (modelInfo ? (modelInfo.multiplier || 1) : 1),
offPeakMultiplier: modelInfo?.offPeakMultiplier || null,
costDetail: costDetail, method: method, effective: effective
});
}
});

// 检查是否超限
if (platform.id === 'opencode') {
if (tier.limits.perMonth && totalEffective > tier.limits.perMonth) {
overLimit = true;
limitReason.push('月限额 $' + tier.limits.perMonth + ',预估 $' + totalEffective.toFixed(4));
}
} else if (platform.id === 'glm') {
if (tier.limits.perWeek && totalEffective > tier.limits.perWeek * 4) {
overLimit = true;
limitReason.push('周限额约 ' + tier.limits.perWeek + ' prompts,预估月 ' + totalEffective + ' prompts');
}
} else {
if (tier.limits.perMonth !== null && totalEffective > tier.limits.perMonth) {
overLimit = true;
limitReason.push('月限额 ' + tier.limits.perMonth.toLocaleString() + ' 次,预估 ' + totalEffective.toLocaleString() + ' 次');
}
}

return {
totalEffective, totalRequests, detailBreakdown, overLimit,
limitReason: limitReason.join('; '), unsupportedModels
};
}

// ===== 主计算函数 =====
function calculate() {
const rows = document.querySelectorAll('.usage-row');
usageData = [];
rows.forEach((row, i) => {
const modelSelect = row.querySelector('#model-' + i);
const customModel = row.querySelector('#custom-model-' + i);
const model = modelSelect && modelSelect.value === 'custom'
? (customModel ? customModel.value : '')
: (modelSelect ? modelSelect.value : '');
const requests = parseInt(row.querySelector('#requests-' + i)?.value) || 0;
const inputTokens = parseInt(row.querySelector('#input-' + i)?.value) || 0;
const outputTokens = parseInt(row.querySelector('#output-' + i)?.value) || 0;
const cachedTokens = parseInt(row.querySelector('#cached-' + i)?.value) || 0;
if (model && requests > 0) {
usageData.push({ model, requests, inputTokens, outputTokens, cachedTokens });
}
});

if (usageData.length === 0) {
alert('请至少添加一个模型的使用情况(请求数 > 0)');
return;
}

const firstMonthMode = document.getElementById('firstMonthCheck').checked;
const multiAccountMode = document.getElementById('multiAccountCheck').checked;

const results = [];

PLATFORMS.forEach(platform => {
platform.tiers.forEach(tier => {
const single = calculateSingleAccount(platform, tier, usageData);

let accountCount = 1;
let totalPrice = tier.price;
let effectivePrice = tier.price;
let isOverLimit = single.overLimit;
let finalLimitReason = single.limitReason;

// 多账号模式:计算所需账号数
if (multiAccountMode && isOverLimit && single.unsupportedModels.length === 0) {
// 计算需要多少个账号才能满足需求
let monthlyLimit;
if (platform.id === 'opencode') {
monthlyLimit = tier.limits.perMonth || 60;
} else if (platform.id === 'glm') {
monthlyLimit = (tier.limits.perWeek || 0) * 4;
} else {
monthlyLimit = tier.limits.perMonth || 0;
}

if (monthlyLimit > 0 && single.totalEffective > 0) {
accountCount = Math.ceil(single.totalEffective / monthlyLimit);
if (accountCount < 1) accountCount = 1;
totalPrice = (tier.price * accountCount).toFixed(1);
isOverLimit = false; // 多账号后不再超限
finalLimitReason = '';
}
}

// 首月优惠模式:使用首月价格
if (firstMonthMode && tier.priceFirstMonth) {
effectivePrice = tier.priceFirstMonth;
totalPrice = (effectivePrice * accountCount).toFixed(1);
}

// 计算性价比分
let valueScore = 0;
if (!isOverLimit) {
const priceForScore = totalPrice;
const usdRate = tier.priceUnit === 'USD' ? 7 : 1;
const cnyPrice = priceForScore * usdRate;
if (platform.id === 'opencode') {
const monthlyLimit = tier.limits.perMonth || 60;
valueScore = (monthlyLimit * accountCount / cnyPrice);
} else if (platform.id === 'glm') {
const monthlyLimit = (tier.limits.perWeek || 0) * 4 * accountCount;
valueScore = monthlyLimit / cnyPrice;
} else {
const monthlyLimit = (tier.limits.perMonth || 0) * accountCount;
valueScore = monthlyLimit / cnyPrice;
}
}

results.push({
platform: platform.name,
platformId: platform.id,
tier: tier.name,
price: tier.price,
priceUnit: tier.priceUnit || 'CNY',
priceFirstMonth: tier.priceFirstMonth,
effectivePrice: effectivePrice,
totalPrice: totalPrice,
accountCount: accountCount,
totalEffective: single.totalEffective,
totalRequests: single.totalRequests,
overLimit: isOverLimit,
limitReason: finalLimitReason,
valueScore: isOverLimit ? -9999 : valueScore,
detailBreakdown: single.detailBreakdown,
billingUnit: platform.billingUnit,
firstMonthMode: firstMonthMode,
multiAccountMode: multiAccountMode
});
});
});

// 排序:先按是否超限,再按总价(考虑汇率)
results.sort((a, b) => {
if (a.overLimit !== b.overLimit) return a.overLimit ? 1 : -1;
const aPrice = a.totalPrice * (a.priceUnit === 'USD' ? 7 : 1);
const bPrice = b.totalPrice * (b.priceUnit === 'USD' ? 7 : 1);
return aPrice - bPrice;
});

renderResults(results);
}

function renderResults(results) {
document.getElementById('emptyState').style.display = 'none';
document.getElementById('resultsSection').style.display = 'block';

const validResults = results.filter(r => !r.overLimit);
const multiAccountCount = results.filter(r => r.accountCount > 1).length;
const firstMonthCount = results.filter(r => r.firstMonthMode && r.priceFirstMonth).length;

const summaryCards = document.getElementById('summaryCards');
let summaryHtml =
'<div class="summary-card"><div class="value">' + results.length + '</div><div class="label">对比方案数</div></div>' +
'<div class="summary-card"><div class="value" style="color:var(--success)">' + validResults.length + '</div><div class="label">可用方案</div></div>' +
'<div class="summary-card"><div class="value" style="color:var(--danger)">' + (results.length - validResults.length) + '</div><div class="label">超限方案</div></div>' +
'<div class="summary-card"><div class="value" style="color:var(--warning)">' + (validResults.length > 0 ? (validResults[0].priceUnit === 'USD' ? '$' : '¥') + validResults[0].totalPrice : '-') + '</div><div class="label">最低月费</div></div>';

if (multiAccountCount > 0) {
summaryHtml += '<div class="summary-card"><div class="value" style="color:var(--accent-light)">' + multiAccountCount + '</div><div class="label">需多账号方案</div></div>';
}
if (firstMonthCount > 0) {
summaryHtml += '<div class="summary-card"><div class="value" style="color:var(--warning)">' + firstMonthCount + '</div><div class="label">含首月优惠</div></div>';
}
summaryCards.innerHTML = summaryHtml;

const tbody = document.getElementById('resultsBody');
tbody.innerHTML = results.map((r, i) => {
const rankClass = i < 3 ? 'rank-' + (i + 1) : '';
const recommendClass = !r.overLimit && i < 3 ? 'recommend' : (r.overLimit ? 'not-recommend' : '');
const unit = r.priceUnit === 'USD' ? '$' : '¥';
let price = r.price;

// 月费显示逻辑
let priceStr = unit + r.price + '/月';
if (r.accountCount > 1) {
priceStr = unit + r.totalPrice + '/月' + '<span class="multi-account-badge">' + r.accountCount + '账号</span>';
}
if (r.firstMonthMode && r.priceFirstMonth) {
price = r.priceFirstMonth;
priceStr += '<span class="first-month-badge">首月' + unit + r.priceFirstMonth + '</span>';
}
if (r.accountCount > 1) {
priceStr += '<div style="font-size:0.75rem;color:var(--text-dim);margin-top:2px;">单价 ' + unit + price + ' × ' + r.accountCount + ' = ' + unit + r.totalPrice + '</div>';
}

let consumeStr;
if (r.platformId === 'opencode') {
const limit = r.accountCount > 1 ? (60 * r.accountCount) : 60;
consumeStr = '$' + r.totalEffective.toFixed(4) + ' / $' + limit;
} else if (r.platformId === 'glm') {
const limit = r.accountCount > 1 ? (r.price === 49 ? 400 * 4 * r.accountCount : r.price === 149 ? 2000 * 4 * r.accountCount : 8000 * 4 * r.accountCount) : (r.price === 49 ? 1600 : r.price === 149 ? 8000 : 32000);
consumeStr = r.totalEffective.toLocaleString() + ' prompts / 月限约' + limit.toLocaleString() + ' prompts';
} else {
const limit = r.accountCount > 1 ? '多账号' : '单账号';
consumeStr = r.totalEffective.toLocaleString() + ' 次';
}

return '<tr class="' + recommendClass + '">' +
'<td class="rank ' + rankClass + '">#' + (i + 1) + '</td>' +
'<td><strong>' + r.platform + '</strong></td>' +
'<td>' + r.tier + '</td>' +
'<td>' + priceStr + '</td>' +
'<td>' + consumeStr + '</td>' +
'<td class="' + (r.overLimit ? 'over-limit' : 'within-limit') + '">' + (r.overLimit ? '⚠️ 超限' : '✅ 可用') + '</td>' +
'<td>' + (r.overLimit ? '-' : (r.valueScore > 0 ? '⭐ 推荐' : '一般')) + '</td>' +
'<td><button class="detail-btn" onclick="toggleDetail(' + i + ')">详情</button></td>' +
'</tr>' +
'<tr>' +
'<td colspan="8" style="padding:0;border:none;">' +
'<div class="detail-panel" id="detail-' + i + '">' +
'<table>' +
'<tr><td>计费单位</td><td>' + r.billingUnit + '</td></tr>' +
'<tr><td>预估总请求</td><td>' + r.totalRequests.toLocaleString() + ' 次</td></tr>' +
(r.accountCount > 1 ? '<tr><td>账号数量</td><td><span class="multi-account-badge">' + r.accountCount + ' 个账号</span>(同套餐多账号模式)</td></tr>' : '') +
(r.firstMonthMode && r.priceFirstMonth ? '<tr><td>首月优惠</td><td><span class="first-month-badge">首月 ' + unit + r.priceFirstMonth + '</span>(原价 ' + unit + r.price + ')</td></tr>' : '') +
(r.overLimit ? '<tr><td>超限原因</td><td style="color:var(--danger)">' + r.limitReason + '</td></tr>' : '') +
'<tr><td>模型消耗明细</td><td>' +
'<table style="margin-top:8px;">' +
'<tr style="color:var(--text-dim);font-size:0.8rem;">' +
'<td>模型</td><td>请求数</td>' +
(r.platformId === 'opencode'
? '<td>输入Token</td><td>输出Token</td><td>缓存Token</td><td>费用</td>'
: '<td>倍率</td><td>折算消耗</td>') +
'</tr>' +
r.detailBreakdown.map(d => {
if (d.method === 'tool-only') {
return '<tr><td>' + d.model + '</td><td>' + d.requests.toLocaleString() + '</td><td colspan="4" style="color:var(--text-dim)">🔧 ' + d.note + '</td></tr>';
}
if (r.platformId === 'opencode') {
const cd = d.costDetail;
let tokenInfo = '';
if (cd) {
tokenInfo = '<td>' + cd.input.toLocaleString() + '</td><td>' + cd.output.toLocaleString() + '</td><td>' + cd.cached.toLocaleString() + '</td><td>$' + cd.cost.toFixed(4) + '</td>';
} else {
tokenInfo = '<td>-</td><td>-</td><td>-</td><td>$' + d.effective.toFixed(4) + '</td>';
}
return '<tr><td>' + d.model + '</td><td>' + d.requests.toLocaleString() + '</td>' + tokenInfo + '</tr>';
} else {
let multiplierStr = '×' + d.multiplier;
if (d.offPeakMultiplier) multiplierStr += ' (高峰)/' + d.offPeakMultiplier + ' (低峰)';
return '<tr><td>' + d.model + '</td><td>' + d.requests.toLocaleString() + '</td><td>' + multiplierStr + '</td><td>' + d.effective.toLocaleString() + '</td></tr>';
}
}).join('') +
'</table>' +
'</td></tr>' +
'</table>' +
'</div>' +
'</td>' +
'</tr>';
}).join('');

document.getElementById('resultsSection').scrollIntoView({ behavior: 'smooth' });
}

function toggleDetail(idx) {
const panel = document.getElementById('detail-' + idx);
panel.classList.toggle('show');
}
</script>
</body>
</html>

希望也能帮助到佬友,数据与逻辑可能有误,发现问题可以反馈以下哈。

最新回复 (6)
  • JOJOBA 楼主 06-24 22:32
    1

    其他佬友的一些相关盘点也记录一下在这里



    GLM-5.2 都发布 10 天了我还没抢到 Coding Plan,我已急哭……不过好消息是它是开源的,目前市面上已有多种第三方渠道接入。以下盘点截至目前 GLM-5.2 的可用渠道(包含我已实测的和道听途说的)。
    省流:付费订阅 OpenCode Go 综合最佳;免费尝鲜可以选官方 ZCode 或 阿里云百炼。
    注:如果怀疑渠道掺水,安全边界也不失为一个检查的好办法。但注意即便是没有内容审…



    最近顺手整理了一下,目前一些能直接买到、并且包含 GLM-5.1 的 Coding Plan。
    因为我是刚手动整理的,个别平台的模型信息如果和别人的表格有差异,这里先按我自己整理到的内容写,欢迎大家补充纠正。
    我主要是从“模型实用性、倍率、限流、速度、整体体验”几个角度简单看了一下,给同样在找备用套餐的人做个参考。

    平台
    包含模型
    我的体验/了解
    简单评价

    火山方舟 Codi…
  • 地瓜 06-24 22:41
    2

    联通云gg了,发公告取消codingplan了

  • JOJOBA 楼主 06-24 22:58
    3

    联通云gg



    的确 ^-^ 在控制台那里订阅不了Coding Plan,显示“已售罄”

  • JOJOBA 楼主 06-25 08:19
    5

    主要收集整理了各渠道套餐订阅信息和藏在文档里的细节信息,实际体验如何,可以去看看社区反馈哈

  • 大风 06-25 08:52
    6

    联通云连续订的都作废了,可能现在发现把GPU租给智谱比自己搭模型更赚钱。

  • 大风 06-25 08:56
    7

    看起来不够直观啊,建议左侧二维表格,带筛选条件。可以各大卖电脑网站那种筛选比对的模式。

* 帖子来源Linux.do
返回