- {messages.length === 0 ? (
+ {/* 触顶加载指示器 */}
+ {isLoadingOlder && (
+
+
+ 正在加载更早历史消息…
+
+ )}
+
+ {activeBuckets.length === 0 ? (
= ({
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
- color: 'var(--text-faint)',
+ color: 'var(--text-faint, #9ca3af)',
gap: '8px',
fontSize: '13px',
}}
@@ -47,17 +148,23 @@ export const MessageStream: React.FC = ({
暂无对话记录,请在下方发送立项需求
) : (
- messages.map((msg) => (
-
+ activeBuckets.map((bucket) => (
+
+ {bucket.dayKey && (
+
+ )}
+ {bucket.messages.map((msg) => (
+
+ ))}
+
))
)}
-
);
};
diff --git a/web/src/components/history/DayDivider.tsx b/web/src/components/history/DayDivider.tsx
new file mode 100644
index 00000000..f3f52595
--- /dev/null
+++ b/web/src/components/history/DayDivider.tsx
@@ -0,0 +1,126 @@
+import React from 'react';
+import { Calendar, AlertCircle } from 'lucide-react';
+import { ChatDayBucket } from '../../types/workbench';
+
+export interface DayDividerProps {
+ bucket: ChatDayBucket;
+ onLoadFullDay?: (dayKey: string) => void;
+}
+
+function formatDayTitle(dayKey: string): string {
+ if (!dayKey) return '';
+ const parts = dayKey.split('-');
+ if (parts.length !== 3) return dayKey;
+
+ const year = parts[0];
+ const month = parts[1];
+ const day = parts[2];
+
+ const now = new Date();
+ const todayStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
+
+ const yesterday = new Date(now.getTime() - 86400000);
+ const yesterdayStr = `${yesterday.getFullYear()}-${String(yesterday.getMonth() + 1).padStart(2, '0')}-${String(yesterday.getDate()).padStart(2, '0')}`;
+
+ let suffix = '';
+ if (dayKey === todayStr) {
+ suffix = ' (今天)';
+ } else if (dayKey === yesterdayStr) {
+ suffix = ' (昨天)';
+ } else {
+ try {
+ const d = new Date(`${dayKey}T00:00:00`);
+ const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
+ suffix = ` (${weekDays[d.getDay()]})`;
+ } catch (_e) {
+ // ignore
+ }
+ }
+
+ return `${year}年${month}月${day}日${suffix}`;
+}
+
+export const DayDivider: React.FC