素材云下载
This commit is contained in:
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 4.9 MiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 272 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 4.6 MiB |
+438
File diff suppressed because one or more lines are too long
-440
File diff suppressed because one or more lines are too long
-425
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
|
After Width: | Height: | Size: 459 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 MiB |
Vendored
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</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">
|
<link rel="stylesheet" crossorigin href="/assets/index-eLRg4pQk.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Generated
+94
-1
@@ -12,6 +12,7 @@
|
|||||||
"@types/three": "^0.184.1",
|
"@types/three": "^0.184.1",
|
||||||
"antd": "^6.3.7",
|
"antd": "^6.3.7",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
"plyr-react": "^6.0.0",
|
"plyr-react": "^6.0.0",
|
||||||
"qrcode.react": "^4.2.0",
|
"qrcode.react": "^4.2.0",
|
||||||
"react": "^19.2.5",
|
"react": "^19.2.5",
|
||||||
@@ -2501,6 +2502,12 @@
|
|||||||
"url": "https://opencollective.com/core-js"
|
"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": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@@ -3083,6 +3090,12 @@
|
|||||||
"node": ">= 4"
|
"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": {
|
"node_modules/imurmurhash": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
@@ -3093,6 +3106,12 @@
|
|||||||
"node": ">=0.8.19"
|
"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": {
|
"node_modules/is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
@@ -3161,6 +3180,12 @@
|
|||||||
"node": ">=0.12.0"
|
"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": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@@ -3241,6 +3266,18 @@
|
|||||||
"node": ">=6"
|
"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": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
@@ -3265,6 +3302,15 @@
|
|||||||
"node": ">= 0.8.0"
|
"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": {
|
"node_modules/lightningcss": {
|
||||||
"version": "1.32.0",
|
"version": "1.32.0",
|
||||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
|
||||||
@@ -3770,6 +3816,12 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"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": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
@@ -4040,6 +4092,12 @@
|
|||||||
"node": ">= 0.8.0"
|
"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": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
@@ -4179,6 +4237,21 @@
|
|||||||
"pify": "^2.3.0"
|
"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": {
|
"node_modules/readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
@@ -4303,6 +4376,12 @@
|
|||||||
"queue-microtask": "^1.2.2"
|
"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": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.27.0",
|
"version": "0.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||||
@@ -4334,6 +4413,12 @@
|
|||||||
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
@@ -4367,6 +4452,15 @@
|
|||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/string-convert": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
|
||||||
@@ -4659,7 +4753,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"@types/three": "^0.184.1",
|
"@types/three": "^0.184.1",
|
||||||
"antd": "^6.3.7",
|
"antd": "^6.3.7",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
"plyr-react": "^6.0.0",
|
"plyr-react": "^6.0.0",
|
||||||
"qrcode.react": "^4.2.0",
|
"qrcode.react": "^4.2.0",
|
||||||
"react": "^19.2.5",
|
"react": "^19.2.5",
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import {
|
|||||||
uploadVideo, getCreditRatios, deleteHistory, calculateCredits
|
uploadVideo, getCreditRatios, deleteHistory, calculateCredits
|
||||||
} from '../api';
|
} from '../api';
|
||||||
|
|
||||||
|
import { useAppStore } from '../store/useAppStore';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
MenuUnfoldOutlined,
|
MenuUnfoldOutlined,
|
||||||
@@ -112,9 +114,31 @@ const AIChatPage: React.FC = () => {
|
|||||||
|
|
||||||
const [inputValue, setInputValue] = useState<string>('');
|
const [inputValue, setInputValue] = useState<string>('');
|
||||||
|
|
||||||
const [mediaType, setMediaType] = useState<string>('image');
|
// 从 store 读取生成配置状态
|
||||||
|
const {
|
||||||
const [countType, setCountType] = useState<string>('请选择');
|
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);
|
const [uploading, setUploading] = useState<boolean>(false);
|
||||||
|
|
||||||
@@ -183,11 +207,6 @@ const AIChatPage: React.FC = () => {
|
|||||||
const [attachmentPopupMessageId, setAttachmentPopupMessageId] = useState<string | null>(null);
|
const [attachmentPopupMessageId, setAttachmentPopupMessageId] = useState<string | null>(null);
|
||||||
const [attachmentPopupPosition, setAttachmentPopupPosition] = useState({ x: 0, y: 0 });
|
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 [showImageSettingsModal, setShowImageSettingsModal] = useState(false);
|
||||||
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
const [showVideoSettingsModal, setShowVideoSettingsModal] = useState(false);
|
||||||
const [ratioOptions, setRatioOptions] = useState([]);
|
const [ratioOptions, setRatioOptions] = useState([]);
|
||||||
@@ -196,22 +215,8 @@ const AIChatPage: React.FC = () => {
|
|||||||
const [blindex, setBlindex] = useState<any>(0);
|
const [blindex, setBlindex] = useState<any>(0);
|
||||||
const [fblindex, setFBlindex] = 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 [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 [creditRatios, setCreditRatios] = useState<any[]>([]);
|
||||||
const [cimage, setCimage] = useState<any[]>([]);
|
const [cimage, setCimage] = useState<any[]>([]);
|
||||||
const [creditCalculationData, setCreditCalculationData] = useState<any[]>([]);
|
const [creditCalculationData, setCreditCalculationData] = useState<any[]>([]);
|
||||||
@@ -359,23 +364,33 @@ const AIChatPage: React.FC = () => {
|
|||||||
// 如果是视频模式,初始化视频参数选项
|
// 如果是视频模式,初始化视频参数选项
|
||||||
if (data.engine.video && data.engine.video.length > 0) {
|
if (data.engine.video && data.engine.video.length > 0) {
|
||||||
const defaultEngine = data.engine.video[0];
|
const defaultEngine = data.engine.video[0];
|
||||||
|
|
||||||
|
// 查找用户之前选择的引擎(如果存在)
|
||||||
|
const savedEngine = data.engine.video.find((e: any) => e.id === countType);
|
||||||
|
const targetEngine = savedEngine || defaultEngine;
|
||||||
|
|
||||||
|
// 更新引擎选项为当前引擎支持的参数
|
||||||
setEngineOptions({
|
setEngineOptions({
|
||||||
ratios: defaultEngine.supportedRatios || ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
|
ratios: targetEngine.supportedRatios || ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
|
||||||
resolutions: defaultEngine.supportedResolutions || ['480p', '720p', '1080p'],
|
resolutions: targetEngine.supportedResolutions || ['480p', '720p', '1080p'],
|
||||||
durations: defaultEngine.supportedDurations || [5, 8, 10, 12, 15],
|
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) {
|
if (!targetEngine.supportedResolutions?.includes(videoResolution)) {
|
||||||
setVideoResolution(defaultEngine.supportedResolutions[0]);
|
setVideoResolution(targetEngine.supportedResolutions?.[0] || '720p');
|
||||||
}
|
}
|
||||||
if (defaultEngine.supportedDurations?.length > 0) {
|
if (!targetEngine.supportedDurations?.includes(videoDuration)) {
|
||||||
setVideoDuration(defaultEngine.supportedDurations[0]);
|
setVideoDuration(targetEngine.supportedDurations?.[0] || 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果之前没有选择过引擎(还是默认值),才设置默认引擎
|
||||||
|
if (countType === '请选择') {
|
||||||
|
setCountType(targetEngine.id);
|
||||||
}
|
}
|
||||||
// 设置默认引擎
|
|
||||||
setCountType(defaultEngine.id);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
|
import React, { useEffect, useState, useLayoutEffect, useRef, useCallback } from 'react';
|
||||||
import { Button, Empty, Input, Select, Space, Typography, Tag, message, Modal, Table, DatePicker } from 'antd';
|
import { Button, Empty, Input, Select, Space, Typography, Tag, message, Modal, Table, DatePicker } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import JSZip from 'jszip';
|
||||||
import {
|
import {
|
||||||
FilterOutlined,
|
FilterOutlined,
|
||||||
VideoCameraOutlined,
|
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 = () => {
|
const handleBatchUploadSelected = () => {
|
||||||
if (selectedItems.size === 0) {
|
if (selectedItems.size === 0) {
|
||||||
message.warning('请先选择要上传的媒体');
|
message.warning('请先选择要上传的媒体');
|
||||||
@@ -828,7 +904,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
}];
|
}];
|
||||||
if (recordList && recordList[0].items.length > 0) {
|
if (recordList && recordList[0].items.length > 0) {
|
||||||
setRecordList(recordList);
|
setRecordList(recordList);
|
||||||
}else{
|
} else {
|
||||||
setRecordList([]);
|
setRecordList([]);
|
||||||
}
|
}
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
@@ -927,7 +1003,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
}, [filterType, filterMedia]);
|
}, [filterType, filterMedia]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ minHeight: 'calc(100vh - 90px)', background: '#ffffffff' , overflowY: 'auto'}} >
|
<div style={{ minHeight: 'calc(100vh - 90px)', background: '#ffffffff', overflowY: 'auto' }} >
|
||||||
{/* 操作栏:筛选 + 上传按钮 */}
|
{/* 操作栏:筛选 + 上传按钮 */}
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -1008,6 +1084,18 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
>
|
>
|
||||||
取消选择
|
取消选择
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => handleDownloadSelected()}
|
||||||
|
style={{
|
||||||
|
borderRadius: 8,
|
||||||
|
background: '#f8f9fc',
|
||||||
|
border: '1px solid #e2e8f0',
|
||||||
|
color: '#222222ff',
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
下载{selectedItems.size}个
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleBatchUploadSelected}
|
onClick={handleBatchUploadSelected}
|
||||||
@@ -1036,7 +1124,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
批量上传
|
批量操作
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
@@ -1534,7 +1622,7 @@ const GeneratedRecord: React.FC = () => {
|
|||||||
open={uploadHistoryModalVisible}
|
open={uploadHistoryModalVisible}
|
||||||
onCancel={() => setUploadHistoryModalVisible(false)}
|
onCancel={() => setUploadHistoryModalVisible(false)}
|
||||||
footer={null}
|
footer={null}
|
||||||
width={ 800 }
|
width={800}
|
||||||
style={{ borderRadius: 8 }}
|
style={{ borderRadius: 8 }}
|
||||||
mask={{ closable: false }}
|
mask={{ closable: false }}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -15,6 +15,23 @@ interface AppState {
|
|||||||
records: api.GenerationRecordPageListOut;
|
records: api.GenerationRecordPageListOut;
|
||||||
loading: boolean;
|
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>;
|
fetchProjects: () => Promise<void>;
|
||||||
createProject: (name: string, industry: Industry) => Promise<Project>;
|
createProject: (name: string, industry: Industry) => Promise<Project>;
|
||||||
deleteProject: (id: string) => Promise<void>;
|
deleteProject: (id: string) => Promise<void>;
|
||||||
@@ -23,6 +40,23 @@ interface AppState {
|
|||||||
optimizePrompt: (projectId: string, params: OptimizeParams) => Promise<OptimizeResult>;
|
optimizePrompt: (projectId: string, params: OptimizeParams) => Promise<OptimizeResult>;
|
||||||
generateVideo: (recordId: string, params: GenerateParams) => Promise<GenerationRecord>;
|
generateVideo: (recordId: string, params: GenerateParams) => Promise<GenerationRecord>;
|
||||||
updateRecordReferences: (recordId: string, references: MediaReference[]) => void;
|
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) => ({
|
export const useAppStore = create<AppState>((set, get) => ({
|
||||||
@@ -30,6 +64,23 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|||||||
records: emptyRecordsPage(),
|
records: emptyRecordsPage(),
|
||||||
loading: false,
|
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 () => {
|
fetchProjects: async () => {
|
||||||
set({ loading: true });
|
set({ loading: true });
|
||||||
try {
|
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: [],
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user