Spaces:
Sleeping
Sleeping
Update web/src/App.tsx
Browse files- web/src/App.tsx +20 -18
web/src/App.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import React, { useState, useEffect, useMemo } from 'react';
|
| 2 |
import { Header } from './components/Header';
|
| 3 |
import { LeftSidebar } from './components/LeftSidebar';
|
|
@@ -20,8 +21,8 @@ export interface Message {
|
|
| 20 |
|
| 21 |
export interface User {
|
| 22 |
name: string;
|
| 23 |
-
email: string;
|
| 24 |
-
user_id: string;
|
| 25 |
}
|
| 26 |
|
| 27 |
export interface GroupMember {
|
|
@@ -101,7 +102,9 @@ async function apiPostForm<T>(path: string, form: FormData): Promise<T> {
|
|
| 101 |
function App() {
|
| 102 |
const [isDarkMode, setIsDarkMode] = useState(() => {
|
| 103 |
const saved = localStorage.getItem('theme');
|
| 104 |
-
return
|
|
|
|
|
|
|
| 105 |
});
|
| 106 |
|
| 107 |
const [user, setUser] = useState<User | null>(null);
|
|
@@ -204,7 +207,8 @@ function App() {
|
|
| 204 |
return;
|
| 205 |
}
|
| 206 |
|
| 207 |
-
const shouldAIRespond =
|
|
|
|
| 208 |
|
| 209 |
const sender: GroupMember | undefined =
|
| 210 |
spaceType === 'group' && user
|
|
@@ -303,9 +307,7 @@ function App() {
|
|
| 303 |
if (!r.ok) throw new Error('Upload response ok=false');
|
| 304 |
|
| 305 |
setUploadedFiles((prev) =>
|
| 306 |
-
prev.map((x, i) =>
|
| 307 |
-
i === index ? { ...x, uploaded: true, uploadedChunks: r.added_chunks } : x
|
| 308 |
-
)
|
| 309 |
);
|
| 310 |
|
| 311 |
toast.success(`Uploaded: ${target.file.name} (+${r.added_chunks} chunks)`);
|
|
@@ -430,10 +432,7 @@ D) Cost reduction
|
|
| 430 |
|
| 431 |
<div className="flex-1 flex overflow-hidden">
|
| 432 |
{leftSidebarOpen && (
|
| 433 |
-
<div
|
| 434 |
-
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
|
| 435 |
-
onClick={() => setLeftSidebarOpen(false)}
|
| 436 |
-
/>
|
| 437 |
)}
|
| 438 |
|
| 439 |
<aside
|
|
@@ -464,10 +463,15 @@ D) Cost reduction
|
|
| 464 |
groupMembers={groupMembers}
|
| 465 |
/>
|
| 466 |
</aside>
|
| 467 |
-
|
|
|
|
|
|
|
|
|
|
| 468 |
flex-1 flex flex-col min-w-0
|
| 469 |
transition-all
|
| 470 |
-
${rightPanelVisible ? 'pr-[320px]' : ''}
|
|
|
|
|
|
|
| 471 |
<ChatArea
|
| 472 |
userId={userId}
|
| 473 |
docType={currentDocTypeForChat}
|
|
@@ -489,10 +493,7 @@ D) Cost reduction
|
|
| 489 |
</main>
|
| 490 |
|
| 491 |
{rightPanelOpen && (
|
| 492 |
-
<div
|
| 493 |
-
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
|
| 494 |
-
onClick={() => setRightPanelOpen(false)}
|
| 495 |
-
/>
|
| 496 |
)}
|
| 497 |
|
| 498 |
{rightPanelVisible && (
|
|
@@ -513,6 +514,7 @@ D) Cost reduction
|
|
| 513 |
<X className="h-5 w-5" />
|
| 514 |
</Button>
|
| 515 |
</div>
|
|
|
|
| 516 |
<RightPanel
|
| 517 |
user={user}
|
| 518 |
onLogin={handleLogin}
|
|
@@ -542,6 +544,7 @@ D) Cost reduction
|
|
| 542 |
{rightPanelVisible ? <ChevronRight className="h-3 w-3" /> : <ChevronLeft className="h-3 w-3" />}
|
| 543 |
</Button>
|
| 544 |
|
|
|
|
| 545 |
{!rightPanelVisible && (
|
| 546 |
<FloatingActionButtons
|
| 547 |
user={user}
|
|
@@ -558,4 +561,3 @@ D) Cost reduction
|
|
| 558 |
}
|
| 559 |
|
| 560 |
export default App;
|
| 561 |
-
|
|
|
|
| 1 |
+
// web/src/App.tsx
|
| 2 |
import React, { useState, useEffect, useMemo } from 'react';
|
| 3 |
import { Header } from './components/Header';
|
| 4 |
import { LeftSidebar } from './components/LeftSidebar';
|
|
|
|
| 21 |
|
| 22 |
export interface User {
|
| 23 |
name: string;
|
| 24 |
+
email: string; // login 输入(原始输入)
|
| 25 |
+
user_id: string; // 实际传后端的 user_id(这里等同 email/ID)
|
| 26 |
}
|
| 27 |
|
| 28 |
export interface GroupMember {
|
|
|
|
| 102 |
function App() {
|
| 103 |
const [isDarkMode, setIsDarkMode] = useState(() => {
|
| 104 |
const saved = localStorage.getItem('theme');
|
| 105 |
+
return (
|
| 106 |
+
saved === 'dark' || (!saved && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
| 107 |
+
);
|
| 108 |
});
|
| 109 |
|
| 110 |
const [user, setUser] = useState<User | null>(null);
|
|
|
|
| 207 |
return;
|
| 208 |
}
|
| 209 |
|
| 210 |
+
const shouldAIRespond =
|
| 211 |
+
spaceType === 'individual' || content.toLowerCase().includes('@clare');
|
| 212 |
|
| 213 |
const sender: GroupMember | undefined =
|
| 214 |
spaceType === 'group' && user
|
|
|
|
| 307 |
if (!r.ok) throw new Error('Upload response ok=false');
|
| 308 |
|
| 309 |
setUploadedFiles((prev) =>
|
| 310 |
+
prev.map((x, i) => (i === index ? { ...x, uploaded: true, uploadedChunks: r.added_chunks } : x))
|
|
|
|
|
|
|
| 311 |
);
|
| 312 |
|
| 313 |
toast.success(`Uploaded: ${target.file.name} (+${r.added_chunks} chunks)`);
|
|
|
|
| 432 |
|
| 433 |
<div className="flex-1 flex overflow-hidden">
|
| 434 |
{leftSidebarOpen && (
|
| 435 |
+
<div className="fixed inset-0 bg-black/50 z-40 lg:hidden" onClick={() => setLeftSidebarOpen(false)} />
|
|
|
|
|
|
|
|
|
|
| 436 |
)}
|
| 437 |
|
| 438 |
<aside
|
|
|
|
| 463 |
groupMembers={groupMembers}
|
| 464 |
/>
|
| 465 |
</aside>
|
| 466 |
+
|
| 467 |
+
{/* ✅ 右侧 Panel 展开时,为 Chat 留出空间(避免被遮住导致 FAB 只能在收起时可见) */}
|
| 468 |
+
<main
|
| 469 |
+
className={`
|
| 470 |
flex-1 flex flex-col min-w-0
|
| 471 |
transition-all
|
| 472 |
+
${rightPanelVisible ? 'pr-[320px]' : ''}
|
| 473 |
+
`}
|
| 474 |
+
>
|
| 475 |
<ChatArea
|
| 476 |
userId={userId}
|
| 477 |
docType={currentDocTypeForChat}
|
|
|
|
| 493 |
</main>
|
| 494 |
|
| 495 |
{rightPanelOpen && (
|
| 496 |
+
<div className="fixed inset-0 bg-black/50 z-40 lg:hidden" onClick={() => setRightPanelOpen(false)} />
|
|
|
|
|
|
|
|
|
|
| 497 |
)}
|
| 498 |
|
| 499 |
{rightPanelVisible && (
|
|
|
|
| 514 |
<X className="h-5 w-5" />
|
| 515 |
</Button>
|
| 516 |
</div>
|
| 517 |
+
|
| 518 |
<RightPanel
|
| 519 |
user={user}
|
| 520 |
onLogin={handleLogin}
|
|
|
|
| 544 |
{rightPanelVisible ? <ChevronRight className="h-3 w-3" /> : <ChevronLeft className="h-3 w-3" />}
|
| 545 |
</Button>
|
| 546 |
|
| 547 |
+
{/* ✅ 右侧 Panel 收起时才显示 FloatingActionButtons(你当前逻辑保持不变) */}
|
| 548 |
{!rightPanelVisible && (
|
| 549 |
<FloatingActionButtons
|
| 550 |
user={user}
|
|
|
|
| 561 |
}
|
| 562 |
|
| 563 |
export default App;
|
|
|