v0.6.2: 仪表盘布局重构 + 每日趋势折线图 + OpenCode Go/Zen 预设

仪表盘:
- 新增每日用量趋势折线图(Token/缓存命中率/请求数三线)
- 用量趋势 Tab 组(每日/模型/供应商模型)与模型表格同行等高
- 热力图独立整行,格子放大 16px
- 折线图坐标轴文字改 HTML 覆盖层(修复 SVG 拉伸变形)
- 表格 border-collapse + 行线与边框同色
- 模型表格估算标签行内显示(行高统一)
- 最近请求容器 max-h 限制
- 页脚归属放内容流末尾

模型唯一性:
- 获取模型列表时自动勾选已存在模型 + 已添加徽章
- 批量添加跳过同供应商已存在 model id
- onBulkAdd 同供应商 model id 去重

新增预设:
- OpenCode Go(套餐 subscription,带推荐链接)
- OpenCode Zen(按量 pay_as_you_go)

折线图优化:
- 缓存命中率 0-1 映射修复
- 请求数默认显示
- 直线连接 + 渐变填充
This commit is contained in:
KimiSwitch Dev committed 2026-07-30 11:50:05 +08:00
1 parent 2614f80d0f
commit bee981aefa
13 files changed
+739 -95

No files matched your search

+13 -2
View File
@@ -459,6 +459,9 @@ function ModelMapping({
provider,
});
setDiscovered(result);
// Auto-select models that already exist in the current provider's list
const existingIds = new Set(models.filter((m) => m.model).map((m) => m.model));
setSelected(new Set(result.filter((dm) => existingIds.has(dm.id)).map((dm) => dm.id)));
} catch (err) {
setDiscoverError(err instanceof Error ? err.message : String(err));
} finally {
@@ -477,9 +480,11 @@ function ModelMapping({
const handleAddSelected = () => {
if (!discovered || selected.size === 0) return;
const existingIds = new Set(models.filter((m) => m.model).map((m) => m.model));
const toAdd: Model[] = [];
for (const dm of discovered) {
if (!selected.has(dm.id)) continue;
if (existingIds.has(dm.id)) continue; // skip models already in this provider
const safeProvider = provider.name.replace(/\//g, "-");
const safeModelId = dm.id.replace(/\//g, "-");
const alias = `${safeProvider}/${safeModelId}`;
@@ -555,7 +560,9 @@ function ModelMapping({
{t("fetchEnableThinking")}
</label>
<div className="max-h-48 overflow-auto space-y-1">
{discovered.map((m) => (
{discovered.map((m) => {
const exists = models.some((mm) => mm.model === m.id);
return (
<label
key={m.id}
className="flex items-center gap-2 text-sm cursor-pointer hover:bg-input p-1.5 rounded"
@@ -569,8 +576,12 @@ function ModelMapping({
{m.display_name && (
<span className="text-content-muted">({m.display_name})</span>
)}
{exists && (
<span className="ml-auto text-[10px] text-emerald-500 shrink-0">{t("alreadyAdded")}</span>
)}
</label>
))}
);
})}
</div>
<button
type="button"