This commit is contained in:
董宏凯 committed 2026-06-12 14:10:08 +08:00
commit 728a4b1170
10 files changed
+204 -8

No files matched your search

@@ -921,7 +921,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
? "正在加载 SOUL.md..."
: "输入 SOUL.md 内容"
}
className="min-h-[40vh] resize-y font-mono text-xs"
className="max-h-[45vh] min-h-48 resize-y font-mono text-xs"
/>
</div>
<div className="space-y-2">
@@ -577,13 +577,13 @@ export function AgentDetailPanel({
setDraft({ ...draft, soul: e.currentTarget.value })
}
placeholder="输入 SOUL.md 内容"
className="min-h-[45vh] resize-y font-mono text-xs"
className="max-h-[45vh] min-h-48 resize-y font-mono text-xs"
/>
) : (
// No inner max-height: the SOUL text flows at full length and the
// panel body scrolls as a whole, instead of a small nested scroll
// box on an otherwise empty screen.
<p className="text-muted-foreground whitespace-pre-wrap text-sm leading-relaxed">
// Viewport-relative cap: the SOUL preview expands with the screen
// (taller than the old fixed 240px box) but never swallows the
// whole panel — long content still scrolls inside.
<p className="text-muted-foreground max-h-[40vh] overflow-y-auto whitespace-pre-wrap text-sm leading-relaxed">
{soulPreview}
</p>
)}
+41
View File
@@ -841,6 +841,47 @@ export function useThreadsPage(options: {
});
}
/**
* Total number of conversations matching the same filters as
* `useThreadsPage`, via the lightweight `/threads/count` endpoint — powers
* the "共 N 条 / X 页" display without fetching any rows. Depends only on the
* filters (not the page), so paging doesn't refire it.
*/
export function useThreadsCount(options: {
search?: string;
metadata?: Record<string, unknown>;
}) {
const normalizedSearch = options.search?.trim() ?? "";
return useQuery<number>({
queryKey: [
"threads",
"search",
"count",
normalizedSearch,
options.metadata ?? null,
],
queryFn: async () => {
const response = await apiFetch(
`${getLangGraphBaseURL()}/threads/count`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
metadata: options.metadata ?? {},
query: normalizedSearch || undefined,
}),
},
);
if (!response.ok) {
throw new Error("Failed to count conversations");
}
const data = (await response.json()) as { total: number };
return data.total;
},
refetchOnWindowFocus: false,
});
}
export function useDeleteThread() {
const queryClient = useQueryClient();
const apiClient = getAPIClient();
+17 -1
View File
@@ -22,6 +22,7 @@ import {
} from "@/components/workspace/workspace-container";
import { useI18n } from "@/core/i18n/hooks";
import {
useThreadsCount,
useThreadsPage,
useToggleThreadFavorite,
useToggleThreadPin,
@@ -90,6 +91,10 @@ export default function ChatsPage() {
search: debouncedSearch,
metadata: pinnedFilter,
});
const { data: totalCount } = useThreadsCount({
search: debouncedSearch,
metadata: favoriteFilter,
});
const pinnedThreads = pinnedData?.threads ?? [];
const pagedThreads = useMemo(
@@ -98,6 +103,10 @@ export default function ChatsPage() {
);
const currentPage = page;
const hasMore = pageData?.hasMore ?? false;
// Page windows are sliced over the raw (pinned-inclusive) row order, so the
// page count derives from the raw total as well.
const totalPages =
totalCount != null ? Math.max(1, Math.ceil(totalCount / PAGE_SIZE)) : null;
const renderThread = (thread: AgentThread) => {
const pinned = isThreadPinned(thread);
@@ -201,6 +210,11 @@ export default function ChatsPage() {
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
{totalCount != null && (
<div className="text-muted-foreground w-full max-w-(--container-width-md) text-right text-xs tabular-nums">
共 {totalCount} 条对话
</div>
)}
</header>
<main className="min-h-0 flex-1">
<ScrollArea className="size-full py-4">
@@ -231,7 +245,9 @@ export default function ChatsPage() {
{t.chats.prevPage}
</Button>
<span className="text-muted-foreground text-sm tabular-nums">
{currentPage}
{totalPages != null
? `${currentPage} / ${totalPages}`
: currentPage}
</span>
<Button
variant="outline"
+1 -1
View File
@@ -546,7 +546,7 @@ export default function NewAgentPage() {
placeholder="写下智能体的人设、边界、工作方式和输出要求"
value={soulInput}
onChange={(event) => setSoulInput(event.currentTarget.value)}
className="min-h-[45vh] resize-y overflow-y-auto font-mono text-xs"
className="max-h-[50vh] min-h-64 resize-y overflow-y-auto font-mono text-xs"
/>
</div>