From 77c1e7404fa24389c66148734e55a46a1fc8084a Mon Sep 17 00:00:00 2001 From: Lemon-miaow Date: Sun, 4 Oct 2026 12:56:46 +0800 Subject: [PATCH] fix(panel): refine login and lobby settings layout --- panel/src/i18n/resources/en-US/lobby.json | 9 +- panel/src/i18n/resources/zh-CN/lobby.json | 9 +- panel/src/lib/experience.ts | 2 +- panel/src/pages/admin/LobbyPage.tsx | 154 +++++++++++++++------- 4 files changed, 122 insertions(+), 52 deletions(-) diff --git a/panel/src/i18n/resources/en-US/lobby.json b/panel/src/i18n/resources/en-US/lobby.json index d48aac4..65ff7c2 100644 --- a/panel/src/i18n/resources/en-US/lobby.json +++ b/panel/src/i18n/resources/en-US/lobby.json @@ -81,5 +81,12 @@ "builder_running": "Start the lobby before changing builder access.", "discard_title": "Discard unsaved settings?", "discard_hint": "Switching spaces discards your edits. Cancel to save them first.", - "discard": "Discard & switch" + "discard": "Discard & switch", + "appearance_description": "Set the welcome message and server menu players see.", + "players_description": "Choose join behavior, game mode and player protection.", + "world_description": "Adjust time, weather and the lobby game rules.", + "loginBook_description": "Edit the guidance players see in the login book.", + "content_tools": "Content & maintenance", + "unsaved": "You have unsaved changes", + "apply_on_start": "Saved settings apply when this space starts" } diff --git a/panel/src/i18n/resources/zh-CN/lobby.json b/panel/src/i18n/resources/zh-CN/lobby.json index 625d04a..dad0de1 100644 --- a/panel/src/i18n/resources/zh-CN/lobby.json +++ b/panel/src/i18n/resources/zh-CN/lobby.json @@ -81,5 +81,12 @@ "builder_running": "请先启动大厅,才能修改建造权限。", "discard_title": "放弃未保存的设置?", "discard_hint": "切换空间会丢失本次编辑。可以取消后先保存。", - "discard": "放弃并切换" + "discard": "放弃并切换", + "appearance_description": "设置玩家加入时看到的欢迎信息与菜单。", + "players_description": "设置加入行为、游戏模式与玩家保护。", + "world_description": "调整大厅的时间、天气和游戏规则。", + "loginBook_description": "编辑玩家打开登录书时看到的引导内容。", + "content_tools": "内容与维护", + "unsaved": "有未保存的更改", + "apply_on_start": "保存的设置将在启动后生效" } diff --git a/panel/src/lib/experience.ts b/panel/src/lib/experience.ts index 8bd0ce4..f136d27 100644 --- a/panel/src/lib/experience.ts +++ b/panel/src/lib/experience.ts @@ -50,10 +50,10 @@ export const LOGIN_GROUPS: ExperienceGroup[] = [ { key: "bookTitle", value: "Felis Login" }, { key: "bookAuthor", value: "Felis" }, { key: "bookHeading", value: "Felis 登录 / Login" }, + { key: "loginTimeoutSeconds", value: 600, min: 30, max: 3600 }, { key: "bookAction", value: "▶ 点此打开登录页\n▶ Open login page", multiline: true }, { key: "bookHelp", value: "在系统浏览器中完成。\nUse your SYSTEM browser —\nnot WeChat / QQ (passkey\nwon't work there).", multiline: true }, { key: "openBook", value: true }, - { key: "loginTimeoutSeconds", value: 600, min: 30, max: 3600 }, ] }, ]; diff --git a/panel/src/pages/admin/LobbyPage.tsx b/panel/src/pages/admin/LobbyPage.tsx index 84f3494..2e267a3 100644 --- a/panel/src/pages/admin/LobbyPage.tsx +++ b/panel/src/pages/admin/LobbyPage.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { Link, useSearchParams } from "react-router-dom"; -import { DoorOpen, FolderOpen, Map, Package, Save, Shield, Terminal } from "lucide-react"; +import { BookOpen, ChevronRight, DoorOpen, FolderOpen, Globe, Map, MessageSquare, Package, Save, Shield, Sun, Terminal, type LucideIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; import { ConfirmDialog } from "@/components/ConfirmDialog"; import { PageHeader } from "@/components/PageHeader"; @@ -16,9 +16,17 @@ import { ErrorState, Loading } from "@/components/States"; import { InlineError, MessageLine } from "@/components/MessageLine"; import { api, humanizeError } from "@/lib/api"; import { joinAddress } from "@/lib/config"; +import { cn } from "@/lib/utils"; import { STATUS_POLL_FAST_MS, useAsync, useConfig, usePolling, useUnsavedGuard } from "@/lib/hooks"; import { experienceValid, LOGIN_GROUPS, LOBBY_GROUPS, readExperience, writeExperience, type Experience } from "@/lib/experience"; +const GROUP_ICONS: Record = { + appearance: MessageSquare, + players: Shield, + world: Sun, + loginBook: BookOpen, +}; + function ExperienceSettings({ name, stopped, onDirtyChange }: { name: string; stopped: boolean; onDirtyChange: (dirty: boolean) => void }) { const { t } = useTranslation("lobby"); const groups = name === "login" ? LOGIN_GROUPS : LOBBY_GROUPS; @@ -55,43 +63,66 @@ function ExperienceSettings({ name, stopped, onDirtyChange }: { name: string; st {!stopped &&

{t(name === "login" ? "stop_login" : "stop_lobby")}

} {stopped && query.loading && !draft && } {query.error != null && } - {draft && groups.map((group) => ( - - {t(group.key)} - - {group.fields.map((field) => { - const value = draft.values[field.key] ?? field.value; - const id = `experience-${field.key}`; - const set = (next: unknown) => setDraft({ ...draft, values: { ...draft.values, [field.key]: next } }); - if (typeof field.value === "boolean") return ( - - ); - return ( -
- - {field.choices ? ( - - ) : field.multiline ? ( -