diff --git a/src/components/ChatView.tsx b/src/components/ChatView.tsx index 06fba9e..dc72ee9 100644 --- a/src/components/ChatView.tsx +++ b/src/components/ChatView.tsx @@ -4,6 +4,7 @@ import { INSUFFICIENT_BALANCE_NOTICE } from '../hooks/useTKMindChat'; import type { CapabilityMap, PortalUser, SessionSummary } from '../types'; import { useNetworkStatus } from '../hooks/useNetworkStatus'; import { getSessionDisplayName } from '../utils/sessions'; +import { isH5OrWechatClient } from '../utils/wechat'; import { BalanceRing } from './BalanceRing'; import { HistorySidebar } from './HistorySidebar'; import { TKMindAvatar } from './TKMindAvatar'; @@ -24,6 +25,7 @@ function RecentSessionRail({ loadingMore, hasMore, chipWidth, + variant = 'inline', onSelect, onLoadMore, }: { @@ -34,6 +36,7 @@ function RecentSessionRail({ loadingMore: boolean; hasMore: boolean; chipWidth?: number | null; + variant?: 'inline' | 'floating'; onSelect: (session: SessionSummary) => void; onLoadMore: () => void; }) { @@ -91,12 +94,14 @@ function RecentSessionRail({ if (!loading && recentSessions.length === 0) return null; + const isFloating = variant === 'floating'; + return (
0 + !isFloating && chipWidth && chipWidth > 0 ? ({ ['--header-session-chip-width' as string]: `${chipWidth}px` }) : undefined } @@ -285,11 +290,6 @@ export function ChatView({ : pendingSessionTitle; const moreMenuItems = [ - { - id: 'new-session', - label: '新会话', - onClick: () => void handleNewSession(), - }, ...(onOpenAdmin ? [{ id: 'admin', label: '管理', onClick: () => onOpenAdmin() }] : []), @@ -298,8 +298,21 @@ export function ChatView({ : []), ]; + const useFloatingSessionRail = useMemo(() => isH5OrWechatClient(), []); + + const recentSessionRailProps = { + sessions, + activeSessionId: session?.id, + armedSessionId, + loading: sessionsLoading, + loadingMore: sessionsLoadingMore, + hasMore: sessionsHasMore, + onSelect: handleRecentSessionSelect, + onLoadMore: () => void loadMoreSessions(), + }; + return ( -
+
-
-
- - -
-
{user?.displayName ?? 'TKMind'}
-
- {isConnectingTitle ? : null} - {sessionTitle} +
+
+
+ + +
+
{user?.displayName ?? 'TKMind'}
+
+ {isConnectingTitle ? : null} + {sessionTitle} +
-
-
- void loadMoreSessions()} - /> +
+ {!useFloatingSessionRail && ( + + )} {typeof balanceCents === 'number' && ( )} openRecharge(false)} /> + {onOpenAdmin && ( )} - {user && } {onLogout && (
- void loadMoreSessions()} - /> + {!useFloatingSessionRail && ( + + )} {typeof balanceCents === 'number' && ( )} openRecharge(false)} /> + {onOpenSpace && (
+ {useFloatingSessionRail && ( + + )} +
{!online && (
网络已断开,请检查连接后重试
diff --git a/src/index.css b/src/index.css index 6489626..2e4bfe7 100644 --- a/src/index.css +++ b/src/index.css @@ -645,6 +645,56 @@ body, background: rgba(255, 255, 255, 0.03); } +.header-shell-sticky { + position: sticky; + top: 0; + z-index: 2; +} + +.header-shell-sticky .header { + position: static; + top: auto; + z-index: auto; + border-bottom: none; +} + +.app-shell-h5 .header-session-rail-floating { + display: flex; + align-items: center; + gap: 0; + width: 100%; + max-width: none; + flex: none; + padding: 8px 12px; + box-sizing: border-box; + background: var(--color-bg-base); + border-bottom: 1px solid var(--color-border); + -webkit-overflow-scrolling: touch; +} + +.app-shell-h5 .header-shell-sticky:has(.header-home) .header-session-rail-floating { + background: rgba(12, 18, 30, 0.72); + backdrop-filter: blur(14px); + border-bottom-color: rgba(103, 123, 156, 0.18); +} + +.app-shell-h5 .header-session-rail-floating .header-session-rail-arrow { + display: none; +} + +.app-shell-h5 .header-session-rail-floating .header-session-rail-track { + --header-session-chip-width: calc((100% - 16px) / 3); + grid-auto-columns: calc((100% - 16px) / 3); + gap: 8px; + width: 100%; + touch-action: pan-x; +} + +.app-shell-h5 .header-session-rail-floating .header-session-chip { + min-height: 34px; + padding: 6px 8px; +} + .header-icon-btn { display: flex; align-items: center; diff --git a/src/utils/wechat.ts b/src/utils/wechat.ts index 449c2ea..5a0bc09 100644 --- a/src/utils/wechat.ts +++ b/src/utils/wechat.ts @@ -89,6 +89,15 @@ export function isWechatContext(options?: { return isWechatEntryUrl(options?.search); } +/** 手机 H5 或微信内置浏览器:导航会话标签采用下方悬浮条布局 */ +export function isH5OrWechatClient(options?: { + userAgent?: string; + search?: string; + serverInWechat?: boolean; +}) { + return isMobileBrowser(options?.userAgent) || isWechatContext(options); +} + export function buildWechatAuthorizeUrl(options?: { returnTo?: string; utmSource?: string;