diff --git a/web/src/app/(main)/function/tasks/detail/_tabs/sessions-tab.tsx b/web/src/app/(main)/function/tasks/detail/_tabs/sessions-tab.tsx index bf8eea9..937b97e 100644 --- a/web/src/app/(main)/function/tasks/detail/_tabs/sessions-tab.tsx +++ b/web/src/app/(main)/function/tasks/detail/_tabs/sessions-tab.tsx @@ -5,6 +5,7 @@ import * as React from "react"; import { ArrowUpIcon, BrainIcon, + ChevronDownIcon, CircleCheckIcon, CircleSlashIcon, CircleXIcon, @@ -473,6 +474,10 @@ function WorkerAssetBadge({ assets }: { assets: IntentAsset[] }) { export function SessionsTab({ taskId }: { taskId: string }) { const [activeId, setActiveId] = React.useState(MAIN_ID); + // 手机端(). const [store, setStore] = React.useState({}); // Worker sessions derived from exploration intents (paged past the old 300 cap). @@ -1130,6 +1135,13 @@ export function SessionsTab({ taskId }: { taskId: string }) { const isSystem = active.role === "system"; const activeKey = keyForSession(active); const activeState = store[activeKey]; + // 折叠态(手机端)标题栏要替代整张列表:显示当前会话名 + 其它会话的未读合计, + // 否则收起后既不知道自己在看哪个会话,也看不到别处有新消息。 + const activeDisplayTitle = (active.role === "worker" ? sessionMeta.get(active.id)?.title : "") || active.title; + const hiddenUnread = React.useMemo( + () => Object.entries(store).reduce((sum, [key, s]) => (key === activeKey ? sum : sum + s.unread), 0), + [store, activeKey], + ); // Keep the SSE dispatcher's notion of the active session current, and lazily load // + clear unread whenever the active session changes. @@ -1350,12 +1362,44 @@ export function SessionsTab({ taskId }: { taskId: string }) { return ( -
+ {/* 高度预留:页面头部(标题行 + 目标 + Tabs ≈ 7.5rem)+ 内容内边距。手机端 p-4、 + 桌面端 lg:p-6,且桌面还要留出滚动余量,所以两档分别预留 10rem / 13rem —— 手机端 + 沿用 13rem 会白白吃掉 3rem 的记录高度。 */} +
{/* Left: session list */} -
+
-
-
会话列表
+
+ {!MOCK && ( )}
- + div]:block!", + !listOpen && "max-lg:hidden", + )} + >
{(["mainagent", "planner", "system", "worker"] as const).map((role) => { const items = grouped[role]; @@ -1421,7 +1472,10 @@ export function SessionsTab({ taskId }: { taskId: string }) { displayTitle={meta?.title ?? s.title} hasPending={hasPendingForSession(s)} unread={store[keyForSession(s)]?.unread} - onClick={() => setActiveId(s.id)} + onClick={() => { + setActiveId(s.id); + setListOpen(false); // 手机端选完即收起,把高度还给会话记录 + }} controlling={controllingIntent === s.intent_id} deleted={meta?.deleted} onPause={() => void controlWorker(s, "pause")} @@ -1459,7 +1513,7 @@ export function SessionsTab({ taskId }: { taskId: string }) { {/* Right: transcript */}
-
+
{(() => { const isWorker = active.role === "worker"; const meta = isWorker ? sessionMeta.get(active.id) : undefined; @@ -1518,8 +1572,24 @@ export function SessionsTab({ taskId }: { taskId: string }) {
{tokenTotal.any && ( + {/* 手机端用短标签(入/缓/出):长标签会把这一行撑成两行,进一步压缩记录区。 */} - + + + + 输入 {activeTokens.input_tokens.toLocaleString()} · 输出{" "}