diff --git a/deploy/tksea-portal/index.html b/deploy/tksea-portal/index.html
index cd5d06c1..259908de 100644
--- a/deploy/tksea-portal/index.html
+++ b/deploy/tksea-portal/index.html
@@ -593,7 +593,7 @@
' +
+ '' + escapeHTML(group.display_name || group.logicalGroupID || "未命名逻辑分组") + '
' +
+ '' +
+ '' + escapeHTML(row.stateText) + '' +
+ '兼容线路 ' + String(row.candidates.length) + '' +
+ '活跃订阅 ' + String(row.matchingActiveSubscriptions.length) + '' +
+ '已有 Key ' + String(row.matchingKeys.length) + '' +
+ '
' +
+ '公开模型:' + escapeHTML(models) + '
' +
+ '兼容宿主线路:' + escapeHTML(compatibilityNames) + '
' +
+ '最近到期时间:' + escapeHTML(formatDate(row.latestExpiresAt)) + '
' +
+ '权限解释:' + escapeHTML(
+ row.stateKey === "active"
+ ? "当前账号已具备订阅与兼容线路,可直接使用或继续申请测试 Key。"
+ : row.stateKey === "granted"
+ ? "当前账号已拿到兼容线路权限,但尚未检测到活跃订阅记录。"
+ : row.stateKey === "pending"
+ ? "当前逻辑分组还没有可直接使用的兼容线路,请联系管理员补开通。"
+ : row.stateKey === "ambiguous"
+ ? "当前逻辑分组命中多条兼容线路,权限归属仍待管理员整理。"
+ : "当前逻辑分组已公开,但还未绑定可直接使用的兼容线路。"
+ ) + '
' +
+ ''
+ );
+ }).join("");
+ }
+
function getPresentationStatus(row) {
if ((row.enabledCandidates || []).length === 1) {
return { cls: "active", text: "可立即申请兼容 Key" };
@@ -1083,8 +1199,10 @@
function renderSessionSummary() {
const sessionGrid = $("session-grid");
const user = state.user;
+ const entitlementRows = logicalGroupEntitlementRows();
+ const activeLogicalGroups = activeLogicalGroupNames();
$("enabled-groups-stat").textContent = String((state.portalLogicalGroups || []).length);
- $("subscriptions-stat").textContent = String(availableLegacyGroupIDs().size);
+ $("subscriptions-stat").textContent = String(entitlementRows.filter((row) => row.stateKey === "active" || row.stateKey === "granted").length);
if (!user) {
statusPill("warn", "未登录");
@@ -1107,6 +1225,7 @@
["状态", user.status || "--"],
["并发", user.concurrency ?? "--"],
["RPM 限制", user.rpm_limit ?? "--"],
+ ["逻辑分组权限", activeLogicalGroups.length ? activeLogicalGroups.join(" / ") : "当前未检测到已激活的逻辑分组权限"],
["兼容宿主分组", Array.isArray(user.allowed_groups) && user.allowed_groups.length ? user.allowed_groups.join(", ") : "由订阅/分组接口决定"],
["创建时间", formatDate(user.created_at)]
];
@@ -1249,6 +1368,7 @@
function renderAll() {
renderSessionSummary();
renderGroupCatalog();
+ renderEntitlementView();
renderKeys();
}
diff --git a/scripts/test/test_tksea_portal_assets.sh b/scripts/test/test_tksea_portal_assets.sh
index 5237da94..6ee011dd 100755
--- a/scripts/test/test_tksea_portal_assets.sh
+++ b/scripts/test/test_tksea_portal_assets.sh
@@ -50,7 +50,8 @@ assert_contains_file "$HTML_FILE" "copy-existing-key-btn"
assert_contains_file "$HTML_FILE" "已有 Key"
assert_contains_file "$HTML_FILE" "showToast"
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" "可立即申请兼容 Key"
assert_contains_file "$HTML_FILE" "需开通兼容线路"
assert_contains_file "$HTML_FILE" "目录已上线"
@@ -59,6 +60,11 @@ assert_contains_file "$HTML_FILE" "当前逻辑分组说明"
assert_contains_file "$HTML_FILE" "兼容宿主线路"
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" "已授予权限"
+assert_contains_file "$HTML_FILE" "归属待整理"
assert_contains_file "$HTML_FILE" "route_policy ="
assert_contains_file "$HTML_FILE" "gpt-5.4"
assert_contains_file "$HTML_FILE" "MiniMax-M2.7-highspeed"