素材云下载

This commit is contained in:
孙佳艺
2026-06-25 11:11:06 +08:00
parent 5fc1e43d4e
commit 87e412ef74
15 changed files with 767 additions and 911 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 MiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

+1 -1
View File
@@ -28,7 +28,7 @@
}
})();
</script>
<script type="module" crossorigin src="/assets/index-BwL6llN9.js"></script>
<script type="module" crossorigin src="/assets/index-BjRp0K8U.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-eLRg4pQk.css">
</head>
<body>
+94 -1
View File
@@ -12,6 +12,7 @@
"@types/three": "^0.184.1",
"antd": "^6.3.7",
"dayjs": "^1.11.20",
"jszip": "^3.10.1",
"plyr-react": "^6.0.0",
"qrcode.react": "^4.2.0",
"react": "^19.2.5",
@@ -2501,6 +2502,12 @@
"url": "https://opencollective.com/core-js"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3083,6 +3090,12 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
"license": "MIT"
},
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -3093,6 +3106,12 @@
"node": ">=0.8.19"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -3161,6 +3180,12 @@
"node": ">=0.12.0"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -3241,6 +3266,18 @@
"node": ">=6"
}
},
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmmirror.com/jszip/-/jszip-3.10.1.tgz",
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
"license": "(MIT OR GPL-3.0-or-later)",
"dependencies": {
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"setimmediate": "^1.0.5"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -3265,6 +3302,15 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"license": "MIT",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lightningcss": {
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
@@ -3770,6 +3816,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"license": "(MIT AND Zlib)"
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -4040,6 +4092,12 @@
"node": ">= 0.8.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -4179,6 +4237,21 @@
"pify": "^2.3.0"
}
},
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -4303,6 +4376,12 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
@@ -4334,6 +4413,12 @@
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
"license": "MIT"
},
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -4367,6 +4452,15 @@
"node": ">=0.10.0"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/string-convert": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
@@ -4659,7 +4753,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true,
"license": "MIT"
},
"node_modules/uuid": {
+1
View File
@@ -14,6 +14,7 @@
"@types/three": "^0.184.1",
"antd": "^6.3.7",
"dayjs": "^1.11.20",
"jszip": "^3.10.1",
"plyr-react": "^6.0.0",
"qrcode.react": "^4.2.0",
"react": "^19.2.5",
+49 -34
View File
@@ -26,6 +26,8 @@ import {
uploadVideo, getCreditRatios, deleteHistory, calculateCredits
} from '../api';
import { useAppStore } from '../store/useAppStore';
import {
PlusOutlined,
MenuUnfoldOutlined,
@@ -112,9 +114,31 @@ const AIChatPage: React.FC = () => {
const [inputValue, setInputValue] = useState<string>('');
const [mediaType, setMediaType] = useState<string>('image');
const [countType, setCountType] = useState<string>('请选择');
// 从 store 读取生成配置状态
const {
mediaType,
countType,
selectedRatio,
selectedResolution,
width,
height,
videoDuration,
videoAspectRatio,
videoResolution,
engineOptions,
enginesele,
setMediaType,
setCountType,
setSelectedRatio,
setSelectedResolution,
setWidth,
setHeight,
setVideoDuration,
setVideoAspectRatio,
setVideoResolution,
setEngineOptions,
setEnginesele,
} = useAppStore();
const [uploading, setUploading] = useState<boolean>(false);
@@ -183,11 +207,6 @@ const AIChatPage: React.FC = () => {
const [attachmentPopupMessageId, setAttachmentPopupMessageId] = useState<string | null>(null);
const [attachmentPopupPosition, setAttachmentPopupPosition] = useState({ x: 0, y: 0 });
// 图片设置相关状态
const [selectedRatio, setSelectedRatio] = useState<string>('1:1');
const [selectedResolution, setSelectedResolution] = useState<string>('2K');
const [width, setWidth] = useState<number>(2048);
const [height, setHeight] = useState<number>(2048);
const [showImageSettingsModal, setShowImageSettingsModal] = useState(false);
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
const [ratioOptions, setRatioOptions] = useState([]);
@@ -196,22 +215,8 @@ const AIChatPage: React.FC = () => {
const [blindex, setBlindex] = useState<any>(0);
const [fblindex, setFBlindex] = useState<any>(0);
// 视频设置相关状态
const [videoDuration, setVideoDuration] = useState(5);
const [videoAspectRatio, setVideoAspectRatio] = useState<string>('16:9');
const [videoResolution, setVideoResolution] = useState<string>('720p');
const [showEngineModal, setShowEngineModal] = useState(false);
const [engineOptions, setEngineOptions] = useState<{
ratios: string[];
resolutions: string[];
durations: number[];
}>({
ratios: ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: ['480p', '720p', '1080p'],
durations: [5, 8, 10, 12, 15],
});
const [enginesele, setEnginesele] = useState<any>([]);
const [creditRatios, setCreditRatios] = useState<any[]>([]);
const [cimage, setCimage] = useState<any[]>([]);
const [creditCalculationData, setCreditCalculationData] = useState<any[]>([]);
@@ -359,23 +364,33 @@ const AIChatPage: React.FC = () => {
// 如果是视频模式,初始化视频参数选项
if (data.engine.video && data.engine.video.length > 0) {
const defaultEngine = data.engine.video[0];
// 查找用户之前选择的引擎(如果存在)
const savedEngine = data.engine.video.find((e: any) => e.id === countType);
const targetEngine = savedEngine || defaultEngine;
// 更新引擎选项为当前引擎支持的参数
setEngineOptions({
ratios: defaultEngine.supportedRatios || ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: defaultEngine.supportedResolutions || ['480p', '720p', '1080p'],
durations: defaultEngine.supportedDurations || [5, 8, 10, 12, 15],
ratios: targetEngine.supportedRatios || ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: targetEngine.supportedResolutions || ['480p', '720p', '1080p'],
durations: targetEngine.supportedDurations || [5, 8, 10, 12, 15],
});
// 设置默认选中值
if (defaultEngine.supportedRatios?.length > 0) {
setVideoAspectRatio(defaultEngine.supportedRatios[0]);
// 确保视频参数在引擎支持的范围内
if (!targetEngine.supportedRatios?.includes(videoAspectRatio)) {
setVideoAspectRatio(targetEngine.supportedRatios?.[0] || '16:9');
}
if (defaultEngine.supportedResolutions?.length > 0) {
setVideoResolution(defaultEngine.supportedResolutions[0]);
if (!targetEngine.supportedResolutions?.includes(videoResolution)) {
setVideoResolution(targetEngine.supportedResolutions?.[0] || '720p');
}
if (defaultEngine.supportedDurations?.length > 0) {
setVideoDuration(defaultEngine.supportedDurations[0]);
if (!targetEngine.supportedDurations?.includes(videoDuration)) {
setVideoDuration(targetEngine.supportedDurations?.[0] || 5);
}
// 如果之前没有选择过引擎(还是默认值),才设置默认引擎
if (countType === '请选择') {
setCountType(targetEngine.id);
}
// 设置默认引擎
setCountType(defaultEngine.id);
}
})
.catch(() => {
+98 -10
View File
@@ -1,6 +1,7 @@
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
import { Button, Empty, Input, Select, Space, Typography, Tag, message, Modal, Table, DatePicker } from 'antd';
import dayjs from 'dayjs';
import JSZip from 'jszip';
import {
FilterOutlined,
VideoCameraOutlined,
@@ -601,6 +602,81 @@ const GeneratedRecord: React.FC = () => {
}
};
const handleDownloadSelected = async () => {
if (selectedItems.size === 0) {
message.warning('请先选择要下载的媒体');
return;
}
// 检查下载数量限制
if (selectedItems.size > 10) {
message.warning('最多只能单次下载10个文件');
return;
}
const selectedContent: any[] = [];
recordlist.forEach((group: any) => {
group.items.forEach((item: any) => {
if (selectedItems.has(getItemResourceId(item))) {
selectedContent.push(item);
}
});
});
const zip = new JSZip();
const baseUrl = import.meta.env.VITE_API_BASE || "http://localhost:8000";
const folder = zip.folder('downloads');
let hasError = false;
let successCount = 0;
message.loading({ content: '下载中,请稍候...', key: 'downloadProgress' });
for (const item of selectedContent) {
const url = `${baseUrl}${item.videoUrl || item.imageUrl}`;
const filename = ((item.videoUrl || item.imageUrl).split('/').pop() || `file_${Date.now()}`).split('?')[0];
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Network response was not ok');
const blob = await response.blob();
folder?.file(filename, blob);
successCount++;
} catch (error) {
console.warn(`文件下载失败(CORS限制): ${filename},将使用备用方式下载`);
hasError = true;
break;
}
}
if (hasError) {
// Fallback: 逐个打开文件下载(不受 CORS 限制)
message.destroy('downloadProgress');
message.info('由于跨域限制,将逐个下载文件');
selectedContent.forEach((item, index) => {
setTimeout(() => {
const url = `${baseUrl}${item.videoUrl || item.imageUrl}&download=1`;
const link = document.createElement('a');
link.href = url;
link.download = '';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}, index * 500);
});
return;
}
const zipBlob = await zip.generateAsync({ type: 'blob' });
const link = document.createElement('a');
link.href = URL.createObjectURL(zipBlob);
link.download = `downloads_${Date.now()}.zip`;
link.click();
URL.revokeObjectURL(link.href);
message.destroy('downloadProgress');
message.success(`下载完成,共 ${successCount} 个文件`);
};
const handleBatchUploadSelected = () => {
if (selectedItems.size === 0) {
message.warning('请先选择要上传的媒体');
@@ -692,7 +768,7 @@ const GeneratedRecord: React.FC = () => {
itemMap.set(resourceId, item);
});
});
for (const itemId of selectedItems) {
const item = itemMap.get(itemId);
// 根据item是否有generatedResourceId来决定source_model
@@ -702,7 +778,7 @@ const GeneratedRecord: React.FC = () => {
} else {
sourceModel = filterType === 'project' ? 'generation_records' : 'chat_generation_tasks';
}
tasks.push({
advertiser_ids: advertiserIds,
resource_ids: [itemId],
@@ -827,8 +903,8 @@ const GeneratedRecord: React.FC = () => {
page: res.page,
}];
if (recordList && recordList[0].items.length > 0) {
setRecordList(recordList);
}else{
setRecordList(recordList);
} else {
setRecordList([]);
}
}).catch((err) => {
@@ -927,7 +1003,7 @@ const GeneratedRecord: React.FC = () => {
}, [filterType, filterMedia]);
return (
<div style={{ minHeight: 'calc(100vh - 90px)', background: '#ffffffff' , overflowY: 'auto'}} >
<div style={{ minHeight: 'calc(100vh - 90px)', background: '#ffffffff', overflowY: 'auto' }} >
{/* 操作栏:筛选 + 上传按钮 */}
<div style={{
display: 'flex',
@@ -1008,6 +1084,18 @@ const GeneratedRecord: React.FC = () => {
>
</Button>
<Button
onClick={() => handleDownloadSelected()}
style={{
borderRadius: 8,
background: '#f8f9fc',
border: '1px solid #e2e8f0',
color: '#222222ff',
fontWeight: 600,
}}
>
{selectedItems.size}
</Button>
<Button
type="primary"
onClick={handleBatchUploadSelected}
@@ -1036,9 +1124,9 @@ const GeneratedRecord: React.FC = () => {
fontWeight: 600,
}}
>
</Button>
)}
</div>
</div>
@@ -1057,7 +1145,7 @@ const GeneratedRecord: React.FC = () => {
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<Typography.Text style={{ color: '#94a3b8', fontSize: 14 }}></Typography.Text>
<Space>
<Button
type={filterMedia === 'video' ? 'primary' : 'default'}
@@ -1534,7 +1622,7 @@ const GeneratedRecord: React.FC = () => {
open={uploadHistoryModalVisible}
onCancel={() => setUploadHistoryModalVisible(false)}
footer={null}
width={ 800 }
width={800}
style={{ borderRadius: 8 }}
mask={{ closable: false }}
>
@@ -1638,7 +1726,7 @@ const GeneratedRecord: React.FC = () => {
width: 180,
render: (date: string) => dayjs(date).format('YYYY-MM-DD HH:mm:ss'),
},
]}
loading={uploadHistoryLoading}
scroll={{ x: 'max-content' }}
+86
View File
@@ -15,6 +15,23 @@ interface AppState {
records: api.GenerationRecordPageListOut;
loading: boolean;
// 生成配置状态 - 页面跳转时保留,刷新时重置
mediaType: string;
countType: string;
selectedRatio: string;
selectedResolution: string;
width: number;
height: number;
videoDuration: number;
videoAspectRatio: string;
videoResolution: string;
engineOptions: {
ratios: string[];
resolutions: string[];
durations: number[];
};
enginesele: any;
fetchProjects: () => Promise<void>;
createProject: (name: string, industry: Industry) => Promise<Project>;
deleteProject: (id: string) => Promise<void>;
@@ -23,6 +40,23 @@ interface AppState {
optimizePrompt: (projectId: string, params: OptimizeParams) => Promise<OptimizeResult>;
generateVideo: (recordId: string, params: GenerateParams) => Promise<GenerationRecord>;
updateRecordReferences: (recordId: string, references: MediaReference[]) => void;
// 生成配置状态更新方法
setMediaType: (mediaType: string) => void;
setCountType: (countType: string) => void;
setImageSettings: (ratio: string, resolution: string, width: number, height: number) => void;
setVideoSettings: (duration: number, aspectRatio: string, resolution: string) => void;
setEngineOptions: (options: { ratios: string[]; resolutions: string[]; durations: number[] }) => void;
// 单独的 setter 方法
setSelectedRatio: (ratio: string) => void;
setSelectedResolution: (resolution: string) => void;
setWidth: (width: number) => void;
setHeight: (height: number) => void;
setVideoDuration: (duration: number) => void;
setVideoAspectRatio: (aspectRatio: string) => void;
setVideoResolution: (resolution: string) => void;
setEnginesele: (enginesele: any) => void;
resetGenerationConfig: () => void;
}
export const useAppStore = create<AppState>((set, get) => ({
@@ -30,6 +64,23 @@ export const useAppStore = create<AppState>((set, get) => ({
records: emptyRecordsPage(),
loading: false,
// 生成配置状态初始值
mediaType: 'image',
countType: '请选择',
selectedRatio: '1:1',
selectedResolution: '2K',
width: 2048,
height: 2048,
videoDuration: 5,
videoAspectRatio: '16:9',
videoResolution: '720p',
engineOptions: {
ratios: ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: ['480p', '720p', '1080p'],
durations: [5, 8, 10, 12, 15],
},
enginesele: [],
fetchProjects: async () => {
set({ loading: true });
try {
@@ -99,4 +150,39 @@ export const useAppStore = create<AppState>((set, get) => ({
},
});
},
// 生成配置状态更新方法
setMediaType: (mediaType) => set({ mediaType }),
setCountType: (countType) => set({ countType }),
setImageSettings: (ratio, resolution, width, height) =>
set({ selectedRatio: ratio, selectedResolution: resolution, width, height }),
setVideoSettings: (duration, aspectRatio, resolution) =>
set({ videoDuration: duration, videoAspectRatio: aspectRatio, videoResolution: resolution }),
setEngineOptions: (options) => set({ engineOptions: options }),
// 单独的 setter 方法
setSelectedRatio: (ratio) => set({ selectedRatio: ratio }),
setSelectedResolution: (resolution) => set({ selectedResolution: resolution }),
setWidth: (width) => set({ width }),
setHeight: (height) => set({ height }),
setVideoDuration: (duration) => set({ videoDuration: duration }),
setVideoAspectRatio: (aspectRatio) => set({ videoAspectRatio: aspectRatio }),
setVideoResolution: (resolution) => set({ videoResolution: resolution }),
setEnginesele: (enginesele) => set({ enginesele }),
resetGenerationConfig: () => set({
mediaType: 'image',
countType: '请选择',
selectedRatio: '1:1',
selectedResolution: '2K',
width: 2048,
height: 2048,
videoDuration: 5,
videoAspectRatio: '16:9',
videoResolution: '720p',
engineOptions: {
ratios: ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: ['480p', '720p', '1080p'],
durations: [5, 8, 10, 12, 15],
},
enginesele: [],
}),
}));