update: 重构项目结构
This commit is contained in:
parent
c6726a385a
commit
bc8404c965
109
src/App.tsx
109
src/App.tsx
|
|
@ -1,111 +1,12 @@
|
|||
import { useState } from 'react'
|
||||
|
||||
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
|
||||
import CanvasArea from './components/CanvasArea'
|
||||
import TopBar from './components/TopBar'
|
||||
import SideBar from './components/SideBar'
|
||||
import AIChatPanel from './components/AIChatPanel'
|
||||
import Login from './components/auth/Login'
|
||||
import Register from './components/auth/Register'
|
||||
import Projects from './components/auth/Projects'
|
||||
import Login from './pages/auth/Login'
|
||||
import Register from './pages/auth/Register'
|
||||
import Projects from './pages/app/Projects'
|
||||
import MainApp from './pages/app/MainApp'
|
||||
import './App.css'
|
||||
|
||||
// 模拟设计文件数据
|
||||
const MOCK_DESIGN_FILES = [
|
||||
{
|
||||
name: 'text_1.html',
|
||||
path: '/designs/text_1.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Hello World</h1><p>This is a test design file.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: undefined,
|
||||
children: ['text_1_1.html']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'text_1_1.html',
|
||||
path: '/designs/text_1_1.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Hello World - Version 1</h1><p>This is a modified version.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: 'text_1.html',
|
||||
children: ['text_1_1_1.html']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'text_1_1_1.html',
|
||||
path: '/designs/text_1_1_1.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Hello World - Version 1.1</h1><p>This is another modified version.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: 'text_1_1.html',
|
||||
children: []
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'text_2.html',
|
||||
path: '/designs/text_2.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Another Design</h1><p>This is a different design file.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: undefined,
|
||||
children: []
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 主应用组件
|
||||
const MainApp: React.FC = () => {
|
||||
const [isChatVisible, setIsChatVisible] = useState(true)
|
||||
const [selectedFrames, setSelectedFrames] = useState<string[]>([])
|
||||
const [designFiles, setDesignFiles] = useState<any[]>(MOCK_DESIGN_FILES)
|
||||
|
||||
const toggleChat = () => {
|
||||
setIsChatVisible(!isChatVisible)
|
||||
}
|
||||
|
||||
const handleFrameSelect = (frames: string[]) => {
|
||||
setSelectedFrames(frames)
|
||||
}
|
||||
|
||||
const handleSelectNote = (frameName: string, note: string) => {
|
||||
console.log('添加备注到设计元素:', frameName, note)
|
||||
}
|
||||
|
||||
const handleCreateContext = (title: string, description: string) => {
|
||||
console.log('创建上下文:', { title, description })
|
||||
const newFrame = {
|
||||
name: title,
|
||||
path: `/context/${title}`,
|
||||
modified: new Date(),
|
||||
content: description,
|
||||
fileType: 'html' as const,
|
||||
size: description.length,
|
||||
version: '1.0',
|
||||
generation: 0,
|
||||
branchIndex: 0,
|
||||
parentDesign: null,
|
||||
children: [],
|
||||
relationships: {
|
||||
parent: undefined,
|
||||
children: []
|
||||
}
|
||||
}
|
||||
setDesignFiles([...designFiles, newFrame])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app-container">
|
||||
<CanvasArea onFrameSelect={handleFrameSelect} designFiles={designFiles} setDesignFiles={setDesignFiles} />
|
||||
<TopBar onToggleChat={toggleChat} isChatVisible={isChatVisible} />
|
||||
<SideBar selectedFrames={selectedFrames} onSelectNote={handleSelectNote} onCreateContext={handleCreateContext} />
|
||||
{isChatVisible && <AIChatPanel />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 路由保护组件
|
||||
const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import './SideBar.css'
|
||||
import { ArrowIcon, NoteIcon, CopyIcon, PaletteIcon, PushPinIcon, PlusIcon } from './Icons'
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { useRef, useEffect, useState, useCallback } from 'react'
|
||||
import { TransformWrapper, TransformComponent, ReactZoomPanPinchRef } from 'react-zoom-pan-pinch'
|
||||
import DesignFrame from './DesignFrame'
|
||||
import ConnectionLines from './ConnectionLines'
|
||||
import DesignFrame from '../../components/DesignFrame'
|
||||
import ConnectionLines from '../../components/ConnectionLines'
|
||||
import {
|
||||
generateResponsiveConfig,
|
||||
buildHierarchyTree,
|
||||
calculateHierarchyPositions,
|
||||
getHierarchicalPosition,
|
||||
detectDesignRelationships
|
||||
} from '../utils/gridLayout'
|
||||
} from '../../utils/gridLayout'
|
||||
import {
|
||||
DesignFile,
|
||||
CanvasConfig,
|
||||
|
|
@ -20,10 +20,8 @@ import {
|
|||
LayoutMode,
|
||||
HierarchyTree,
|
||||
ConnectionLine
|
||||
} from '../types/canvas.types'
|
||||
} from '../../types/canvas.types'
|
||||
import {
|
||||
ZoomInIcon,
|
||||
ZoomOutIcon,
|
||||
HomeIcon,
|
||||
RefreshIcon,
|
||||
GlobeIcon,
|
||||
|
|
@ -32,9 +30,9 @@ import {
|
|||
DesktopIcon,
|
||||
TreeIcon,
|
||||
LinkIcon
|
||||
} from './Icons'
|
||||
} from '../../components/Icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import './CanvasArea.css'
|
||||
import '../../components/CanvasArea.css'
|
||||
|
||||
const CANVAS_CONFIG: CanvasConfig = {
|
||||
frameSize: { width: 320, height: 400 },
|
||||
|
|
@ -116,7 +114,7 @@ interface CanvasAreaProps {
|
|||
setDesignFiles?: (files: DesignFile[]) => void
|
||||
}
|
||||
|
||||
const CanvasArea: React.FC<CanvasAreaProps> = ({ onFrameSelect, designFiles: externalDesignFiles, setDesignFiles: externalSetDesignFiles }) => {
|
||||
const CanvasArea: React.FC<CanvasAreaProps> = ({ onFrameSelect, designFiles: externalDesignFiles }) => {
|
||||
const { t } = useTranslation()
|
||||
const [designFiles, setDesignFiles] = useState<DesignFile[]>([])
|
||||
const [selectedFrames, setSelectedFrames] = useState<string[]>([])
|
||||
|
|
@ -170,7 +168,7 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({ onFrameSelect, designFiles: ext
|
|||
}, [useGlobalViewport, globalViewportMode, frameViewports])
|
||||
|
||||
const handleFrameViewportChange = useCallback((fileName: string, viewport: ViewportMode) => {
|
||||
setFrameViewports(prev => ({
|
||||
setFrameViewports((prev: FrameViewportState) => ({
|
||||
...prev,
|
||||
[fileName]: viewport
|
||||
}))
|
||||
|
|
@ -449,7 +447,7 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({ onFrameSelect, designFiles: ext
|
|||
y: mousePos.y - dragState.offset.y
|
||||
}
|
||||
|
||||
setDragState(prev => ({
|
||||
setDragState((prev: DragState) => ({
|
||||
...prev,
|
||||
currentPosition: newPosition
|
||||
}))
|
||||
|
|
@ -464,7 +462,7 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({ onFrameSelect, designFiles: ext
|
|||
y: Math.round(dragState.currentPosition.y / gridSize) * gridSize
|
||||
}
|
||||
|
||||
setCustomPositions(prev => ({
|
||||
setCustomPositions((prev: FramePositionState) => ({
|
||||
...prev,
|
||||
[dragState.draggedFrame!]: snappedPosition
|
||||
}))
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
import { useState } from 'react'
|
||||
import CanvasArea from './CanvasArea'
|
||||
import TopBar from '../../components/TopBar'
|
||||
import SideBar from '../../components/SideBar'
|
||||
import AIChatPanel from '../../components/AIChatPanel'
|
||||
import '../../App.css'
|
||||
|
||||
// 模拟设计文件数据
|
||||
const MOCK_DESIGN_FILES = [
|
||||
{
|
||||
name: 'text_1.html',
|
||||
path: '/designs/text_1.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Hello World</h1><p>This is a test design file.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: undefined,
|
||||
children: ['text_1_1.html']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'text_1_1.html',
|
||||
path: '/designs/text_1_1.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Hello World - Version 1</h1><p>This is a modified version.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: 'text_1.html',
|
||||
children: ['text_1_1_1.html']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'text_1_1_1.html',
|
||||
path: '/designs/text_1_1_1.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Hello World - Version 1.1</h1><p>This is another modified version.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: 'text_1_1.html',
|
||||
children: []
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'text_2.html',
|
||||
path: '/designs/text_2.html',
|
||||
modified: new Date(),
|
||||
content: '<div style="padding: 20px; font-family: Arial, sans-serif;"><h1>Another Design</h1><p>This is a different design file.</p></div>',
|
||||
fileType: 'html',
|
||||
relationships: {
|
||||
parent: undefined,
|
||||
children: []
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 主应用组件
|
||||
const MainApp: React.FC = () => {
|
||||
const [isChatVisible, setIsChatVisible] = useState(true)
|
||||
const [selectedFrames, setSelectedFrames] = useState<string[]>([])
|
||||
const [designFiles, setDesignFiles] = useState<any[]>(MOCK_DESIGN_FILES)
|
||||
|
||||
const toggleChat = () => {
|
||||
setIsChatVisible(!isChatVisible)
|
||||
}
|
||||
|
||||
const handleFrameSelect = (frames: string[]) => {
|
||||
setSelectedFrames(frames)
|
||||
}
|
||||
|
||||
const handleSelectNote = (frameName: string, note: string) => {
|
||||
console.log('添加备注到设计元素:', frameName, note)
|
||||
}
|
||||
|
||||
const handleCreateContext = (title: string, description: string) => {
|
||||
console.log('创建上下文:', { title, description })
|
||||
const newFrame = {
|
||||
name: title,
|
||||
path: `/context/${title}`,
|
||||
modified: new Date(),
|
||||
content: description,
|
||||
fileType: 'html' as const,
|
||||
size: description.length,
|
||||
version: '1.0',
|
||||
generation: 0,
|
||||
branchIndex: 0,
|
||||
parentDesign: null,
|
||||
children: [],
|
||||
relationships: {
|
||||
parent: undefined,
|
||||
children: []
|
||||
}
|
||||
}
|
||||
setDesignFiles([...designFiles, newFrame])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app-container">
|
||||
<CanvasArea onFrameSelect={handleFrameSelect} designFiles={designFiles} setDesignFiles={setDesignFiles} />
|
||||
<TopBar onToggleChat={toggleChat} isChatVisible={isChatVisible} />
|
||||
<SideBar selectedFrames={selectedFrames} onSelectNote={handleSelectNote} onCreateContext={handleCreateContext} />
|
||||
{isChatVisible && <AIChatPanel />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MainApp
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import './Auth.css';
|
||||
import '../auth/Auth.css';
|
||||
|
||||
interface Project {
|
||||
id: string;
|
||||
|
|
@ -86,6 +86,11 @@ const Projects: React.FC = () => {
|
|||
);
|
||||
}
|
||||
|
||||
const handleProjectClick = (projectId: string) => {
|
||||
// 跳转到canvas页面,并传递项目ID
|
||||
navigate(`/app?projectId=${projectId}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="projects-container">
|
||||
<div className="projects-header">
|
||||
|
|
@ -99,7 +104,12 @@ const Projects: React.FC = () => {
|
|||
<div className="projects-empty">暂无项目</div>
|
||||
) : (
|
||||
projects.map((project) => (
|
||||
<div key={project.id} className="project-card">
|
||||
<div
|
||||
key={project.id}
|
||||
className="project-card"
|
||||
onClick={() => handleProjectClick(project.id)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<h3>{project.name}</h3>
|
||||
<p>{project.description}</p>
|
||||
<div className="project-meta">
|
||||
Loading…
Reference in New Issue