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:
2025-12-07 22:02:14 +08:00
parent 2c7ed94161
commit af325348b8
30 changed files with 5005 additions and 976 deletions

View File

@@ -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>