Procházet zdrojové kódy

fix: 声音克隆任务

王晓东 před 1 měsícem
rodič
revize
bc47ac6de5

+ 1 - 1
src/components/custom-share/index.tsx

@@ -175,7 +175,7 @@ export default (props: Props) => {
     companyName.x = 0;
     companyName.y = 0;
     companyName.lineClamp = 1;
-    companyName.text = 'helloworld';
+    companyName.text = agent?.entName ?? '';
     companyName.wrapWidth = 160 * ratio;
     companyName.fontSize = 12 * ratio;
     companyName.color = "rgba(0, 0, 0, .45)";

+ 115 - 141
src/pages/voice/components/MyVoiceList/index.tsx

@@ -1,60 +1,47 @@
 import EmptyData from "@/components/empty-data";
 import CardListItem from "@/components/list/card-list-item/index";
-import CardList from "@/components/list/card-list/index";
-import { IVoicePlayerBar } from "@/components/voice-player-bar/index";
+
 import WemetaRadio from "@/components/wemeta-radio/index";
-import { CloneVoiceStatus } from "@/consts/enum";
 import IconWave from "@/images/icon-wave-20.png";
-import { useAppStore } from "@/store/appStore";
-import { ICharacter } from "@/types";
-import { formatDateFull } from "@/utils/index";
+
 import { Image, View } from "@tarojs/components";
 import { useEffect, useRef, useState } from "react";
 import Popup from "@/components/popup/popup";
 import PopupRecorder, { ECloneStatus } from "./components/popup-recorder/index";
-import PopupTryout from "./components/popup-tryout/index";
 import style from "./index.module.less";
 import { useVoiceStore } from "@/store/voiceStore";
 import { EVoiceStatus, TVoiceItem } from "@/types/voice";
 import { TAgentDetail } from "@/types/agent";
 
+import { getVoiceStatus } from "@/service/voice";
+
 interface Props {
-  agent: TAgentDetail|null
-  value?: ICharacter;
-  setValue?: (value: ICharacter) => void;
+  agent: TAgentDetail | null;
   onPlay?: (voice: any) => void;
 }
 
+type TTask = {
+  message: string;
+  status: "processing" | "success" | "process_fail";
+  taskId: string;
+};
+
 export default ({ onPlay, agent }: Props) => {
   const intervalRef = useRef<NodeJS.Timeout | null>(null);
   const [show, setShow] = useState(false);
-  const [popupType, setPopupType] = useState<"clone" | "try" | "reclone">(
-    "clone",
-  );
   
-  const {getVoices} = useVoiceStore()
-  const voices = useVoiceStore(state => state.voices)
-  const myVoices = useVoiceStore(state => state.myVoices)
-  const appConfig = useAppStore((state) => state.appConfig);
 
-  
-  
+  const { getVoices } = useVoiceStore();
+  const myVoices = useVoiceStore((state) => state.myVoices);
+
+  const [cloning, setCloning] = useState<TTask>();
 
   const handleSelect = (item: TVoiceItem) => {
     if (item.status == EVoiceStatus.DONE) {
       if (item.voiceName) {
-        // setVoiceName(item.voiceName);
-        onPlay &&
-          onPlay(item);
+        onPlay && onPlay(item);
       }
-      // save
     }
-
-    // if (item.status == CloneVoiceStatus.CloneVoiceStatusUnconfirmed) {
-    //   // 未确认,弹出试听框
-    //   setPopupType("try");
-    //   setShow(true);
-    // }
   };
 
   // 克隆按钮状态
@@ -62,31 +49,36 @@ export default ({ onPlay, agent }: Props) => {
     console.log(status);
   };
 
-  const fetchVoiceList = async () => {
-    await getVoices();
-    const result = voices.find((item) => !item.isSystem && item.status === 'processing');
-    if (result) {
-      intervalRef.current = setTimeout(() => fetchVoiceList(), 3000);
-    } else {
+  const fetchVoiceList = async (taskId: string) => {
+    const response = await getVoiceStatus(taskId);
+    console.log(response.data);
+    if (response.data.status === "processing") {
+      setCloning({
+        message: response.data.message,
+        status: response.data.status,
+        taskId: response.data.taskId,
+      });
+      intervalRef.current = setTimeout(() => fetchVoiceList(taskId), 3000);
+      return;
+    }
+    if (
+      response.data.status === "process_fail" ||
+      response.data.status === "success"
+    ) {
+      setCloning({
+        message: response.data.message,
+        status: response.data.status,
+        taskId: response.data.taskId,
+      });
       stopTimer();
+      getVoices();
     }
   };
 
-  // const handleSureAction = async () => {
-  //   setShow(false);
-  //   // await voiceCloneConfirm(myVoices[voiceIndex].voiceName!);
-  //   // fetchVoiceList();
-  // };
-
-  // const handleRecloneAction = () => {
-  //   setPopupType("reclone");
-  //   setShow(true);
-  // };
-
   // 声音录制完成
-  const onRecordEnd = (r: string) => {
-    console.log("onRecordEnd:", r);
-    fetchVoiceList();
+  const onRecordEnd = (taskId: string) => {
+    console.log("onRecordEnd:", taskId);
+    fetchVoiceList(taskId);
   };
 
   const stopTimer = () => {
@@ -96,24 +88,9 @@ export default ({ onPlay, agent }: Props) => {
     }
   };
 
-  const calcRemainCloneNum = () => {
-    if (appConfig?.maxCloneNum) {
-      // const clonedNum = myVoices.filter(
-      //   (item) =>
-      //     item.status === CloneVoiceStatus.CloneVoiceStatusSuccess ||
-      //     item.status === CloneVoiceStatus.CloneVoiceStatusUnconfirmed,
-      // ).length;
-      // const remainNum = appConfig.maxCloneNum - clonedNum;
-      // return remainNum < 0 ? 0 : remainNum;
-    }
-    return myVoices.length;
-  };
-
-  const initPage = async () => {
-    
-  };
-
-  
+  useEffect(() => {
+    getVoices();
+  }, []);
 
   // 清除定时器
   useEffect(() => {
@@ -122,67 +99,88 @@ export default ({ onPlay, agent }: Props) => {
     };
   }, []);
 
-
   // 克隆列表右侧操作栏
   const renderRightColumn = (item: TVoiceItem) => {
     if (item.status == EVoiceStatus.DONE) {
-      return <WemetaRadio checked={item.voiceId === agent?.voiceId}></WemetaRadio>;
+      return (
+        <View className="flex items-center h-full">
+          <WemetaRadio checked={item.voiceId === agent?.voiceId}></WemetaRadio>
+        </View>
+      );
     }
 
     return <></>;
   };
 
   // 克隆状态栏
-  const renderCloneStatus = (item: TVoiceItem) => {
-    if (item.status === EVoiceStatus.DONE) {
+  const renderCloneStatus = (item: TTask) => {
+    if (item.status === "success") {
       return (
-        <View className={`text-12 leading-20 text-gray-45`}>
-          {item.createTime && formatDateFull(new Date(item.createTime.replace(/-/g,'/')))}
-        </View>
+        <View className={`text-12 leading-20 text-green`}>{item.message}</View>
       );
     }
-    if (item.status === EVoiceStatus.DOING) {
-      return <View className={`text-12 leading-20 text-orange`}>生成中...</View>;
+    if (item.status === "processing") {
+      return (
+        <View className={`text-12 leading-20 text-primary`}>{item.message}</View>
+      );
     }
 
-    if (item.status == EVoiceStatus.FAILED) {
-      return <View className={`text-12 leading-20 text-orange`}>生成错误</View>;
+    if (item.status === "process_fail") {
+      return <View className={`text-12 leading-20 text-orange`}>{item.message}</View>;
     }
-    return <View>...</View>;
+    console.log(item.status)
+    return <></>;
+  };
+
+  const renderItem = (item) => {
+    if (item.taskId) {
+      return <CardListItem
+        className="pb-16"
+        underline
+        leftRenderer={() => {
+          return (
+            <View className={style.listIcon}>
+              <Image src={IconWave} className={style.iconImage}></Image>
+            </View>
+          );
+        }}
+      >
+        <View className="flex items-center h-full ">{renderCloneStatus(item)}</View>
+      </CardListItem>;
+    }
+
+    return (
+      <CardListItem
+        className="pb-16"
+        underline
+        leftRenderer={() => {
+          return (
+            <View className={style.listIcon}>
+              <Image src={IconWave} className={style.iconImage}></Image>
+            </View>
+          );
+        }}
+        rightRenderer={() => {
+          return renderRightColumn(item);
+        }}
+        onClick={() => handleSelect(item)}
+      >
+        <View className="flex items-center h-full ">{item.voiceName}</View>
+      </CardListItem>
+    );
   };
 
   // 渲染克隆列表
   const renderCloneList = () => {
-    if (!myVoices.length) {
+    //
+    const voices = cloning ? [cloning, ...myVoices] : myVoices;
+    if (!voices.length) {
       return <EmptyData></EmptyData>;
     }
     return (
-      <View className="py-12 px-16 gap-">
-        {myVoices.map((item, _index) => {
-          return (
-            <CardListItem
-             className="py-16"
-              underline
-              leftRenderer={()=> {
-                return <View className={style.listIcon}>
-                  <Image src={IconWave} className={style.iconImage}></Image>
-                </View>
-              }}
-              rightRenderer={() => {
-                return renderRightColumn(item);
-              }}
-              onClick={() => handleSelect(item)}
-            >
-              <View className="flex items-center gap-16">
-                <View className="flex flex-col gap-4">
-                  <View className={style.ListItemText}>
-                    {item.voiceName}
-                  </View>
-                  {renderCloneStatus(item)}
-                </View>
-              </View>
-            </CardListItem>
-          );
+      <View className="py-12 px-16">
+        {voices.map((item, _index) => {
+          return renderItem(item);
         })}
       </View>
     );
@@ -190,51 +188,27 @@ export default ({ onPlay, agent }: Props) => {
 
   return (
     <View className={`flex flex-col`}>
-      <View className="flex-1">
-        {/* <VoicePlayerBar
-          ref={playerRef}
-          voiceName={voiceName}
-          voiceNameText={createVoiceNameText(voiceName)}
-        /> */}
-
-        {renderCloneList()}
-      </View>
-
-      <Popup show={show} setShow={setShow}>
-        <View>
-          {(popupType == "clone" || popupType == "reclone") && (
-            <PopupRecorder
-              onRecordEnd={onRecordEnd}
-              show={show}
-              setShow={setShow}
-              setCloneStatus={(status) => handleCloneStatus(status)}
-            ></PopupRecorder>
-          )}
-          {/* {popupType == "try" && (
-            <PopupTryout
-              show={show}
-              onSure={handleSureAction}
-              onReclone={handleRecloneAction}
-              showName={getCloneVoiceIdentifier(voiceIndex + 1)}
-            ></PopupTryout>
-          )} */}
-        </View>
-      </Popup>
-
+      {renderCloneList()}
+      
       <View
         className={style.addButton}
         onClick={() => {
-          setPopupType("clone");
           setShow(true);
         }}
       >
         <View className="button-rounded-big font-medium">
           <View>添加克隆声音</View>
-          <View className="font-normal text-12 leading-0">
-            (剩{calcRemainCloneNum()}次)
-          </View>
         </View>
       </View>
+
+      <Popup show={show} setShow={setShow}>
+        <PopupRecorder
+          onRecordEnd={onRecordEnd}
+          show={show}
+          setShow={setShow}
+          setCloneStatus={(status) => handleCloneStatus(status)}
+        ></PopupRecorder>
+      </Popup>
     </View>
   );
 };

+ 0 - 1
src/pages/voice/index.tsx

@@ -3,7 +3,6 @@ import VoicePlayerBar, { IVoicePlayerBar } from "@/components/voice-player-bar";
 import VoiceList from "./components/VoiceList";
 import MyVoiceList from "./components/MyVoiceList/index";
 import { View, ScrollView } from "@tarojs/components";
-import { useRouter } from "@tarojs/taro";
 import React, { useEffect, useRef, useState } from "react";
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import style from "./index.module.less";

+ 1 - 1
src/service/voice.ts

@@ -22,7 +22,7 @@ export const deleteVoice = (voiceId: string)=> {
 
 // 获取指定克隆的音色记录--用于状态轮询
 export const getVoiceStatus = (taskId: string) => {
-  return request.get<TPaginatedVoiceResponse>(`${bluebookAiAgent}api/v1/my/voice/${taskId}/status`)
+  return request.get<TVoiceCloneResponse>(`${bluebookAiAgent}api/v1/my/voice/${taskId}/status`)
 }
 
 // 获取个人录音音色库

+ 5 - 5
src/types/voice.ts

@@ -26,11 +26,11 @@ export type TVoiceItem = {
 };
 
 export type TVoiceCloneResponse = {
-  "userId": string|number,
-  "taskId": string,
-  "status": string,
-  "message": string,
-  "data": null  
+  userId: string|number,
+  taskId: string,
+  status: 'processing'| 'success' |'process_fail',
+  message: string,
+  data: TVoiceItem  
 }
 
 // 分页获取音色列表