feat(dc): Complete Tool C Day 5 - AI Chat + Ant Design X Integration
Summary: - Upgrade to Ant Design 6.0.1 + install Ant Design X (2.1.0) + X SDK (2.1.0) - Develop frontend common capability layer: Chat component library (~968 lines) * ChatContainer.tsx - Core container component * MessageRenderer.tsx - Message renderer * CodeBlockRenderer.tsx - Code block renderer with syntax highlighting * Complete TypeScript types and documentation - Integrate ChatContainer into Tool C - Fix 7 critical UI issues: * AG Grid module registration error * UI refinement (borders, shadows, gradients) * Add AI welcome message * Auto-clear input field after sending * Remove page scrollbars * Manual code execution (not auto-run) * Support simple Q&A (new /ai/chat API) - Complete end-to-end testing - Update all documentation (4 status docs + 6 dev logs) Technical Stack: - Frontend: React 19 + Ant Design 6.0 + Ant Design X 2.1 - Components: Bubble, Sender from @ant-design/x - Total code: ~5418 lines Status: Tool C MVP completed, production ready
This commit is contained in:
@@ -79,7 +79,7 @@ const ToolC = () => {
|
||||
|
||||
if (preview.success) {
|
||||
updateState({
|
||||
data: preview.data.rows,
|
||||
data: preview.data.previewData || preview.data.rows || [],
|
||||
columns: preview.data.columns.map((col) => ({
|
||||
id: col,
|
||||
name: col,
|
||||
@@ -111,94 +111,8 @@ const ToolC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== AI消息发送 ====================
|
||||
const handleSendMessage = async (message: string) => {
|
||||
if (!state.sessionId) {
|
||||
alert('请先上传文件');
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加用户消息
|
||||
const userMessage: Message = {
|
||||
id: Date.now(),
|
||||
role: 'user',
|
||||
content: message,
|
||||
};
|
||||
|
||||
updateState({
|
||||
messages: [...state.messages, userMessage],
|
||||
isLoading: true,
|
||||
});
|
||||
|
||||
try {
|
||||
// 调用AI处理接口(一步到位:生成+执行)
|
||||
const result = await api.processMessage(state.sessionId, message);
|
||||
|
||||
if (result.success) {
|
||||
const { code, explanation, executeResult, retryCount } = result.data;
|
||||
|
||||
// 添加AI消息
|
||||
const aiMessage: Message = {
|
||||
id: Date.now() + 1,
|
||||
role: 'assistant',
|
||||
content: explanation,
|
||||
code: {
|
||||
content: code,
|
||||
status: executeResult.success ? 'success' : 'error',
|
||||
},
|
||||
};
|
||||
|
||||
updateState({
|
||||
messages: [...state.messages, userMessage, aiMessage],
|
||||
});
|
||||
|
||||
// 如果执行成功,更新表格数据
|
||||
if (executeResult.success && executeResult.newDataPreview) {
|
||||
updateState({
|
||||
data: executeResult.newDataPreview,
|
||||
messages: [
|
||||
...state.messages,
|
||||
userMessage,
|
||||
aiMessage,
|
||||
{
|
||||
id: Date.now() + 2,
|
||||
role: 'system',
|
||||
content: `✅ 代码执行成功!表格已更新。${retryCount > 0 ? `(重试 ${retryCount} 次后成功)` : ''}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
} else if (!executeResult.success) {
|
||||
updateState({
|
||||
messages: [
|
||||
...state.messages,
|
||||
userMessage,
|
||||
aiMessage,
|
||||
{
|
||||
id: Date.now() + 2,
|
||||
role: 'system',
|
||||
content: `❌ 执行失败:${executeResult.error}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('AI处理失败:', error);
|
||||
updateState({
|
||||
messages: [
|
||||
...state.messages,
|
||||
userMessage,
|
||||
{
|
||||
id: Date.now() + 1,
|
||||
role: 'system',
|
||||
content: `❌ 处理失败:${error.response?.data?.error || error.message}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
} finally {
|
||||
updateState({ isLoading: false });
|
||||
}
|
||||
};
|
||||
// ==================== AI消息发送(已由 ChatContainer 处理) ====================
|
||||
// 此功能已移至 Sidebar 中的 ChatContainer 内部
|
||||
|
||||
// ==================== 心跳机制 ====================
|
||||
useEffect(() => {
|
||||
@@ -219,33 +133,33 @@ const ToolC = () => {
|
||||
|
||||
// ==================== 渲染 ====================
|
||||
return (
|
||||
<div className="h-screen w-screen flex flex-col bg-slate-50 overflow-hidden">
|
||||
<div className="h-screen w-screen flex flex-col bg-gradient-to-br from-slate-50 to-slate-100 overflow-hidden">
|
||||
{/* 顶部栏 */}
|
||||
<Header
|
||||
fileName={state.fileName || '未上传文件'}
|
||||
onExport={() => alert('导出功能开发中...')}
|
||||
isSidebarOpen={state.isSidebarOpen}
|
||||
onToggleSidebar={() => updateState({ isSidebarOpen: !state.isSidebarOpen })}
|
||||
/>
|
||||
|
||||
{/* 主工作区 */}
|
||||
<div className="flex-1 flex overflow-hidden">
|
||||
{/* 左侧:表格区域 */}
|
||||
<div className="flex-1 flex flex-col min-w-0">
|
||||
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||||
<Toolbar />
|
||||
<div className="flex-1 overflow-auto p-6">
|
||||
<div className="flex-1 p-4 overflow-hidden">
|
||||
<DataGrid data={state.data} columns={state.columns} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 右侧:AI Copilot */}
|
||||
{/* 右侧:AI 数据清洗助手 */}
|
||||
{state.isSidebarOpen && (
|
||||
<Sidebar
|
||||
isOpen={state.isSidebarOpen}
|
||||
onClose={() => updateState({ isSidebarOpen: false })}
|
||||
messages={state.messages}
|
||||
onSendMessage={handleSendMessage}
|
||||
sessionId={state.sessionId}
|
||||
onFileUpload={handleFileUpload}
|
||||
isLoading={state.isLoading}
|
||||
hasSession={!!state.sessionId}
|
||||
onDataUpdate={(newData) => updateState({ data: newData })}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user