Improve SCUM catalog readability

This commit is contained in:
npc0-hue
2026-09-24 20:46:43 +08:00
parent 7e0780ea51
commit 2f9b4b3780
4 changed files with 70 additions and 21 deletions
@@ -1448,6 +1448,16 @@ function catalogIconStrip(e: ReactLike["createElement"], icons: string[]) {
return icons.length ? e("span", { className: "scum-catalog-icons" }, icons.map((url, index) => e("img", { key: `${url}-${index}`, className: "scum-catalog-icon", src: url, alt: "" }))) : null;
}
function catalogCard(e: ReactLike["createElement"], view: ViewState, target: CatalogPickTarget, entry: ScumCatalogEntry) {
const icon = scumCatalogIconUrl(entry.icon);
const displayName = scumCatalogDisplayName(entry);
const sourceName = entry.name || entry.code;
return e("button", { key: entry.code, type: "button", className: "scum-catalog-card", title: `${displayName} · ${sourceName} · ${entry.code} · ${entry.command}`, onClick: () => target === "gift-items" ? view.setGiftItems((items) => appendCatalogItem(items, entry.code)) : view.setEventItems((items) => appendCatalogItem(items, entry.code)) },
e("span", { className: "scum-catalog-thumb" }, icon ? e("img", { src: icon, alt: "" }) : e("span", { className: "scum-catalog-thumb-empty", "aria-hidden": "true" }, "—")),
e("span", { className: "scum-catalog-meta" }, e("strong", null, displayName), e("span", { className: "scum-catalog-category" }, scumCatalogCategoryLabel(entry)), e("span", { className: "scum-catalog-source", title: sourceName }, sourceName), e("code", { className: "scum-catalog-code", title: entry.code }, entry.code))
);
}
function giftCatalogIcons(gift: RecordMap): string[] {
const items = field(gift, "items");
return Array.isArray(items) ? items.flatMap((item) => isRecord(item) ? catalogIconsForValue(textField(item, "catalogCode", "catalogItemKey", "key", "className")) : []).slice(0, 12) : [];
@@ -1458,11 +1468,11 @@ function catalogPicker(e: ReactLike["createElement"], view: ViewState, target: C
const activeFilter = filters.some(([key]) => key === view.catalogKind) ? view.catalogKind : "all";
const matches = catalogMatches(view.catalogSearch, activeFilter, target);
return e("details", { className: "console-module scum-editor scum-catalog-picker", open: view.catalogOpen, onToggle: (event: InputEvent) => view.setCatalogOpen(detailOpen(event)) },
e("summary", null, e("strong", null, target === "gift-items" ? "从 SCUM 目录选择礼包内容" : "从 SCUM 目录选择活动物品 / NPC"), e("span", { className: "page-status" }, "图标 / 名称 / 代码")),
e("summary", null, e("strong", null, target === "gift-items" ? "从 SCUM 目录选择礼包内容" : "从 SCUM 目录选择活动物品 / NPC"), e("span", { className: "page-status" }, `${matches.length} 个条目`)),
view.catalogOpen ? e("div", { className: "scum-catalog-picker-body" },
e("input", { type: "search", value: view.catalogSearch, "aria-label": target === "gift-items" ? "搜索礼包目录" : "搜索活动物品目录", placeholder: "中文名 / 英文名 / 代码,例如 莱卡", onChange: (event: InputEvent) => view.setCatalogSearch(inputValue(event)) }),
e("div", { className: "scum-catalog-kinds", role: "group", "aria-label": target === "gift-items" ? "礼包目录分类" : "活动目录分类" }, filters.map(([key, label]) => e("button", { key, type: "button", className: activeFilter === key ? "icon-command is-active" : "icon-command", "aria-pressed": activeFilter === key, onClick: () => view.setCatalogKind(key) }, label))),
e("div", { className: "scum-catalog-grid" }, matches.length ? matches.map((entry) => { const icon = scumCatalogIconUrl(entry.icon); const displayName = scumCatalogDisplayName(entry); return e("button", { key: entry.code, type: "button", className: "scum-catalog-chip", title: `${displayName} · ${scumCatalogCategoryLabel(entry)} · ${entry.command}`, onClick: () => target === "gift-items" ? view.setGiftItems((items) => appendCatalogItem(items, entry.code)) : view.setEventItems((items) => appendCatalogItem(items, entry.code)) }, icon ? e("img", { className: "scum-catalog-icon", src: icon, alt: "" }) : e("span", { className: "scum-catalog-icon scum-catalog-icon-empty" }), e("span", { className: "scum-catalog-meta" }, e("strong", null, displayName), e("span", { className: "provider-id" }, `${scumCatalogCategoryLabel(entry)} · ${entry.code}`))); }) : e("p", { className: "page-status" }, "没有匹配的目录条目。"))
e("div", { className: "scum-catalog-grid" }, matches.length ? matches.map((entry) => catalogCard(e, view, target, entry)) : e("p", { className: "page-status" }, "没有匹配的目录条目。"))
) : null
);
}
@@ -1486,7 +1496,7 @@ export function scumGiftCatalogCategory(entry: ScumCatalogEntry): string {
export function scumGiftCatalogFilterKey(entry: ScumCatalogEntry): string { return entry.kind === "item" ? scumGiftCatalogCategory(entry) : entry.kind; }
export function scumCatalogCategoryLabel(entry: ScumCatalogEntry): string { if (entry.kind === "vehicle") return "载具"; if (entry.kind === "animal") return "动物"; if (entry.kind === "zombie") return "丧尸"; if (entry.kind === "armed-npc") return "NPC"; return ({ hunting: "狩猎", food: "食物", metabolism: "代谢", medical: "医疗", weapons: "武器", crafting: "制作", gear: "装备", fishing: "钓鱼", building: "建筑", tools: "工具", farming: "农业", misc: "其他" } as Record<string, string>)[scumGiftCatalogCategory(entry)] ?? "其他"; }
export function scumCatalogCategoryLabel(entry: ScumCatalogEntry): string { if (entry.kind === "vehicle") return "载具"; if (entry.kind === "animal") return "动物"; if (entry.kind === "zombie") return "丧尸"; if (entry.kind === "armed-npc") return "非玩家角色"; return ({ hunting: "狩猎", food: "食物", metabolism: "代谢", medical: "医疗", weapons: "武器", crafting: "制作", gear: "装备", fishing: "钓鱼", building: "建筑", tools: "工具", farming: "农业", misc: "其他" } as Record<string, string>)[scumGiftCatalogCategory(entry)] ?? "其他"; }
function labeledField(e: ReactLike["createElement"], label: string, control: unknown) { return e("label", { className: "console-field" }, e("span", null, label), control); }
function detailOpen(event: InputEvent): boolean { return Boolean(event.target?.open); }
function giftTabButton(e: ReactLike["createElement"], view: ViewState, tab: GiftTab, label: string) { return e("button", { type: "button", role: "tab", "aria-selected": view.giftTab === tab, className: view.giftTab === tab ? "primary-command" : "icon-command", onClick: () => view.setGiftTab(tab) }, label); }