feat(portal): add logical group usage guidance

This commit is contained in:
phamnazage-jpg
2026-05-30 10:26:53 +08:00
parent 939dd4f8e1
commit 037e141cc4
2 changed files with 143 additions and 0 deletions

View File

@@ -498,6 +498,36 @@
font-size: 12px;
line-height: 1.7;
}
.guide-grid {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.guide-card {
padding: 16px;
border-radius: 20px;
border: 1px solid rgba(215, 201, 177, 0.92);
background: rgba(255, 255, 255, 0.82);
}
.guide-card h4 {
margin: 0 0 8px;
font-size: 17px;
}
.guide-card .guide-copy {
margin: 0 0 10px;
color: var(--muted);
line-height: 1.65;
font-size: 13px;
}
.guide-card .guide-lines {
display: grid;
gap: 8px;
}
.guide-card .guide-line {
color: var(--muted);
font-size: 12px;
line-height: 1.6;
}
.toast {
position: fixed;
right: 20px;
@@ -624,6 +654,16 @@
<div id="entitlement-grid" class="group-grid"></div>
</article>
<article class="panel">
<div class="section-head">
<div>
<h2>使用建议与可用模型说明</h2>
<p>这里按逻辑分组给出推荐模型、适用场景、接入建议和下一步动作,让普通用户不需要理解宿主分组也能直接开始使用。</p>
</div>
</div>
<div id="guide-grid" class="guide-grid"></div>
</article>
<article class="panel">
<div class="section-head">
<div>
@@ -783,6 +823,32 @@
description: "适合 DeepSeek 官方 chat 路线需求。当前用户侧建议直接使用 deepseek-chat。"
}
};
const MODEL_GUIDANCE = {
"kimi-k2.6": {
scenario: "适合日常聊天、长上下文问答和轻量智能体使用。",
recommendation: "默认先从这条模型线开始验证接入是否通畅。"
},
"gpt-5.4": {
scenario: "适合高质量推理、复杂编排、代码辅助和更稳的通用对话。",
recommendation: "如果你已经开通对应权限,优先用它做主模型。"
},
"gpt-5.4-mini": {
scenario: "适合低成本试跑、轻量自动化和更高频的小请求。",
recommendation: "更适合作为低成本补充线路或快速压测模型。"
},
"MiniMax-M2.5-highspeed": {
scenario: "适合对速度敏感的 MiniMax 使用场景。",
recommendation: "优先做高速场景和批量调用验证。"
},
"MiniMax-M2.7-highspeed": {
scenario: "适合需要更强能力、同时仍关注速度的 MiniMax 场景。",
recommendation: "适合和 M2.5 做效果与时延对照。"
},
"deepseek-chat": {
scenario: "适合通用 DeepSeek Chat 入口与官方兼容场景。",
recommendation: "建议直接按公开模型名调用,不需要额外记宿主细节。"
}
};
const state = {
accessToken: "",
@@ -1183,6 +1249,74 @@
}).join("");
}
function buildGuideEntries() {
return logicalGroupEntitlementRows().map((row) => {
const group = row.logicalGroup;
const models = portalLogicalGroupModels(group);
const primaryModel = models[0] || "";
const guidance = MODEL_GUIDANCE[primaryModel] || {
scenario: "适合按该逻辑分组下的公开模型集合统一接入。",
recommendation: "建议先用列表中的第一个公开模型做连通性验证。"
};
const nextStep = row.stateKey === "active"
? "当前已具备订阅与权限,建议直接创建测试 Key 并使用推荐模型发起第一次请求。"
: row.stateKey === "granted"
? "当前已具备线路权限,但未发现活跃订阅;建议先确认订阅状态后再发起调用。"
: row.stateKey === "pending"
? "当前目录已公开,但你还没有对应兼容线路;建议联系管理员补开通后再申请 Key。"
: row.stateKey === "ambiguous"
? "当前逻辑分组命中多条兼容线路;建议等待管理员整理归属,避免申请到不确定线路。"
: "当前可先浏览模型目录与接入建议,待管理员发布兼容线路后再申请测试 Key。";
const compatibility = (row.candidates || []).map((candidate) => candidate.title).join(" / ") || "尚未建立兼容线路";
return {
title: group.display_name || group.logical_group_id || "未命名逻辑分组",
logicalGroupID: group.logical_group_id || "",
models,
stateText: row.stateText,
stateKey: row.stateKey,
scenario: guidance.scenario,
recommendation: guidance.recommendation,
nextStep,
compatibility,
stickyMode: group.sticky_mode || "conversation_preferred",
routePolicy: group.route_policy || "priority"
};
});
}
function renderUsageGuides() {
const grid = $("guide-grid");
const guides = buildGuideEntries();
if (!guides.length) {
grid.innerHTML = '<div class="empty">当前还没有可展示的逻辑分组使用建议。</div>';
return;
}
grid.innerHTML = guides.map((guide) => {
const badgeClass = guide.stateKey === "active"
? "active"
: guide.stateKey === "granted"
? "neutral"
: "pending";
return (
'<article class="guide-card">' +
'<div class="group-meta">' +
'<span class="badge strong ' + badgeClass + '">' + escapeHTML(guide.stateText) + '</span>' +
'<span class="badge mono">' + escapeHTML(guide.logicalGroupID) + '</span>' +
'</div>' +
'<h4>' + escapeHTML(guide.title) + '</h4>' +
'<p class="guide-copy">' + escapeHTML(guide.scenario) + '</p>' +
'<div class="guide-lines">' +
'<div class="guide-line"><strong>推荐模型:</strong><span class="mono">' + escapeHTML(guide.models.join(", ") || "--") + '</span></div>' +
'<div class="guide-line"><strong>接入建议:</strong>' + escapeHTML(guide.recommendation) + '</div>' +
'<div class="guide-line"><strong>下一步:</strong>' + escapeHTML(guide.nextStep) + '</div>' +
'<div class="guide-line"><strong>兼容线路:</strong>' + escapeHTML(guide.compatibility) + '</div>' +
'<div class="guide-line"><strong>路由策略:</strong><span class="mono">' + escapeHTML(guide.routePolicy) + '</span> / <span class="mono">' + escapeHTML(guide.stickyMode) + '</span></div>' +
'</div>' +
'</article>'
);
}).join("");
}
function getPresentationStatus(row) {
if ((row.enabledCandidates || []).length === 1) {
return { cls: "active", text: "可立即申请兼容 Key" };
@@ -1369,6 +1503,7 @@
renderSessionSummary();
renderGroupCatalog();
renderEntitlementView();
renderUsageGuides();
renderKeys();
}

View File

@@ -62,6 +62,14 @@ assert_contains_file "$HTML_FILE" "portalLogicalGroups"
assert_contains_file "$HTML_FILE" "LEGACY_GROUP_CATALOG"
assert_contains_file "$HTML_FILE" "逻辑分组权限"
assert_contains_file "$HTML_FILE" "renderEntitlementView"
assert_contains_file "$HTML_FILE" "使用建议与可用模型说明"
assert_contains_file "$HTML_FILE" "MODEL_GUIDANCE"
assert_contains_file "$HTML_FILE" "buildGuideEntries"
assert_contains_file "$HTML_FILE" "renderUsageGuides"
assert_contains_file "$HTML_FILE" "推荐模型"
assert_contains_file "$HTML_FILE" "接入建议"
assert_contains_file "$HTML_FILE" "下一步"
assert_contains_file "$HTML_FILE" "路由策略"
assert_contains_file "$HTML_FILE" "已开通订阅"
assert_contains_file "$HTML_FILE" "已授予权限"
assert_contains_file "$HTML_FILE" "归属待整理"