import { useState, useMemo } from 'react'; import { Plus, Trash2, Settings2, Layout, Type, Square, CheckSquare, Smartphone, Monitor, Eye, Code, Save, Download } from 'lucide-react'; import { v4 as uuidv4 } from 'uuid'; import { clsx, type ClassValue } from 'clsx'; import { twMerge } from 'tailwind-merge'; // 样式合并工具函数 function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } // 组件类型定义 type ComponentType = 'text' | 'button' | 'input' | 'card' | 'checkbox'; interface VisualComponent { id: string; type: ComponentType; props: Record; } // 可选组件库 const COMPONENT_LIBRARY = [ { type: 'text' as const, label: '文本', icon: Type, defaultProps: { text: '点击编辑文本', fontSize: '16px', color: '#000000' } }, { type: 'button' as const, label: '按钮', icon: Square, defaultProps: { label: '点击按钮', variant: 'primary', width: 'auto' } }, { type: 'input' as const, label: '输入框', icon: Type, defaultProps: { placeholder: '请输入内容...', label: '表单字段' } }, { type: 'card' as const, label: '卡片容器', icon: Layout, defaultProps: { title: '卡片标题', content: '这里是卡片内容区域' } }, { type: 'checkbox' as const, label: '复选框', icon: CheckSquare, defaultProps: { label: '选项名称', checked: false } }, ]; /** * 极简可视化低代码平台 - 核心入口组件 * 支持组件库拖拽、画布渲染、属性实时编辑及多端预览 */ export default function App() { // --- 状态管理 --- const [components, setComponents] = useState([]); // 画布上的组件列表 const [selectedId, setSelectedId] = useState(null); // 当前选中的组件 ID const [viewMode, setViewMode] = useState<'desktop' | 'mobile'>('desktop'); // 预览模式:桌面/移动端 const [isPreview, setIsPreview] = useState(false); // 是否处于预览模式 // 获取当前选中的组件对象 const selectedComponent = useMemo(() => components.find(c => c.id === selectedId), [components, selectedId] ); // 添加新组件到画布 const addComponent = (type: ComponentType, defaultProps: any) => { const newComp: VisualComponent = { id: uuidv4(), type, props: { ...defaultProps } }; setComponents([...components, newComp]); setSelectedId(newComp.id); }; // 从画布中移除组件 const removeComponent = (id: string) => { setComponents(components.filter(c => c.id !== id)); if (selectedId === id) setSelectedId(null); }; // 更新选中组件的属性 const updateProps = (id: string, newProps: any) => { setComponents(components.map(c => c.id === id ? { ...c, props: { ...c.props, ...newProps } } : c )); }; // 渲染单个可视化组件 const renderComponent = (comp: VisualComponent, index: number) => { const isSelected = selectedId === comp.id; const wrapperClass = cn( "relative group cursor-pointer border-2 border-transparent transition-all", !isPreview && isSelected && "border-blue-500 rounded-lg", !isPreview && !isSelected && "hover:border-dashed hover:border-gray-300 rounded-lg" ); const commonProps = { onClick: (e: React.MouseEvent) => { if (isPreview) return; e.stopPropagation(); setSelectedId(comp.id); } }; let element; switch (comp.type) { case 'text': element = (
{comp.props.text}
); break; case 'button': element = ( ); break; case 'input': element = (
); break; case 'card': element = (

{comp.props.title}

{comp.props.content}

); break; case 'checkbox': element = ( ); break; } return (
{element} {!isPreview && isSelected && ( )}
); }; return (
{/* 顶部工具栏 */}
极简低代码平台
{/* 左侧组件库 */} {!isPreview && ( )} {/* 中间画布 */}
setSelectedId(null)} > {components.length === 0 ? (

从左侧拖拽或点击组件开始设计

) : (
{components.map((comp, index) => renderComponent(comp, index))}
)}
{/* 右侧属性面板 */} {!isPreview && ( )}
); }