feat: 添加图片生视频功能

- 在结果页面添加图片生视频按钮,仅在图片结果时显示
- 集成serverSdk调用executeTemplate接口生成视频
- 实现加载状态和错误处理机制
- 生成成功后跳转到生成页面查看进度
- 扩展DownloadSection组件支持新功能
This commit is contained in:
imeepos 2025-09-09 17:47:19 +08:00
parent be157d0bcb
commit 9e39ca842c
2 changed files with 72 additions and 4 deletions

View File

@ -4,12 +4,23 @@ import './index.css'
interface DownloadSectionProps {
onDownload: () => void
onRegenerate?: () => void
onImageToVideo?: () => void
loading: boolean
hasWatchedAd?: boolean
adAvailable?: boolean
showImageToVideo?: boolean
imageToVideoLoading?: boolean
}
const DownloadSection: React.FC<DownloadSectionProps> = ({ onDownload, onRegenerate, loading, adAvailable = true }) => {
const DownloadSection: React.FC<DownloadSectionProps> = ({
onDownload,
onRegenerate,
onImageToVideo,
loading,
adAvailable = true,
showImageToVideo = false,
imageToVideoLoading = false
}) => {
const getButtonText = () => {
if (loading) {
return '广告加载中...'
@ -40,6 +51,14 @@ const DownloadSection: React.FC<DownloadSectionProps> = ({ onDownload, onRegener
<Text>🎨 </Text>
</View>
)}
{showImageToVideo && onImageToVideo && (
<View
className={`regenerate-btn ${imageToVideoLoading ? 'disabled' : ''}`}
onClick={imageToVideoLoading ? undefined : onImageToVideo}
>
<Text>{imageToVideoLoading ? '🎬 生成中...' : '🎬 图片生视频'}</Text>
</View>
)}
<Text className='download-tip'>{getTipText()}</Text>
</View>
)

View File

@ -1,13 +1,16 @@
import { View, Image, Video } from '@tarojs/components'
import { useEffect, useState } from 'react'
import { saveImageToPhotosAlbum, saveVideoToPhotosAlbum, downloadFile, showToast, navigateBack, getCurrentInstance, hideToast } from '@tarojs/taro'
import { saveImageToPhotosAlbum, saveVideoToPhotosAlbum, navigateTo, downloadFile, showToast, navigateBack, getCurrentInstance, hideToast } from '@tarojs/taro'
import DownloadSection from '../../components/DownloadSection'
import { useAd } from '../../hooks/useAd'
import { useServerSdk } from '../../hooks/index'
import './index.css'
const ResultPage: React.FC = () => {
const [images, setImages] = useState<string[]>([])
const [mediaType, setMediaType] = useState<'image' | 'video'>('image')
const [loading, setLoading] = useState(false)
const serverSdk = useServerSdk()
// 集成广告钩子
const { showAd, loading: adLoading, adAvailable } = useAd({
onReward: () => {
@ -162,7 +165,7 @@ const ResultPage: React.FC = () => {
// 提取扩展名
const extensionMatch = fileName.match(/\.([^.]+)$/)
const extension = extensionMatch ? extensionMatch[1].toLowerCase() : ''
return { fileName, extension, cleanUrl }
}
@ -187,7 +190,7 @@ const ResultPage: React.FC = () => {
hideToast()
// 使用实际的文件路径
const filePath = downloadRes.tempFilePath
showToast({ title: '保存中...', icon: 'loading' })
// 根据实际文件类型选择保存方法
if (mediaType === 'video') {
@ -249,6 +252,49 @@ const ResultPage: React.FC = () => {
navigateBack()
}
// 图片生视频
const handleImageToVideo = async () => {
if (mediaType !== 'image' || !images[0]) {
showToast({
title: '仅支持图片生成视频',
icon: 'error',
duration: 2000
})
return
}
try {
setLoading(true)
showToast({
title: '正在生成视频...',
icon: 'loading',
duration: 60000
})
const taskId = await serverSdk.executeTemplate({
imageUrl: images[0],
templateCode: 'character_figurine_v1'
})
hideToast()
// 跳转到生成页面
navigateTo({
url: `/pages/generate/index?taskId=${taskId}&templateCode=character_figurine_v1`
})
} catch (error) {
hideToast()
console.error('图片生视频失败:', error)
showToast({
title: '生成失败,请重试',
icon: 'error',
duration: 2000
})
} finally {
setLoading(false)
}
}
// 兼容原有的多图片显示
if (!images.length) {
@ -287,8 +333,11 @@ const ResultPage: React.FC = () => {
<DownloadSection
onDownload={showAd}
onRegenerate={handleRegenerate}
onImageToVideo={handleImageToVideo}
loading={adLoading}
adAvailable={adAvailable}
showImageToVideo={mediaType === 'image'}
imageToVideoLoading={loading}
/>
</View>
)