Sfoglia il codice sorgente

feat: 对接系统声音列表分页

王晓东 1 mese fa
parent
commit
bded2c073a

+ 9 - 15
src/pages/voice/components/my-voice/index.tsx

@@ -7,8 +7,7 @@ import { CloneVoiceStatus } from "@/consts/enum";
 import IconWave from "@/images/icon-wave-20.png";
 import { voiceCloneConfirm } from "@/service/character";
 import { useAppStore } from "@/store/appStore";
-import { useCharacterStore } from "@/store/characterStore";
-import { ICharacter, TEntityVoiceCloneRecord } from "@/types";
+import { ICharacter } from "@/types";
 import { formatDateFull, getCloneVoiceIdentifier } from "@/utils/index";
 import { Image, View } from "@tarojs/components";
 import { useEffect, useRef, useState } from "react";
@@ -22,11 +21,10 @@ import { EVoiceStatus, TVoiceItem } from "@/types/voice";
 interface Props {
   value?: ICharacter;
   setValue?: (value: ICharacter) => void;
-  profileId: string;
   onPlay?: (voice: any) => void;
 }
 
-export default ({ profileId, onPlay }: Props) => {
+export default ({ onPlay }: Props) => {
   const playerRef = useRef<IVoicePlayerBar>(null);
   const intervalRef = useRef<NodeJS.Timeout | null>(null);
   const [show, setShow] = useState(false);
@@ -41,14 +39,13 @@ export default ({ profileId, onPlay }: Props) => {
   //   useCharacterStore();
   const {getVoices} = useVoiceStore()
   const voices = useVoiceStore(state => state.voices)
-  const character = useCharacterStore((state) => state.character);
   const myVoices = useVoiceStore(state => state.myVoices)
   const appConfig = useAppStore((state) => state.appConfig);
 
   
   
 
-  const handleSelect = (item: TEntityVoiceCloneRecord, index: number) => {
+  const handleSelect = (item: TVoiceItem, index: number) => {
     setVoiceIndex(index);
 
     if (item.status == CloneVoiceStatus.CloneVoiceStatusSuccess) {
@@ -57,7 +54,6 @@ export default ({ profileId, onPlay }: Props) => {
         onPlay &&
           onPlay({
             voiceName: item.voiceName,
-            voiceAlias: item.voiceAlias,
             voiceIndex: index,
           });
       }
@@ -77,14 +73,12 @@ export default ({ profileId, onPlay }: Props) => {
   };
 
   const fetchVoiceList = async () => {
-    if (profileId) {
-      await getVoices();
-      const result = voices.find((item) => !item.isSystem && item.status === 'processing');
-      if (result) {
-        intervalRef.current = setTimeout(() => fetchVoiceList(), 3000);
-      } else {
-        stopTimer();
-      }
+    await getVoices();
+    const result = voices.find((item) => !item.isSystem && item.status === 'processing');
+    if (result) {
+      intervalRef.current = setTimeout(() => fetchVoiceList(), 3000);
+    } else {
+      stopTimer();
     }
   };
 

+ 83 - 12
src/pages/voice/index.tsx

@@ -14,8 +14,8 @@ import { useVoiceStore } from "@/store/voiceStore";
 interface Props {}
 type ExtendedTServiceAudioModel = TServiceAudioModel & { checked: boolean };
 const VoiceTabs: React.FC<Props> = ({}) => {
-const playerRef = useRef<IVoicePlayerBar>(null);
-const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
+  const playerRef = useRef<IVoicePlayerBar>(null);
+  const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
     null
   );
 
@@ -25,18 +25,55 @@ const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
   const router = useRouter();
   const profileId = router.params.profileId || "";
 
-  const {voices, isLoading, pagination, getVoices, setPagination} = useVoiceStore()
+  const {
+    voices,
+    femaleVoices,
+    femalePagination,
+    maleVoices,
+    malePagination,
+    isLoading,
+    pagination,
+    getVoices,
+    getFemaleVoices,
+    getMaleVoices,
+    setPagination,
+    setMalePagination,
+    setFemalePagination,
+    
+  } = useVoiceStore();
 
   const handleScrollEnd = () => {
-    if(isLoading){
+    if (isLoading) {
       return;
     }
     setPagination({ pageIndex: pagination.pageIndex + 1 });
-  }
+  };
+
+  useEffect(() => {
+    getVoices();
+  }, []);
+
+  // 获取女声列表
+  useEffect(() => {
+    getFemaleVoices();
+  }, []);
+
+  // 获取男声列表
+  useEffect(() => {
+    getMaleVoices();
+  }, []);
+
+  // 处理滚动加载更多
+  const handleFemaleScrollEnd = () => {
+    if (isLoading) return;
+    setFemalePagination({ pageIndex: femalePagination.pageIndex + 1 });
+  };
 
-  useEffect(()=> {
-    getVoices()
-  }, [])
+  // 处理滚动加载更多
+  const handleMaleScrollEnd = () => {
+    if (isLoading) return;
+    setMalePagination({ pageIndex: malePagination.pageIndex + 1 });
+  };
 
   const tabList = [
     {
@@ -44,7 +81,7 @@ const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
       key: "1",
       children: (
         <View className={style.tabContent}>
-          <MyVoice profileId={profileId}></MyVoice>
+          <MyVoice></MyVoice>
         </View>
       ),
     },
@@ -66,7 +103,7 @@ const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
               <AllVoice
                 list={voices}
                 onPlay={(item) => {
-                  handlePlayAction(item, 'system');
+                  handlePlayAction(item, "system");
                 }}
               ></AllVoice>
             </View>
@@ -79,7 +116,24 @@ const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
       key: "3",
       children: (
         <View className={style.tabContent}>
-          <View>female</View>
+          <ScrollView
+            scrollY
+            id="scrollView"
+            onScrollEnd={handleFemaleScrollEnd}
+            style={{
+              flex: 1,
+              height: "100%", // 高度自适应
+            }}
+          >
+            <View className="px-16 py-12">
+              <AllVoice
+                list={femaleVoices}
+                onPlay={(item) => {
+                  handlePlayAction(item, "system");
+                }}
+              ></AllVoice>
+            </View>
+          </ScrollView>
         </View>
       ),
     },
@@ -88,7 +142,24 @@ const [sysVoice, setSysVoice] = useState<ExtendedTServiceAudioModel | null>(
       key: "4",
       children: (
         <View className={style.tabContent}>
-          <View>male</View>
+          <ScrollView
+            scrollY
+            id="scrollView"
+            onScrollEnd={handleMaleScrollEnd}
+            style={{
+              flex: 1,
+              height: "100%", // 高度自适应
+            }}
+          >
+            <View className="px-16 py-12">
+              <AllVoice
+                list={maleVoices}
+                onPlay={(item) => {
+                  handlePlayAction(item, "system");
+                }}
+              ></AllVoice>
+            </View>
+          </ScrollView>
         </View>
       ),
     },

+ 3 - 3
src/service/voice.ts

@@ -5,14 +5,14 @@ import {
 import request from '@/xiaolanbenlib/module/axios.js'
 import Taro from '@tarojs/taro'
 
-import { TCloneVoiceResponse, TGetMyVoicesParams, TPaginatedVoiceResponse, TVoiceItem } from '@/types/storage'
+import { TGetMyVoicesParams, TPaginatedVoiceResponse, TVoiceItem } from '@/types/voice'
 
 // 克隆一个新的音色
 export const cloneVoice = (data: {
   sourceUrl: string // 源语音地址 ,
   voiceText?: string // 录音文案
 }) => {
-  return request.post<TCloneVoiceResponse>(`${bluebookAiAgent}api/v1/voice/clone`, data)
+  return request.post<TPaginatedVoiceResponse>(`${bluebookAiAgent}api/v1/voice/clone`, data)
 }
 
 // 删除指定克隆的音色
@@ -22,7 +22,7 @@ export const deleteVoice = (voiceId: string)=> {
 
 // 获取指定克隆的音色记录--用于状态轮询
 export const getVoiceStatus = (taskId: string) => {
-  return request.get<TCloneVoiceResponse>(`${bluebookAiAgent}api/v1/my/voice/${taskId}/status`)
+  return request.get<TPaginatedVoiceResponse>(`${bluebookAiAgent}api/v1/my/voice/${taskId}/status`)
 }
 
 // 获取个人录音音色库

+ 72 - 3
src/store/voiceStore.ts

@@ -1,6 +1,6 @@
 import { create } from "zustand";
 
-import { TGetMyVoicesParams, TVoiceItem, TPageination } from '@/types/storage'
+import { TGetMyVoicesParams, TVoiceItem, TPageination, TGender } from '@/types/voice'
 
 import {
   getVoices as _getVoices,
@@ -14,10 +14,18 @@ export interface StorageStoreState {
   // 初始状态
   voices: TVoiceItem[];
   myVoices: TVoiceItem[];
-  pagination: TPageination
+  maleVoices: TVoiceItem[];
+  femaleVoices: TVoiceItem[];
+  pagination: TPageination;
+  malePagination: TPageination;
+  femalePagination: TPageination;
   isLoading: boolean,
   getVoices: (params?: TGetMyVoicesParams) => Promise<boolean>;
+  getMaleVoices: (params?: TGetMyVoicesParams) => Promise<boolean>;
+  getFemaleVoices: (params?: TGetMyVoicesParams) => Promise<boolean>;
   setPagination: (params:any) => Promise<void>;
+  setMalePagination: (params:any) => Promise<void>;
+  setFemalePagination: (params:any) => Promise<void>;
   cloneVoice: (params: {
     sourceUrl: string // 源语音地址 ,
     voiceText?: string // 录音文案
@@ -27,6 +35,8 @@ export interface StorageStoreState {
 export const useVoiceStore = create<StorageStoreState>((set, get) => ({
   voices: [],
   myVoices: [],
+  maleVoices: [],
+  femaleVoices: [],
   pagination: {
     pageIndex: 1,
     pageSize: 10,
@@ -34,7 +44,20 @@ export const useVoiceStore = create<StorageStoreState>((set, get) => ({
     searchKey: '',
     extData: null,
   },
-  
+  malePagination: {
+    pageIndex: 1,
+    pageSize: 10,
+    totalCount: 0,
+    searchKey: '',
+    extData: null,
+  },
+  femalePagination: {
+    pageIndex: 1,
+    pageSize: 10,
+    totalCount: 0,
+    searchKey: '',
+    extData: null,
+  },
   isLoading: false,
   getVoices: async (params = {}) => {
     set({ isLoading: true });
@@ -56,6 +79,40 @@ export const useVoiceStore = create<StorageStoreState>((set, get) => ({
     });
     return isSuccess(response.status)
   },
+  getMaleVoices: async (params = {}) => {
+    set({ isLoading: true });
+    const currentPagination = get().malePagination;
+    const requestParams = { ...currentPagination, ...params, gender: 'male' as TGender };
+
+    const response = await _getVoices(requestParams)
+
+    set({
+      maleVoices: response.data.data,
+      malePagination: {
+        ...requestParams,
+        totalCount: response.data.totalCount,
+      },
+      isLoading: false
+    });
+    return isSuccess(response.status)
+  },
+  getFemaleVoices: async (params = {}) => {
+    set({ isLoading: true });
+    const currentPagination = get().femalePagination;
+    const requestParams = { ...currentPagination, ...params, gender: 'female' as TGender };
+
+    const response = await _getVoices(requestParams)
+
+    set({
+      femaleVoices: response.data.data,
+      femalePagination: {
+        ...requestParams,
+        totalCount: response.data.totalCount,
+      },
+      isLoading: false
+    });
+    return isSuccess(response.status)
+  },
   // 更新分页参数
   setPagination: async (params:any) => {
     set((state) => ({
@@ -64,6 +121,18 @@ export const useVoiceStore = create<StorageStoreState>((set, get) => ({
     // 可选:自动触发请求
     get().getVoices();
   },
+  setMalePagination: async (params:any) => {
+    set((state) => ({
+      malePagination: { ...state.malePagination, ...params },
+    }));
+    get().getMaleVoices();
+  },
+  setFemalePagination: async (params:any) => {
+    set((state) => ({
+      femalePagination: { ...state.femalePagination, ...params },
+    }));
+    get().getFemaleVoices();
+  },
   cloneVoice: async (params) => {
     const response = await _cloneVoice(params)
     console.log(response,444444) 

+ 4 - 4
src/types/voice.ts

@@ -47,9 +47,9 @@ export enum EVoiceType {
 }
 
 export type TGetMyVoicesParams = {
-  pageIndex: number,
-  pageSize: number,
-  type: EVoiceType,
-  gender: TGender,
+  pageIndex?: number,
+  pageSize?: number,
+  type?: EVoiceType,
+  gender?: TGender,
 }