feat: 用自定义侧边栏替换聊天室 Conversations 组件,提取公共 SidebarGroup 和 date-group

This commit is contained in:
2026-06-04 00:46:57 +08:00
parent dc7d9e83b8
commit f67cfa84ef
18 changed files with 1042 additions and 262 deletions

View File

@@ -0,0 +1,28 @@
import { CaretDownOutlined, CaretRightOutlined } from "@ant-design/icons";
import { Typography } from "antd";
import { type ReactNode, useState } from "react";
interface SidebarGroupProps {
children: ReactNode;
count: number;
label: string;
}
export function SidebarGroup({ children, count, label }: SidebarGroupProps) {
const [collapsed, setCollapsed] = useState(false);
return (
<div className="app-sidebar-group">
<div className="app-sidebar-group-header" onClick={() => setCollapsed(!collapsed)}>
<span className="app-sidebar-group-arrow">{collapsed ? <CaretRightOutlined /> : <CaretDownOutlined />}</span>
<Typography.Text className="app-sidebar-group-label" type="secondary">
{label}
</Typography.Text>
<Typography.Text className="app-sidebar-group-count" type="secondary">
({count})
</Typography.Text>
</div>
{!collapsed && <div className="app-sidebar-group-content">{children}</div>}
</div>
);
}

View File

@@ -40,7 +40,7 @@ export async function fetchConversation(projectId: string, conversationId: strin
}
export async function fetchConversations(projectId: string): Promise<ConversationListResponse> {
const response = await fetch(`/api/projects/${projectId}/conversations?pageSize=100`);
const response = await fetch(`/api/projects/${projectId}/conversations?pageSize=200`);
return handleResponse(response, (data) => data as ConversationListResponse);
}

View File

@@ -0,0 +1,52 @@
export type DateGroup = "earlier" | "thisMonth" | "thisWeek" | "today" | "yesterday";
export const GROUP_LABELS: Record<DateGroup, string> = {
earlier: "更早",
thisMonth: "本月",
thisWeek: "本周",
today: "今天",
yesterday: "昨天",
};
export const GROUP_ORDER: readonly DateGroup[] = ["today", "yesterday", "thisWeek", "thisMonth", "earlier"];
export interface DateGroupData<T> {
items: T[];
key: DateGroup;
}
export function getDateGroup(dateStr: string, now: Date): DateGroup {
const date = new Date(dateStr);
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const yesterday = new Date(today.getTime() - 86_400_000);
const dateDay = new Date(date.getFullYear(), date.getMonth(), date.getDate());
if (dateDay.getTime() >= today.getTime()) return "today";
if (dateDay.getTime() >= yesterday.getTime()) return "yesterday";
const dayOfWeek = today.getDay();
const mondayOffset = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
const monday = new Date(today.getTime() - mondayOffset * 86_400_000);
if (dateDay.getTime() >= monday.getTime()) return "thisWeek";
if (dateDay.getFullYear() === today.getFullYear() && dateDay.getMonth() === today.getMonth()) {
return "thisMonth";
}
return "earlier";
}
export function groupByDate<T>(items: readonly T[], dateField: keyof T & string): Array<DateGroupData<T>> {
const now = new Date();
const groups = new Map<DateGroup, T[]>();
for (const item of items) {
const dateValue = item[dateField];
if (typeof dateValue !== "string") continue;
const group = getDateGroup(dateValue, now);
if (!groups.has(group)) groups.set(group, []);
groups.get(group)!.push(item);
}
return GROUP_ORDER.map((key) => ({ items: groups.get(key) ?? [], key }));
}