diff --git a/web/client/src/App.tsx b/web/client/src/App.tsx new file mode 100644 index 0000000..09fba56 --- /dev/null +++ b/web/client/src/App.tsx @@ -0,0 +1,24 @@ +import { AppLayout } from '@/components/layout/AppLayout'; +import { ChatView } from '@/components/chat/ChatView'; +import { AccountList } from '@/components/accounts/AccountList'; +import { AssetGallery } from '@/components/assets/AssetGallery'; +import { ConfigForm } from '@/components/config/ConfigForm'; +import { useAppStore } from '@/store'; + +function MainContent() { + const view = useAppStore((s) => s.activeView); + switch (view) { + case 'chat': return ; + case 'accounts': return ; + case 'assets': return ; + case 'config': return ; + } +} + +export default function App() { + return ( + + + + ); +} diff --git a/web/client/src/components/accounts/AccountList.tsx b/web/client/src/components/accounts/AccountList.tsx new file mode 100644 index 0000000..3ad32ea --- /dev/null +++ b/web/client/src/components/accounts/AccountList.tsx @@ -0,0 +1,3 @@ +export function AccountList() { + return
账户管理
; +} diff --git a/web/client/src/components/assets/AssetGallery.tsx b/web/client/src/components/assets/AssetGallery.tsx new file mode 100644 index 0000000..fb0dee6 --- /dev/null +++ b/web/client/src/components/assets/AssetGallery.tsx @@ -0,0 +1,3 @@ +export function AssetGallery() { + return
资产画廊
; +} diff --git a/web/client/src/components/chat/ChatView.tsx b/web/client/src/components/chat/ChatView.tsx new file mode 100644 index 0000000..9672061 --- /dev/null +++ b/web/client/src/components/chat/ChatView.tsx @@ -0,0 +1,3 @@ +export function ChatView() { + return
选择或开始新对话
; +} diff --git a/web/client/src/components/config/ConfigForm.tsx b/web/client/src/components/config/ConfigForm.tsx new file mode 100644 index 0000000..57b39cb --- /dev/null +++ b/web/client/src/components/config/ConfigForm.tsx @@ -0,0 +1,3 @@ +export function ConfigForm() { + return
设置
; +} diff --git a/web/client/src/components/layout/AppLayout.tsx b/web/client/src/components/layout/AppLayout.tsx new file mode 100644 index 0000000..c0bc784 --- /dev/null +++ b/web/client/src/components/layout/AppLayout.tsx @@ -0,0 +1,17 @@ +import { Sidebar } from './Sidebar'; +import { MiddlePanel } from './MiddlePanel'; +import { useAppStore } from '@/store'; + +export function AppLayout({ children }: { children: React.ReactNode }) { + const activeView = useAppStore((s) => s.activeView); + + return ( +
+ + {activeView === 'chat' && } +
+ {children} +
+
+ ); +} diff --git a/web/client/src/components/layout/MiddlePanel.tsx b/web/client/src/components/layout/MiddlePanel.tsx new file mode 100644 index 0000000..7c3ea97 --- /dev/null +++ b/web/client/src/components/layout/MiddlePanel.tsx @@ -0,0 +1,38 @@ +import { Plus } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { ScrollArea } from '@/components/ui/scroll-area'; +import { useAppStore } from '@/store'; + +export function MiddlePanel() { + const { conversations, activeConversationId, setActiveConversationId } = useAppStore(); + + return ( + + ); +} diff --git a/web/client/src/components/layout/Sidebar.tsx b/web/client/src/components/layout/Sidebar.tsx new file mode 100644 index 0000000..88c2bf9 --- /dev/null +++ b/web/client/src/components/layout/Sidebar.tsx @@ -0,0 +1,35 @@ +import { MessageCircle, FolderOpen, Image, Settings } from 'lucide-react'; +import { useAppStore } from '@/store'; +import type { NavView } from '@/types'; +import { cn } from '@/lib/utils'; + +const navItems: { id: NavView; icon: typeof MessageCircle; label: string }[] = [ + { id: 'chat', icon: MessageCircle, label: '对话' }, + { id: 'accounts', icon: FolderOpen, label: '账户' }, + { id: 'assets', icon: Image, label: '资产' }, + { id: 'config', icon: Settings, label: '设置' }, +]; + +export function Sidebar() { + const { activeView, setActiveView } = useAppStore(); + + return ( + + ); +} diff --git a/web/client/src/store/index.ts b/web/client/src/store/index.ts new file mode 100644 index 0000000..1a77c11 --- /dev/null +++ b/web/client/src/store/index.ts @@ -0,0 +1,24 @@ +import { create } from 'zustand'; +import type { NavView, Conversation } from '@/types'; + +interface AppState { + activeView: NavView; + setActiveView: (view: NavView) => void; + selectedAccountId: string | null; + setSelectedAccountId: (id: string | null) => void; + activeConversationId: string | null; + setActiveConversationId: (id: string | null) => void; + conversations: Conversation[]; + setConversations: (list: Conversation[]) => void; +} + +export const useAppStore = create((set) => ({ + activeView: 'chat', + setActiveView: (view) => set({ activeView: view }), + selectedAccountId: null, + setSelectedAccountId: (id) => set({ selectedAccountId: id }), + activeConversationId: null, + setActiveConversationId: (id) => set({ activeConversationId: id }), + conversations: [], + setConversations: (list) => set({ conversations: list }), +})); diff --git a/web/client/src/types/index.ts b/web/client/src/types/index.ts new file mode 100644 index 0000000..73efb68 --- /dev/null +++ b/web/client/src/types/index.ts @@ -0,0 +1,53 @@ +export type NavView = 'chat' | 'accounts' | 'assets' | 'config'; + +export interface Account { + id: string; + name: string; + description: string; + defaultFormat: string; + imageModel: string; + videoModel: string; + batchSize: number; + ttsVoice: string; + ttsInstruction: string; + storyboardPrompt: string; + imageStylePrompt: string; + videoStylePrompt: string; + references: { file: string; url?: string }[]; + capcut: Record; +} + +export interface Conversation { + id: string; + title: string; + account_id: string | null; + created_at: string; + updated_at: string; +} + +export interface Message { + id: string; + conversation_id: string; + role: 'user' | 'assistant' | 'system' | 'tool'; + content: string; + tool_calls?: unknown; + created_at: string; +} + +export interface Asset { + id: string; + account_id: string | null; + manifest_path: string | null; + type: 'image' | 'video'; + file_path: string; + url: string | null; + shot_index: number | null; + created_at: string; +} + +export interface ConfigItem { + id: string; + key: string; + value: Record; + updated_at: string; +}