|
@@ -7,28 +7,48 @@ import { getUploadedAvatarStatus, genAvatarVideo, type TAvatarItem } from '@/ser
|
|
|
import useSWR from 'swr';
|
|
|
import Taro from "@tarojs/taro";
|
|
|
import { isSuccess } from "@/utils";
|
|
|
+import ButtonMain from '@/components/buttons/ButtonMain'
|
|
|
interface IProps {
|
|
|
prev: () => void;
|
|
|
next: () => void;
|
|
|
setPickedAvatar: (pickedAvatar: TAvatarItem)=> void
|
|
|
+ avatars: TAvatarItem[],
|
|
|
+ videos: TAvatarItem[],
|
|
|
+ setAvatars: (avatars: TAvatarItem[])=> void
|
|
|
+ setVideos: (avatars: TAvatarItem[])=> void
|
|
|
taskId: string|number
|
|
|
}
|
|
|
-export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }: IProps) {
|
|
|
+export default React.memo(function Index({ prev, next, taskId, avatars, videos, setVideos, setAvatars, setPickedAvatar }: IProps) {
|
|
|
const [currentSwiperIndex, setCurrentSwiperIndex] = useState(0);
|
|
|
- const [avatars, setAvatars] = useState<TAvatarItem[]>([]);
|
|
|
const [shouldPoll, setShouldPoll] = useState(false);
|
|
|
- const [videoGen, setVideoGen] = useState(false);
|
|
|
+ const [videoGenerating, setVideoGenerating] = useState(false);
|
|
|
const [currentTaskId, setCurrentTaskId] = useState<string|number>(taskId);
|
|
|
+
|
|
|
+ const avatarsList = (videoGenerating) ? videos : avatars
|
|
|
|
|
|
const goNext = () => {
|
|
|
- const pickedAvatar = avatars[currentSwiperIndex]
|
|
|
+ const pickedAvatar = avatarsList[currentSwiperIndex]
|
|
|
+ console.log(avatarsList, currentSwiperIndex, 11111, pickedAvatar)
|
|
|
setPickedAvatar(pickedAvatar)
|
|
|
console.log(pickedAvatar)
|
|
|
next()
|
|
|
}
|
|
|
+
|
|
|
+ const handlePrev = () => {
|
|
|
+ // 如果是生成微视频后,点击的上一步,则退回到生成微视频前
|
|
|
+ if(videoGenerating){
|
|
|
+ setVideoGenerating(false)
|
|
|
+ setVideos([])
|
|
|
+ }else{
|
|
|
+ setShouldPoll(false);
|
|
|
+ // 否则退回到生成 ai 图片的第一步
|
|
|
+ prev()
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
Taro.hideLoading()
|
|
|
|
|
|
+ // 隔 3 秒轮询生成微视频任务
|
|
|
const { data, mutate } = useSWR(
|
|
|
shouldPoll ? `getUploadedAvatarStatus${currentTaskId}` : null,
|
|
|
()=> getUploadedAvatarStatus(currentTaskId),
|
|
@@ -50,7 +70,12 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
|
|
|
useEffect(()=> {
|
|
|
if(data?.data.status === 'success'){
|
|
|
- setAvatars(data.data?.data.reverse())
|
|
|
+ const results = data.data?.data
|
|
|
+ if(videoGenerating){
|
|
|
+ setVideos(results)
|
|
|
+ }else{
|
|
|
+ setAvatars(results)
|
|
|
+ }
|
|
|
setShouldPoll(false);
|
|
|
}
|
|
|
if(data?.data.status === 'process_fail'){
|
|
@@ -61,6 +86,10 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
}
|
|
|
}, [data])
|
|
|
|
|
|
+ useEffect(()=> {
|
|
|
+ setShouldPoll(true);
|
|
|
+ }, [taskId])
|
|
|
+
|
|
|
|
|
|
const genVideo = async () => {
|
|
|
const a = avatars[currentSwiperIndex]
|
|
@@ -68,10 +97,12 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
return
|
|
|
}
|
|
|
const avatarUrl = a.avatarUrl
|
|
|
- setVideoGen(true)
|
|
|
+ setVideoGenerating(true)
|
|
|
// 清空 useSWR 缓存
|
|
|
mutate(undefined, false);
|
|
|
- setAvatars([]);
|
|
|
+ // 清空上一次可能生成的 videos
|
|
|
+ setVideos([])
|
|
|
+ setCurrentSwiperIndex(0)
|
|
|
const response = await genAvatarVideo({avatarUrl})
|
|
|
if(isSuccess(response.status)){
|
|
|
setCurrentTaskId(response.data.taskId)
|
|
@@ -82,6 +113,7 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
|
|
|
const onSwiperChange = (e: any) => {
|
|
|
const i = e.detail.current;
|
|
|
+ console.log(i)
|
|
|
setCurrentSwiperIndex(i);
|
|
|
};
|
|
|
|
|
@@ -90,7 +122,7 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
return (
|
|
|
<>
|
|
|
<View className={style.indicatorContainer}>
|
|
|
- {avatars.map((_item, index) => {
|
|
|
+ {avatarsList.map((_item, index) => {
|
|
|
return (
|
|
|
<View
|
|
|
key={index}
|
|
@@ -119,7 +151,7 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
current={currentSwiperIndex}
|
|
|
onChange={(e) => onSwiperChange(e)}
|
|
|
>
|
|
|
- {avatars.map(avatar => {
|
|
|
+ {avatarsList.map(avatar => {
|
|
|
return <SwiperItem>
|
|
|
<View className={style.swiperItem}>
|
|
|
<AvatarMedia source={avatar.avatarUrl} className="w-full h-full" />
|
|
@@ -143,8 +175,7 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
|
|
|
|
|
|
const renderProcessingStatus = () => {
|
|
|
- const targetText = !videoGen ? 'AI' : '视频'
|
|
|
-
|
|
|
+ const targetText = !videoGenerating ? 'AI' : '视频'
|
|
|
if(data?.data.status === 'process_fail'){
|
|
|
return <View className="gradient-text">{`${targetText}生成失败`}</View>
|
|
|
}
|
|
@@ -155,7 +186,7 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
}
|
|
|
|
|
|
const renderContent = ()=> {
|
|
|
- if(avatars.length){
|
|
|
+ if((avatars.length && !videoGenerating) || (videos.length)){
|
|
|
|
|
|
return renderSwipers()
|
|
|
}
|
|
@@ -177,16 +208,10 @@ export default React.memo(function Index({ prev, next, taskId, setPickedAvatar }
|
|
|
</View>
|
|
|
|
|
|
<View className="bottom-bar">
|
|
|
- <View className="grid grid-cols-3 gap-8 px-20 py-12">
|
|
|
- <View className={`button-rounded`} onClick={prev}>
|
|
|
- 上一步
|
|
|
- </View>
|
|
|
- <View className={`button-rounded ${avatars.length ? '' : 'opacity-20'}`} onClick={genVideo}>
|
|
|
- 生成微视频
|
|
|
- </View>
|
|
|
- <View className={`button-rounded primary ${avatars.length ? '' : 'opacity-20'}`} onClick={()=> goNext()}>
|
|
|
- 使用这张
|
|
|
- </View>
|
|
|
+ <View className="flex items-center gap-8 px-20 py-12">
|
|
|
+ <ButtonMain type="normal" disabled={videoGenerating && !videos.length} className="w-[76px]" onClick={handlePrev}>上一步</ButtonMain>
|
|
|
+ {!videoGenerating && <ButtonMain className="flex-1" type="normal" onClick={genVideo} disabled={!avatars.length} >生成微视频</ButtonMain> }
|
|
|
+ <ButtonMain className="flex-1" onClick={goNext} disabled={(!avatars.length && !videoGenerating) || (videoGenerating && !videos.length )} >使用这张</ButtonMain>
|
|
|
</View>
|
|
|
</View>
|
|
|
</View>
|