feat: 对话列表显示总数,SOUL 编辑区高度自适应收敛

- 新增 POST /threads/count:与 /threads/search 同一套过滤(标题搜索、
  系统会话排除),仅返回 {total};ThreadMetaStore 增加 count 方法
  (SQL 走 COUNT(*),JSON 过滤分批扫描计数)
- 对话页面搜索框下常驻显示「共 N 条对话」,分页条显示 当前页/总页数
  (useThreadsCount,仅随筛选条件变化,翻页不重复请求)
- 智能体右侧 SOUL 预览改为 40vh 上限自适应展开(不再全部展开);
  详情面板/卡片编辑/创建页的 SOUL 输入框统一为适中高度 + 可拖拽

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Fable 5 committed 2026-06-11 20:26:44 +08:00
1 parent f107ebc46d
commit 3d6f35391e
10 files changed
+204 -8

No files matched your search

+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>