Initial commit: Memind H5 portal with MindSpace, Plaza, and agent jobs.

Track application source and tests; exclude local env, user workspaces, and runtime data via .gitignore.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
John
2026-06-15 15:04:43 -07:00
commit 2e14873f2d
272 changed files with 64133 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
import { useEffect } from 'react';
import { useChat } from '../context/ChatProvider';
import type { MindSpaceChatContext, MindSpaceSaveCategory, PortalUser } from '../types';
import { formatContextChip } from '../utils/mindspaceChatContext';
import { ChatPanel } from './ChatPanel';
import { TKMindAvatar } from './TKMindAvatar';
export function SpaceChatPanel({
open,
context,
user,
onClose,
onOpenFullChat,
onPageSaved,
}: {
open: boolean;
context: MindSpaceChatContext;
user: PortalUser;
onClose: () => void;
onOpenFullChat: () => void;
onPageSaved?: (result: {
kind: 'page' | 'category';
pageId?: string;
categoryCode?: MindSpaceSaveCategory;
}) => void;
}) {
const {
session,
messages,
chatState,
pendingTool,
submit,
stop,
approveTool,
error,
retryConnect,
} = useChat();
useEffect(() => {
if (!open) return;
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') onClose();
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [open, onClose]);
if (!open) return null;
const contextLabel = formatContextChip(context);
return (
<div className="space-chat-panel" role="dialog" aria-modal="false" aria-label="Agent 对话">
<header className="space-chat-panel-header">
<div className="space-chat-panel-brand">
<TKMindAvatar size="sm" />
<div>
<strong>TKMind</strong>
<span className="space-chat-context-chip" title={context.route}>
{contextLabel}
</span>
</div>
</div>
<div className="space-chat-panel-actions">
<button type="button" className="ghost-btn" onClick={onOpenFullChat}>
打开完整聊天
</button>
<button type="button" className="space-chat-panel-close" onClick={onClose} aria-label="关闭">
×
</button>
</div>
</header>
{error && (
<div className="space-chat-panel-error">
<span>{error}</span>
<button type="button" onClick={() => void retryConnect()}>
重试
</button>
</div>
)}
<ChatPanel
variant="compact"
user={user}
messages={messages}
chatState={chatState}
pendingTool={pendingTool}
session={session}
onSubmit={(text) => submit(text, { mindspaceContext: context })}
onStop={stop}
onApproveTool={approveTool}
onPageSaved={onPageSaved}
/>
</div>
);
}