diff --git a/video-gen-app/src/api/index.ts b/video-gen-app/src/api/index.ts index 51936e3c..4bd110fb 100644 --- a/video-gen-app/src/api/index.ts +++ b/video-gen-app/src/api/index.ts @@ -305,51 +305,7 @@ export async function getCreditRatios(): Promise { return api.get('/credits/ratios'); } // 引擎配置 -export async function getEngine(): Promise { - if (USE_MOCK) return { - engine: { - image: [ - { - id: "0019e3dac0b795b925b", - name: "Seedream 5.0", - provider: "ark", - model_name: "doubao-seedream-5-0-260128", - supported_models: ["doubao-seedream-5-0-260128"], - supported_sizes: { - "2K": { - "1:1": "2048×2048", - "4:3": "2304×1728", - "3:4": "1728×2304", - "16:9": "2560×1440", - "9:16": "1600×2848", - "3:2": "2496×1664", - "2:3": "1664×2496", - "21:9": "3024×1296" - }, - "4K": { - "1:1": "4096×4096", - "4:3": "4608×3456", - "3:4": "3520×4704", - "16:9": "5404×3040", - "9:16": "3040×5504", - "3:2": "4992×3328", - "2:3": "3328×4992", - "21:9": "6197×2656" - } - }, - default_size: "2K", - priority: 10, - maxImageCount: 4, - maxVideoCount: 0 - } - ], - video: [ - { id: '0019e1697667d0eff39', name: 'Seedance 2.0', provider: 'ark', model_name: 'seedance-2-0', supportedRatios: ['16:9', '9:16', '1:1', '4:3', '3:4', '21:9'], supportedResolutions: ['480p', '720p', '1080p'], supportedDurations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], maxImageCount: 4, maxVideoCount: 1 }, - { id: '0019e1697667d0eff38', name: 'Seedance 2.0 fast', provider: 'ark', model_name: 'seedance-2-0-fast', supportedRatios: ['16:9', '9:16', '1:1'], supportedResolutions: ['720p', '1080p'], supportedDurations: [5, 8, 10], maxImageCount: 2, maxVideoCount: 1 }, - { id: '0019f1b89b545d8e4b1', name: 'Seedance 2.0 mini', provider: 'ark', model_name: 'seedance-2-0-mini', supportedRatios: ['16:9', '9:16', '1:1'], supportedResolutions: ['480p', '720p'], supportedDurations: [4, 5, 6], maxImageCount: 1, maxVideoCount: 1 } - ] - } - }; +export async function getEngine(): Promise { return api.get('/generation-ai/engines'); } // ── Generation AI Tasks ──────────────────────────────────── @@ -760,6 +716,6 @@ export async function getHomeCaseHeader(): Promise { } // 首页素材按钮资源 -export async function getHomeCaseButton(id: string,limit:number=8): Promise { +export async function getHomeCaseButton(id: string,limit:number=5): Promise { return api.get(`/home-materials?category_id=${id}&limit_per_category=${limit}&include_empty_categories=false&response_mode=grouped&page=1&page_size=20`); } diff --git a/video-gen-app/src/components/Layout/AppLayout.tsx b/video-gen-app/src/components/Layout/AppLayout.tsx index 5a51b7c1..1d482dab 100644 --- a/video-gen-app/src/components/Layout/AppLayout.tsx +++ b/video-gen-app/src/components/Layout/AppLayout.tsx @@ -165,9 +165,10 @@ const StorageCard: React.FC<{ data: ResourceCapacityData | null }> = ({ data }) width: '100%', height: 20, background: '#e2e8f0', - borderRadius: 3, + borderRadius: 2, overflow: 'hidden', position: 'relative', + }} >
= ({ data }) justifyContent: 'space-between', marginBottom: 6, fontSize: 12, - color: '#000000ff', + color: isOver ? '#ffffffff' : '#000000ff', padding: '0 8px', - - + }}> - + {rawPercent.toFixed(1)}% {data.enabled ? ( - + {used.toFixed(2)} / {total.toFixed(2)} {unit} ) : ( @@ -207,10 +207,13 @@ const StorageCard: React.FC<{ data: ResourceCapacityData | null }> = ({ data }) style={{ width: `${barPercent}%`, height: '100%', - background: isOver - ? 'linear-gradient(90deg, #ef4444, #dc2626)' - : 'linear-gradient(90deg, #6366f1, #8b5cf6)', - borderRadius: 3, + + background: rawPercent < 50 + ? 'linear-gradient(90deg, #279951, #b7fad0)' + : rawPercent < 85 + ? 'linear-gradient(90deg, #ffd759, #fff6d4)' + : 'linear-gradient(90deg, #ef4444, #dc2626)', + borderRadius: 2, transition: 'width 0.4s ease', }} /> diff --git a/video-gen-app/src/pages/HomePage.tsx b/video-gen-app/src/pages/HomePage.tsx index 141b3d97..642504bf 100644 --- a/video-gen-app/src/pages/HomePage.tsx +++ b/video-gen-app/src/pages/HomePage.tsx @@ -1,5 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import { Button, Input, Tabs, Tag, Upload, message } from 'antd'; +import React, { useEffect, useState, useRef } from 'react'; +import { Button, Input, Tabs, Tag, Upload, message, Modal } from 'antd'; import { FileTextOutlined, ScissorOutlined, @@ -9,6 +9,7 @@ import { VideoCameraOutlined, PictureOutlined, ThunderboltOutlined, + PlayCircleOutlined, } from '@ant-design/icons'; import { useNavigate } from 'react-router-dom'; import { getmedit ,getHomeCaseHeader,getHomeCaseButton} from '../api'; @@ -39,13 +40,28 @@ const HomePage: React.FC = () => { const [activeTab, setActiveTab] = useState('project'); const [inputValue, setInputValue] = useState(''); const [mockVideos, setMockVideos] = useState([]); + const [caseHeader, setCaseHeader] = useState([]); + const [activeCaseTab, setActiveCaseTab] = useState(''); + const [caseAssets, setCaseAssets] = useState([]); + const [previewAsset, setPreviewAsset] = useState(null); + const previewVideoRef = useRef(null); + useEffect(() => { - getHomeCaseHeader().then((res) => { - console.log(res); - }) - getHomeCaseButton('0019f17d00fdbece98e').then((res) => { - console.log(res); - }) + getHomeCaseHeader().then((res: any) => { + // console.log('caseHeader:', res); + if (res?.items?.length > 0) { + setCaseHeader(res.items); + const firstId = res.items[0].id; + setActiveCaseTab(firstId); + // 初始请求第一个 tab 的数据 + getHomeCaseButton(firstId).then((btnRes: any) => { + console.log('caseButton:', btnRes); + if (btnRes?.categories?.[0]?.assets) { + setCaseAssets(btnRes.categories[0].assets); + } + }); + } + }); }, []); useEffect(() => { @@ -83,21 +99,21 @@ const HomePage: React.FC = () => { { icon: , title: '爆款开头复刻', - description: '一键复刻热门视频开篇,快速替换自有商品素材', + description: '上传参考视频与产品图片,一键复刻爆款视频开头', action: '立即创作', path: '/initial', }, { icon: , - title: '批量混剪', - description: '多素材批量自动剪辑,智能筛选高清优质镜头片段', + title: '拆镜复刻', + description: '一键拆解画面分镜,助力仿拍或创作', action: '开始混剪', path: '/removelens', }, { icon: , title: 'AI成片', - description: 'AI全自动快速出片,支持文案生成/上传参考素材制作', + description: '输入想法、剧本或上传参考,智能生成视频/图片', action: '立即生成', path: '/conversation', }, @@ -715,8 +731,6 @@ const HomePage: React.FC = () => { gap: 6, fontSize: 12, color: '#64748b', - - }}> {(() => { // 显示所属模块,而非媒体类型 @@ -781,68 +795,176 @@ const HomePage: React.FC = () => { 精选优质作品参考
-
更多案例 -
+ */} -
- {materialCases.map((caseUrl, index) => ( + {/* Tab切换 */} +
+ { + setActiveCaseTab(key); + getHomeCaseButton(key).then((btnRes: any) => { + if (btnRes?.categories?.[0]?.assets) { + setCaseAssets(btnRes.categories[0].assets); + } else { + setCaseAssets([]); + } + }); + }} + items={caseHeader.map((item: any) => ({ + key: item.id, + label: item.name, + }))} + className="homepage-tabs" + /> +
+ + {/* ========== 素材案例列表(与近期作品一致) ========== */} +
+ {caseAssets.length === 0 ? ( +
+ +
暂无素材
+
+ ) : caseAssets.map((asset: any, index: number) => (
setPreviewAsset(asset)} style={{ - flex: 1, - aspectRatio: '16/9', borderRadius: 12, overflow: 'hidden', cursor: 'pointer', - background: '#f1f5f9', - position: 'relative', - }} - onMouseEnter={(e) => { - const overlay = e.currentTarget.querySelector('.case-overlay') as HTMLElement | null; - if (overlay) overlay.style.opacity = '1'; - }} - onMouseLeave={(e) => { - const overlay = e.currentTarget.querySelector('.case-overlay') as HTMLElement | null; - if (overlay) overlay.style.opacity = '0'; + background: '#fff', + border: '1px solid #e2e8f0', }} > - {`素材案例 - 案例悬停遮罩(由父级 hover 触发) -
- 案例 {index + 1} + {/* 媒体区域 16:9 */} +
+ {asset.mediaType === 'video' ? ( + <> +
+ {/* 底部信息栏 */} +
+
+ {asset.title || `素材 ${index + 1}`} +
))}
+ + {/* ========== 预览弹窗 ========== */} + { + previewVideoRef.current?.pause(); + setPreviewAsset(null); + }} + footer={null} + width={760} + centered + className="preview-modal" + bodyStyle={{ + padding: 0, + background: '#fff', + borderRadius: 16, + overflow: 'hidden', + }} + > + {/* 固定比例容器 16:9 */} +
+
+ {previewAsset?.mediaType === 'video' ? ( +
+
+ {/* 底部标题栏 */} + {previewAsset?.title && ( +
+ {previewAsset.title} +
+ )} +
); }; diff --git a/video-gen-app/src/pages/InitialReplication.tsx b/video-gen-app/src/pages/InitialReplication.tsx index 61c11796..8c29e1c8 100644 --- a/video-gen-app/src/pages/InitialReplication.tsx +++ b/video-gen-app/src/pages/InitialReplication.tsx @@ -459,7 +459,8 @@ const GenerateConver: React.FC = () => { background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', - backgroundClip: 'text' + backgroundClip: 'text', + textAlign: 'center', }}> 爆款开头复刻 diff --git a/video-gen-app/src/pages/ProjectsPage.tsx b/video-gen-app/src/pages/ProjectsPage.tsx index 187e2312..3ed92569 100644 --- a/video-gen-app/src/pages/ProjectsPage.tsx +++ b/video-gen-app/src/pages/ProjectsPage.tsx @@ -125,7 +125,8 @@ const ProjectsPage: React.FC = () => { background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', - backgroundClip: 'text' + backgroundClip: 'text', + textAlign: 'center', }}> 我的项目 diff --git a/video-gen-app/src/pages/RemoveLens.tsx b/video-gen-app/src/pages/RemoveLens.tsx index c10e7d73..03e5e756 100644 --- a/video-gen-app/src/pages/RemoveLens.tsx +++ b/video-gen-app/src/pages/RemoveLens.tsx @@ -186,7 +186,8 @@ export default function VideoFrameExtractor() { background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', - backgroundClip: 'text' + backgroundClip: 'text', + textAlign: 'center', }}> AI视频拆镜工作台