From 1c2421e2b6c7725945c3c72be5affbb362270167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=97=E6=9E=B3?= <7854742+wang_rumeng@user.noreply.gitee.com> Date: Fri, 17 Oct 2025 20:32:06 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80create=E8=BE=93=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/create/page.tsx | 10 + components/layout/type.ts | 3 +- .../create-video/CreateInput/ConfigPanel.tsx | 145 +++++++++++++ .../pages/create-video/CreateInput/README.md | 77 +++++++ .../CreateInput/VideoCreationForm.tsx | 193 ++++++++++++++++++ .../CreateInput/config-options.ts | 51 +++++ .../pages/create-video/CreateInput/index.ts | 4 + components/pages/create-video/CreateVideo.tsx | 17 ++ .../PhotoPreview/PhotoPreviewSection.tsx | 147 +++++++++++++ .../pages/create-video/PhotoPreview/README.md | 113 ++++++++++ .../pages/create-video/PhotoPreview/index.ts | 6 + .../create-video/PhotoPreview/styles.css | 33 +++ .../pages/create-video/PhotoPreview/types.ts | 25 +++ 13 files changed, 823 insertions(+), 1 deletion(-) create mode 100644 app/create/page.tsx create mode 100644 components/pages/create-video/CreateInput/ConfigPanel.tsx create mode 100644 components/pages/create-video/CreateInput/README.md create mode 100644 components/pages/create-video/CreateInput/VideoCreationForm.tsx create mode 100644 components/pages/create-video/CreateInput/config-options.ts create mode 100644 components/pages/create-video/CreateInput/index.ts create mode 100644 components/pages/create-video/CreateVideo.tsx create mode 100644 components/pages/create-video/PhotoPreview/PhotoPreviewSection.tsx create mode 100644 components/pages/create-video/PhotoPreview/README.md create mode 100644 components/pages/create-video/PhotoPreview/index.ts create mode 100644 components/pages/create-video/PhotoPreview/styles.css create mode 100644 components/pages/create-video/PhotoPreview/types.ts diff --git a/app/create/page.tsx b/app/create/page.tsx new file mode 100644 index 0000000..b332b09 --- /dev/null +++ b/app/create/page.tsx @@ -0,0 +1,10 @@ +import CreateVideo from '@/components/pages/create-video/CreateVideo'; +import { DashboardLayout } from '@/components/layout/dashboard-layout'; + +export default function CreatePage() { + return ( + + + + ); +} \ No newline at end of file diff --git a/components/layout/type.ts b/components/layout/type.ts index 9660c8b..8441d55 100644 --- a/components/layout/type.ts +++ b/components/layout/type.ts @@ -1,4 +1,4 @@ -import { BookHeart, Gift } from "lucide-react"; +import { BookHeart, Gift, Plus } from "lucide-react"; interface NavigationItem { name: string; @@ -17,6 +17,7 @@ export const navigationItems: Navigations[] = [ items: [ { name: 'My Portfolio', href: '/movies', icon: BookHeart }, { name: 'Share', href: '/share', icon: Gift }, + { name: 'Create', href: '/create', icon: Plus }, ], } ]; \ No newline at end of file diff --git a/components/pages/create-video/CreateInput/ConfigPanel.tsx b/components/pages/create-video/CreateInput/ConfigPanel.tsx new file mode 100644 index 0000000..7a949d8 --- /dev/null +++ b/components/pages/create-video/CreateInput/ConfigPanel.tsx @@ -0,0 +1,145 @@ +"use client"; + +import { + GlobalOutlined, + ClockCircleOutlined, + DownOutlined, + MobileOutlined, + DesktopOutlined, +} from '@ant-design/icons'; +import { WandSparkles, RectangleHorizontal, RectangleVertical } from 'lucide-react'; +import { Dropdown, Menu, Tooltip } from 'antd'; +import { LanguageOptions, VideoDurationOptions } from './config-options'; +import type { ConfigOptions, LanguageValue, VideoDurationValue } from './config-options'; + +interface ConfigPanelProps { + /** Current configuration options */ + configOptions: ConfigOptions; + /** Handler for configuration changes */ + onConfigChange: (key: K, value: ConfigOptions[K]) => void; + /** Whether it's mobile device */ + isMobile?: boolean; + /** Whether it's desktop device */ + isDesktop?: boolean; +} + +/** + * Configuration panel component for video creation settings. + * Includes language, auto script, duration, and aspect ratio selectors. + * @param {ConfigOptions} configOptions - current configuration + * @param {Function} onConfigChange - handler for config changes + * @param {boolean} isMobile - whether it's mobile device + * @param {boolean} isDesktop - whether it's desktop device + * @returns {JSX.Element} + */ +export const ConfigPanel = ({ + configOptions, + onConfigChange, + isMobile = false, + isDesktop = true, +}: ConfigPanelProps) => { + /** Language dropdown menu */ + const languageMenu = ( + onConfigChange('language', key as LanguageValue)} + items={LanguageOptions.map((option) => ({ + key: option.value, + label: {option.label}, + }))} + /> + ); + + /** Duration dropdown menu */ + const durationMenu = ( + onConfigChange('videoDuration', key as VideoDurationValue)} + items={VideoDurationOptions.map((option) => ({ + key: option.value, + label: {option.label}, + }))} + /> + ); + + const currentLanguage = LanguageOptions.find((option) => option.value === configOptions.language); + const currentDuration = configOptions.videoDuration === 'unlimited' ? 'auto' : configOptions.videoDuration; + + return ( +
+ {/* Language selector */} + + + + + {/* Auto script toggle */} + + + + + {/* Duration selector */} + + + + + {/* Aspect ratio toggles */} +
+ + +
+
+ ); +}; + diff --git a/components/pages/create-video/CreateInput/README.md b/components/pages/create-video/CreateInput/README.md new file mode 100644 index 0000000..b7951a8 --- /dev/null +++ b/components/pages/create-video/CreateInput/README.md @@ -0,0 +1,77 @@ +# CreateInput Component + +Video creation input form with configuration options. + +## File Structure + +``` +CreateInput/ +├── VideoCreationForm.tsx # Main form component +├── ConfigPanel.tsx # Configuration panel with all options +├── config-options.ts # Configuration options and types +├── index.ts # Module exports +└── README.md # This file +``` + +## Components + +### VideoCreationForm +Main form component for video creation, includes: +- Photo upload (character, scene, prop) +- Text input area +- Configuration options +- Create button + +### ConfigPanel +Configuration panel with unified circular button style: +- Language selector (14 languages) +- Auto Script toggle (AI Story Copilot) +- Duration selector (8s, 1min, 2min, auto) +- Aspect ratio selector (landscape/portrait) + +All buttons follow the same design pattern: +- Circular buttons with `rounded-full` +- Border: `border-white/20` +- Hover: `hover:bg-white/5 hover:border-cyan-400/60` +- Active state: `border-cyan-400 bg-cyan-400/10` +- Cyan color theme for interactions + +## Configuration Options + +Defined in `config-options.ts`: + +```typescript +interface ConfigOptions { + language: LanguageValue; // Default: 'english' + expansion_mode: boolean; // Default: false + videoDuration: VideoDurationValue; // Default: 'unlimited' + aspect_ratio: AspectRatioValue; // Default: 'VIDEO_ASPECT_RATIO_LANDSCAPE' +} +``` + +## Usage + +```tsx +import { VideoCreationForm } from '@/components/pages/create-video/CreateInput'; + +export default function CreatePage() { + return ; +} +``` + +## Design System + +All configuration buttons follow a unified design: +- **Base style**: `rounded-full border border-white/20 bg-transparent` +- **Hover**: `hover:bg-white/5 hover:border-cyan-400/60 hover:text-cyan-400` +- **Active**: `border-cyan-400 bg-cyan-400/10 text-cyan-400` +- **Transition**: `transition-all duration-200` + +## Notes + +- Configuration options are synchronized with ChatInputBox component +- All text and labels are in English as per project guidelines +- Uses Tailwind CSS 3.x for all styling +- Uses Ant Design icons for consistency with existing UI +- Responsive design with mobile/desktop support + diff --git a/components/pages/create-video/CreateInput/VideoCreationForm.tsx b/components/pages/create-video/CreateInput/VideoCreationForm.tsx new file mode 100644 index 0000000..c3fc030 --- /dev/null +++ b/components/pages/create-video/CreateInput/VideoCreationForm.tsx @@ -0,0 +1,193 @@ +"use client"; + +import { useState, useRef } from 'react'; +import { PhotoPreviewSection } from '../PhotoPreview'; +import type { PhotoItem, PhotoType } from '../PhotoPreview/types'; +import { + PlusOutlined, + UserOutlined, + CameraOutlined, + BulbOutlined, + ArrowRightOutlined, +} from '@ant-design/icons'; +import { Dropdown, Menu } from 'antd'; +import { ConfigPanel } from './ConfigPanel'; +import { defaultConfig } from './config-options'; +import type { ConfigOptions } from './config-options'; +import { useDeviceType } from '@/hooks/useDeviceType'; + +export default function VideoCreationForm() { + const [photos, setPhotos] = useState([]); + const [inputText, setInputText] = useState(''); + const [configOptions, setConfigOptions] = useState(defaultConfig); + + const { isMobile, isDesktop } = useDeviceType(); + + const characterInputRef = useRef(null); + const sceneInputRef = useRef(null); + const propInputRef = useRef(null); + + /** Handle photo deletion */ + const handleDeletePhoto = (index: number) => { + setPhotos(prevPhotos => prevPhotos.filter((_, i) => i !== index)); + }; + + /** Handle file upload */ + const handleFileUpload = (event: React.ChangeEvent, type: PhotoType) => { + const files = event.target.files; + if (!files || files.length === 0) return; + + const newPhotos: PhotoItem[] = Array.from(files).map((file, index) => ({ + url: URL.createObjectURL(file), + type, + id: `${type}-${Date.now()}-${index}`, + })); + + setPhotos(prevPhotos => [...prevPhotos, ...newPhotos]); + event.target.value = ''; + }; + + /** Handle configuration change */ + const handleConfigChange = ( + key: K, + value: ConfigOptions[K] + ) => { + setConfigOptions(prev => ({ ...prev, [key]: value })); + }; + + /** Handle video creation */ + const handleCreate = () => { + console.log({ + text: inputText, + photos, + config: configOptions, + }); + // TODO: Implement video creation logic + }; + + return ( +
+ {/* Main Content Area with Border */} +
+ {/* Photo Preview Section - Top */} + {photos.length > 0 && ( +
+ +
+ )} + + {/* Text Input Area - Middle */} +
+