Spaces:
Sleeping
Sleeping
| import React, { useState } from 'react'; | |
| import { Layout, Input, Button, Card, List, Typography, Space, Divider, message, Spin } from 'antd'; | |
| import { SendOutlined, HistoryOutlined, SettingOutlined, ProjectOutlined, CodeOutlined, EyeOutlined } from '@ant-design/icons'; | |
| import axios from 'axios'; | |
| const { Header, Content, Sider } = Layout; | |
| const { TextArea } = Input; | |
| const { Title, Text } = Typography; | |
| export default function Home() { | |
| const [input, setInput] = useState(''); | |
| const [loading, setLoading] = useState(false); | |
| const [generatedCode, setGeneratedCode] = useState(''); | |
| const [history, setHistory] = useState([ | |
| '生成一个蓝色风格的登录页面', | |
| '创建一个电商首页轮播图', | |
| '设计一个响应式的个人主页', | |
| ]); | |
| const [viewMode, setViewMode] = useState<'preview' | 'code'>('preview'); | |
| const handleGenerate = async () => { | |
| if (!input.trim()) { | |
| message.warning('请输入您的描述内容'); | |
| return; | |
| } | |
| setLoading(true); | |
| try { | |
| const response = await axios.post('/api/ai/generate', { prompt: input }); | |
| if (response.data.success) { | |
| setGeneratedCode(response.data.data.code); | |
| setHistory([input, ...history.slice(0, 9)]); | |
| message.success('生成成功!'); | |
| } else { | |
| message.error(response.data.error || '生成失败'); | |
| } | |
| } catch (error) { | |
| console.error('Generation failed:', error); | |
| message.error('请求失败,请检查后端服务是否正常运行'); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| return ( | |
| <Layout style={{ minHeight: '100vh' }}> | |
| <Header style={{ background: '#fff', padding: '0 24px', display: 'flex', alignItems: 'center', borderBottom: '1px solid #f0f0f0' }}> | |
| <Title level={4} style={{ margin: 0, color: '#1890ff' }}>生成式 UI Agent</Title> | |
| <div style={{ marginLeft: 'auto' }}> | |
| <Space size="large"> | |
| <Button type="text" icon={<ProjectOutlined />}>项目管理</Button> | |
| <Button type="text" icon={<SettingOutlined />}>设置</Button> | |
| </Space> | |
| </div> | |
| </Header> | |
| <Layout> | |
| <Sider width={250} style={{ background: '#fff', borderRight: '1px solid #f0f0f0' }}> | |
| <div style={{ padding: '16px' }}> | |
| <Title level={5}><HistoryOutlined /> 历史记录</Title> | |
| <List | |
| dataSource={history} | |
| renderItem={(item) => ( | |
| <List.Item | |
| style={{ cursor: 'pointer', padding: '8px 0' }} | |
| onClick={() => setInput(item)} | |
| > | |
| <Text ellipsis>{item}</Text> | |
| </List.Item> | |
| )} | |
| /> | |
| </div> | |
| </Sider> | |
| <Content style={{ padding: '24px', display: 'flex', gap: '24px' }}> | |
| <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '16px' }}> | |
| <Card title="AI 对话输入" variant="borderless" style={{ boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }}> | |
| <TextArea | |
| rows={4} | |
| value={input} | |
| onChange={(e) => setInput(e.target.value)} | |
| placeholder="描述你想要的 UI 界面,例如:'生成一个精美的博客主页'..." | |
| style={{ marginBottom: '16px' }} | |
| disabled={loading} | |
| /> | |
| <div style={{ textAlign: 'right' }}> | |
| <Button | |
| type="primary" | |
| icon={<SendOutlined />} | |
| size="large" | |
| onClick={handleGenerate} | |
| loading={loading} | |
| > | |
| {loading ? '正在生成...' : '开始生成'} | |
| </Button> | |
| </div> | |
| </Card> | |
| <Card title="系统状态" variant="borderless" style={{ boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }}> | |
| <Space direction="vertical" style={{ width: '100%' }}> | |
| <div style={{ display: 'flex', justifyContent: 'space-between' }}> | |
| <Text>API 状态</Text> | |
| <Text type="success">已连接 (SiliconFlow)</Text> | |
| </div> | |
| <div style={{ display: 'flex', justifyContent: 'space-between' }}> | |
| <Text>当前模型</Text> | |
| <Text>DeepSeek-V3</Text> | |
| </div> | |
| </Space> | |
| </Card> | |
| </div> | |
| <div style={{ flex: 2 }}> | |
| <Card | |
| title="实时预览" | |
| extra={ | |
| <Space> | |
| <Button | |
| size="small" | |
| type={viewMode === 'preview' ? 'primary' : 'default'} | |
| icon={<EyeOutlined />} | |
| onClick={() => setViewMode('preview')} | |
| > | |
| 预览 | |
| </Button> | |
| <Button | |
| size="small" | |
| type={viewMode === 'code' ? 'primary' : 'default'} | |
| icon={<CodeOutlined />} | |
| onClick={() => setViewMode('code')} | |
| > | |
| 代码 | |
| </Button> | |
| </Space> | |
| } | |
| style={{ height: '100%', minHeight: '600px', boxShadow: '0 2px 8px rgba(0,0,0,0.06)' }} | |
| styles={{ body: { height: 'calc(100% - 58px)', padding: 0, overflow: 'auto', background: '#f5f5f5' } }} | |
| > | |
| {loading ? ( | |
| <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}> | |
| <Space direction="vertical" align="center"> | |
| <Spin size="large" /> | |
| <Text type="secondary">AI 正在为您精心设计界面...</Text> | |
| </Space> | |
| </div> | |
| ) : generatedCode ? ( | |
| viewMode === 'preview' ? ( | |
| <div style={{ padding: '24px', height: '100%', width: '100%' }}> | |
| <div style={{ background: '#fff', padding: '24px', borderRadius: '8px', boxShadow: '0 4px 12px rgba(0,0,0,0.08)', minHeight: '100%' }}> | |
| {/* 简单起见,这里显示生成的代码说明,真实预览通常需要 react-live 或类似组件 */} | |
| <Title level={4}>预览说明</Title> | |
| <Text style={{ display: 'block', marginBottom: 16 }}> | |
| AI 已为您生成了完整的 React + Tailwind 代码。 | |
| </Text> | |
| <Divider /> | |
| <div style={{ background: '#fafafa', padding: '16px', borderRadius: '4px', border: '1px solid #eee' }}> | |
| <Text type="secondary"> | |
| 由于环境限制,当前预览仅支持静态渲染提示。您可以点击右上角“代码”查看并复制生成的完整源代码。 | |
| </Text> | |
| </div> | |
| </div> | |
| </div> | |
| ) : ( | |
| <pre style={{ margin: 0, padding: '24px', background: '#1e1e1e', color: '#d4d4d4', overflow: 'auto', height: '100%' }}> | |
| <code>{generatedCode}</code> | |
| </pre> | |
| ) | |
| ) : ( | |
| <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}> | |
| <Text type="secondary">生成的 UI 将在这里实时显示</Text> | |
| </div> | |
| )} | |
| </Card> | |
| </div> | |
| </Content> | |
| </Layout> | |
| </Layout> | |
| ); | |
| } |