diff --git a/frontend/src/components/pages/MobileCallPage.tsx b/frontend/src/components/pages/MobileCallPage.tsx index 0a0cb22..fb93be0 100644 --- a/frontend/src/components/pages/MobileCallPage.tsx +++ b/frontend/src/components/pages/MobileCallPage.tsx @@ -37,6 +37,7 @@ import { useVoicePreview, type ChatMessage, } from "@/hooks/use-voice-preview"; +import { assistantsApi } from "@/lib/api"; type CallView = "video" | "chat"; @@ -452,9 +453,25 @@ export function MobileCallPage({ assistantId }: { assistantId: string }) { selectCamera: changeCamera, } = camera; const [view, setView] = useState("chat"); + const [assistantName, setAssistantName] = useState(""); const connecting = status === "connecting"; const inCall = !callEnded && (connecting || status === "connected"); + useEffect(() => { + let cancelled = false; + void assistantsApi + .get(assistantId) + .then((assistant) => { + if (!cancelled) setAssistantName(assistant.name.trim()); + }) + .catch(() => { + if (!cancelled) setAssistantName(""); + }); + return () => { + cancelled = true; + }; + }, [assistantId]); + const startCall = useCallback(async () => { await connect({ visionEnabled: true, @@ -474,11 +491,6 @@ export function MobileCallPage({ assistantId }: { assistantId: string }) { [changeCamera, selectTransportCamera], ); - useEffect(() => { - void startCall(); - // 首次打开页面时自动发起通话;hooks 会在卸载时各自释放媒体资源。 - }, [startCall]); - const error = previewError || cameraError || photoCapture.error; return ( @@ -524,12 +536,20 @@ export function MobileCallPage({ assistantId }: { assistantId: string }) { ? "通话中" : connecting ? "正在连接…" - : "通话已结束"} + : status === "failed" + ? "连接失败" + : "等待开始"} {!inCall && (
-
+
+
+

AI 助手

+

+ {assistantName || "助手"} +

+
{error &&

{error}

}
@@ -547,26 +567,7 @@ export function MobileCallPage({ assistantId }: { assistantId: string }) { )} {inCall && ( -
- - +
{photoCapture.visible && ( +
+ +
+
)}
diff --git a/frontend/src/components/ui/data-list.tsx b/frontend/src/components/ui/data-list.tsx index e207cb8..3f7a12e 100644 --- a/frontend/src/components/ui/data-list.tsx +++ b/frontend/src/components/ui/data-list.tsx @@ -51,6 +51,28 @@ export type DataListProps = { pagination?: DataListPagination; }; +/** 页码或省略号。页数少时全部展示;多时固定首尾 + 当前附近,避免按钮撑破布局。 */ +type PageItem = number | "ellipsis"; + +function buildPageItems(current: number, total: number): PageItem[] { + if (total <= 7) { + return Array.from({ length: total }, (_, index) => index + 1); + } + + // 靠近开头: 1 2 3 4 5 … N + if (current <= 3) { + return [1, 2, 3, 4, 5, "ellipsis", total]; + } + + // 靠近结尾: 1 … N-4 N-3 N-2 N-1 N + if (current >= total - 2) { + return [1, "ellipsis", total - 4, total - 3, total - 2, total - 1, total]; + } + + // 中间: 1 … c-1 c c+1 … N + return [1, "ellipsis", current - 1, current, current + 1, "ellipsis", total]; +} + export function DataList({ columns, rows, @@ -151,7 +173,7 @@ export function DataList({
{pagination.summary}
-
+
- {Array.from({ length: pagination.totalPages }, (_, index) => index + 1).map( - (page) => ( - - ), + {buildPageItems(pagination.page, pagination.totalPages).map( + (item, index) => + item === "ellipsis" ? ( + + … + + ) : ( + + ), )}