Explorar el Código

feat: 那间支持删除

王晓东 hace 1 mes
padre
commit
df0b691d3f

+ 1 - 1
src/components/AgentPage/components/SummaryBar/index.tsx

@@ -75,7 +75,7 @@ export default ({agent, isVisitor}: IProps) => {
             <View className="flex items-start mb-24">
               <View className="flex flex-col flex-1">
                 <View className="flex items-end gap-8">
-                  <View className="text-24 font-medium leading-32">{agent?.name}</View>
+                  <View className="text-24 font-medium leading-32 truncate max-w-180">{agent?.name}</View>
                   <View className="text-12 leading-20">{agent?.position ?? ''}</View>
                 </View>
                 <View className="flex items-center gap-2">

+ 17 - 0
src/components/buttons/ButtonMain.tsx

@@ -0,0 +1,17 @@
+import { View } from "@tarojs/components";
+
+interface IProps {
+  onClick: ()=> {}
+  disabled?: boolean
+  children: JSX.Element|JSX.Element[]|string
+}
+export default function ButtonMain({ onClick, disabled = false, children }:IProps) {
+  const handleClick = ()=> {
+    if(!disabled){
+      onClick()
+    }
+  }
+  return (
+    <View className={`button-rounded button-primary flex-1 ${disabled ? 'opacity-50': ''}`} onClick={handleClick}>{children}</View>
+  );
+}

+ 6 - 0
src/components/list/card-list-item/index.tsx

@@ -10,6 +10,7 @@ interface Props {
   rightRenderer?: () => JSX.Element[] | JSX.Element;
   className?: string,
   onClick?: () => void;
+  onLongPress?: ()=> void;
   underline?: boolean;
 }
 export default ({
@@ -19,15 +20,20 @@ export default ({
   leftRenderer,
   rightRenderer,
   onClick,
+  onLongPress,
   children,
 }: Props) => {
   const handleClick = () => {
     onClick && onClick();
   };
+  const handleLongPress = () => {
+    onLongPress && onLongPress();
+  };
   return (
     <View
       className={`flex w-full bg-white gap-12 ${className}`}
       onClick={handleClick}
+      onLongPress={handleLongPress}
     >
       {leftRenderer && <View className="flex items-center justify-center">{leftRenderer()}</View>}
       <View className={`${

+ 18 - 13
src/components/wemeta-input/index.tsx

@@ -1,7 +1,7 @@
-import { View, Input, ITouchEvent, InputProps } from "@tarojs/components";
+import { View, Input, InputProps } from "@tarojs/components";
 import style from "./index.module.less";
 import { useState, useRef } from "react";
-
+import { countCharacters, getStrByMaxLength } from "@/utils/index";
 interface Props {
   placeholder?: string;
   value: string;
@@ -14,6 +14,7 @@ interface Props {
   cursorSpacing?: number;
   extraStyle?: Record<string, string>;
   adjustPosition?: boolean
+  maxlength?: number;
 }
 let isInbox = false;
 const index = ({
@@ -28,20 +29,23 @@ const index = ({
   prefix,
   suffix,
   adjustPosition,
+  maxlength
 }: Props) => {
   const [focus, setFocus] = useState(false);
   const inputRef = useRef(null); // 创建一个 ref
 
-  // const handleClear = (e: ITouchEvent) => {
-  //   isInbox = true;
-  //   e.stopPropagation();
-  //   e.preventDefault();
-  //   onInput("");
-  //   setFocus(true);
-
-  //   //@ts-ignore
-  //   inputRef.current && inputRef.current.focus();
-  // };
+  const handleInput = (value: string) => {
+    const len = countCharacters(value);
+    if (maxlength && len > maxlength) {
+      const r = getStrByMaxLength(value, maxlength);
+      // const slicedValue = value.slice(0, value.length)
+      // setText(r);
+      onInput && onInput(r);
+      return;
+    }
+    // setText(value);
+    onInput && onInput(value);
+  };
   const handleFocus = () => {
     isInbox = false;
     setFocus(true);
@@ -70,7 +74,7 @@ const index = ({
           ref={inputRef}
           type="text"
           adjustPosition={adjustPosition}
-          onInput={(e: any) => onInput(e.target.value)}
+          onInput={(e: any) => handleInput(e.target.value)}
           placeholder={placeholder}
           placeholderStyle="rgba(0,0,0,.05)"
           className={style.textInput}
@@ -79,6 +83,7 @@ const index = ({
           cursorSpacing={cursorSpacing}
           confirmType={confirmType}
           disabled={disabled}
+          maxlength={10000}
           onConfirm={(e: any) => {
             onConfirm && onConfirm(e.detail.value);
           }}

+ 2 - 2
src/components/wemeta-textarea/index.tsx

@@ -123,13 +123,13 @@ const index = ({
             onConfirm && onConfirm(e.detail.value);
           }}
         />
-        <View className={`${style.textareaButtons} justify-end`}>
+        <View className={`${style.textareaButtons} justify-end gap-8`}>
           {ai && renderAIButton()}
 
           {extra && extra()}
           {/* <View className={`button-rounded-mini ${!value.length ? 'disabled' :''}`} onClick={handleClear}>清除</View> */}
           {maxlength && (
-            <View>
+            <View className="text-gray-45">
               {maxlength}/{countCharacters(value)}
             </View>
           )}

+ 0 - 1
src/hooks/useEditContactCard.ts

@@ -2,7 +2,6 @@ import Taro, { useRouter } from "@tarojs/taro";
 import { useState } from "react";
 import { useAgentStore } from "@/store/agentStore";
 import { TAgentDetail } from "@/types/agent";
-import { pickNonEmpty } from "@/utils";
 
 const useEditContactCard = (
   editKey: string,

+ 1 - 1
src/pages/agent/components/AgentSetting/components/AgentContactCard/index.tsx

@@ -15,7 +15,7 @@ export default () => {
   return(
     <View className={style.container}>
       <View className={style.header}>
-        <View className={style.name}>{agent?.name}</View>
+        <View className={`${style.name} truncate`}>{agent?.name}</View>
         <View className={style.icons}>
           <ContactIcon type="phone" actived={!!agent?.mobile}></ContactIcon>
           <ContactIcon type="mail" actived={!!agent?.email}></ContactIcon>

+ 2 - 3
src/pages/editor-contact/index.tsx

@@ -8,7 +8,6 @@ import CardListItem from "@/components/list/card-list-item";
 import Taro, { useRouter } from "@tarojs/taro";
 import { useAgentStore } from "@/store/agentStore";
 import { TAgentDetail } from "@/types/agent";
-import useEditContactCard from "@/hooks/useEditContactCard";
 const  RenderEntCard = (agent: TAgentDetail|null, navToUrl: (url: string)=>void) => {
   if(!agent?.entName){
     return <></>
@@ -58,9 +57,9 @@ export default function Index() {
         <CardList>
           <View className="py-16 px-20 flex flex-col gap-20">
             <CardListItem underline arrow onClick={()=> navToUrl(`/pages/editor-pages/editor-name/index?agentId=${agentId}`)}>
-              <View className="flex items-center font-normal pb-16">
+              <View className="flex items-center font-normal pb-16 truncate">
                 <View className="flex-1 font-normal">姓名</View>
-                <View className="text-gray-65 mr-8">{agent?.name}</View>
+                <View className="text-gray-65 mr-8 truncate max-w-160">{agent?.name}</View>
               </View>
             </CardListItem>
             <CardListItem underline arrow onClick={()=> navToUrl(`/pages/editor-pages/editor-phone/index?agentId=${agentId}`)}>

+ 1 - 0
src/pages/editor-pages/editor-greeting-questions/index.tsx

@@ -71,6 +71,7 @@ export default function Index() {
                 value={item.value}
                 onInput={(value: string) => handleChange(item.id, value)}
                 placeholder="请输入"
+                maxlength={50}
               />
             </View>
           );

+ 7 - 5
src/pages/editor-pages/editor-greeting/index.tsx

@@ -5,6 +5,8 @@ import NavBarNormal from "@/components/nav-bar-normal/index";
 import WemetaTextarea from "@/components/wemeta-textarea/index";
 import { useAgentStore } from "@/store/agentStore";
 import useEditAgent from "@/hooks/useEditAgent";
+import BottomBar from "@/components/BottomBar";
+import ButtonMain from "@/components/buttons/ButtonMain";
 export default function Index() {
 
 const agent = useAgentStore((state)=> state.agent)  
@@ -20,15 +22,15 @@ const {handleSubmit, onChange, value} = useEditAgent('greeting', agent?.greeting
               onBlur={(value: string) => onChange(value)}
               onInput={(value: string) => onChange(value)}
               placeholder="碰到TA之后,第一句话想说什么?"
+              maxlength={200}
               autoFocus
               ai
             />
         </View>
-        <View className="bottom-bar" onClick={handleSubmit}>
-          <View className="pt-12 px-20">
-            <View className={`button-rounded button-primary`}>保存</View>
-          </View>
-        </View>
+
+        <BottomBar>
+          <ButtonMain disabled={!value.length} onClick={handleSubmit}>保存</ButtonMain>
+        </BottomBar>  
       </View>
     </PageCustom>
   );

+ 3 - 2
src/pages/editor-pages/editor-name/index.tsx

@@ -3,7 +3,7 @@ import { View } from "@tarojs/components";
 
 import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
-import editorStyle from "../editor.module.less";
+import ButtonMain from "@/components/buttons/ButtonMain";
 import BottomBar from "@/components/BottomBar";
 
 import WemetaTextarea from "@/components/wemeta-textarea/index";
@@ -28,10 +28,11 @@ export default function Index() {
             onInput={(value: string) => onChange(value)}
             placeholder="填写姓名"
             autoFocus
+            maxlength={20}
           />
         </View>
         <BottomBar>
-          <View className="button-rounded button-primary flex-1" onClick={handleSubmit}>保存</View>
+          <ButtonMain disabled={!value.length} onClick={handleSubmit}>保存</ButtonMain>
         </BottomBar>
       </View>
     </PageCustom>

+ 2 - 4
src/pages/editor-pages/editor-personality/index.tsx

@@ -1,12 +1,10 @@
-import { useState } from "react";
 import { View } from "@tarojs/components";
 
 import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
-import editorStyle from "../editor.module.less";
+import ButtonMain from "@/components/buttons/ButtonMain";
 import BottomBar from "@/components/BottomBar";
 import WemetaTextarea from "@/components/wemeta-textarea/index";
-import Taro, {useRouter, useUnload} from "@tarojs/taro";
 import { useAgentStore } from "@/store/agentStore";
 import useEditAgent from "@/hooks/useEditAgent";
 
@@ -35,7 +33,7 @@ export default function Index() {
           </View>
         
         <BottomBar>
-          <View className="button-rounded button-primary flex-1" onClick={handleSubmit}>保存</View>
+          <ButtonMain disabled={!value.length} onClick={handleSubmit}>保存</ButtonMain>
         </BottomBar>
       </View>
     </PageCustom>

+ 53 - 6
src/pages/voice/components/MyVoiceList/index.tsx

@@ -13,8 +13,10 @@ import { useVoiceStore } from "@/store/voiceStore";
 import { EVoiceStatus, TVoiceItem } from "@/types/voice";
 import { TAgentDetail } from "@/types/agent";
 
-import { getVoiceStatus } from "@/service/voice";
+import { deleteVoice, getVoiceStatus } from "@/service/voice";
 import ThinkingAnimation from "@/components/think-animation";
+import { useModalStore } from "@/store/modalStore";
+import { isSuccess } from "@/utils";
 
 interface Props {
   agent: TAgentDetail | null;
@@ -30,10 +32,11 @@ type TTask = {
 export default ({ onPlay, agent }: Props) => {
   const intervalRef = useRef<NodeJS.Timeout | null>(null);
   const [show, setShow] = useState(false);
-  
+  const {showModal} = useModalStore()  
 
   const { getVoices } = useVoiceStore();
   const myVoices = useVoiceStore((state) => state.myVoices);
+  const voices = useVoiceStore((state) => state.voices);
 
   // {
   //   message: '生成中',
@@ -42,6 +45,33 @@ export default ({ onPlay, agent }: Props) => {
   // }
   const [cloning, setCloning] = useState<TTask>();
 
+  //获取一个默认声音
+  const getDefaultVoice = ()=> {
+    // 优先使用我的声音
+    if(myVoices.length){
+      return myVoices[0]
+    }
+    // 其次使用系统声音
+    const systemVoices = voices.filter((item)=> item.isSystem)
+    if(systemVoices.length){
+      return systemVoices[0] 
+    }
+    return null
+  }
+
+  // 检查需要不要改变默认声音
+  const syncDefaultVoice = (item: TVoiceItem)=> {
+    // 说明删除的声音是当前使用的声音
+    if(agent?.voiceId === item.voiceId){
+      // 需要默认找一个声音
+      const defaultVoice = getDefaultVoice()
+      if(defaultVoice){
+        handleSelect(defaultVoice)
+      }
+    }
+    
+  }
+
   const handleSelect = (item: TVoiceItem) => {
     if (item.status == EVoiceStatus.DONE) {
       if (item.voiceName) {
@@ -49,6 +79,21 @@ export default ({ onPlay, agent }: Props) => {
       }
     }
   };
+  const handleLongPress = (item: TVoiceItem) => {
+    if(voices.length <= 1){
+      return;
+    }
+    showModal({
+      content: '确认删除该声音?',
+      onConfirm: async () => {
+        const response = await deleteVoice(item.voiceId)
+        if(isSuccess(response.status)){
+          await getVoices();
+          syncDefaultVoice(item);
+        }
+      }
+    })
+  };
 
   // 克隆按钮状态
   const handleCloneStatus = (status: ECloneStatus) => {
@@ -141,7 +186,6 @@ export default ({ onPlay, agent }: Props) => {
   const renderItem = (item) => {
     if (item.taskId) {
       return <CardListItem
-        className="pb-16"
         underline
         leftRenderer={() => {
           return (
@@ -157,7 +201,6 @@ export default ({ onPlay, agent }: Props) => {
 
     return (
       <CardListItem
-        className="pb-16"
         underline
         leftRenderer={() => {
           return (
@@ -169,9 +212,13 @@ export default ({ onPlay, agent }: Props) => {
         rightRenderer={() => {
           return renderRightColumn(item);
         }}
+        onLongPress={()=> handleLongPress(item)}
         onClick={() => handleSelect(item)}
       >
-        <View className="flex items-center h-full ">{item.voiceName}</View>
+        <View className="flex flex-col gap-4 py-16">
+          <View className="flex items-center leading-22">{item.voiceName}</View>
+          <View className="text-12 text-gray-45 leading-20">{item.createTime.slice(0,7)}创建</View>
+        </View>
       </CardListItem>
     );
   };
@@ -184,7 +231,7 @@ export default ({ onPlay, agent }: Props) => {
       return <EmptyData></EmptyData>;
     }
     return (
-      <View className="py-12 px-16">
+      <View className="px-16 flex flex-col w-full">
         {voices.map((item, _index) => {
           return renderItem(item);
         })}

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

@@ -85,7 +85,10 @@ const VoiceTabs: React.FC<Props> = ({}) => {
 
   // 设置当前播放器的播放音频信息
   const setPlayerItem = async (voiceItem: TVoiceItem, type: "system" | "cloned") => {
-    playerRef.current && playerRef.current.stop();
+    if(playerRef.current){
+      playerRef.current.stop();
+      playerRef.current.play(voiceItem.voiceUrl)
+    }
     setSysVoice(voiceItem);
     saveAgentVoiceId(voiceItem)
   };

+ 1 - 1
src/service/voice.ts

@@ -17,7 +17,7 @@ export const cloneVoice = (data: {
 
 // 删除指定克隆的音色
 export const deleteVoice = (voiceId: string)=> {
-  return request.delete(`${bluebookAiAgent}api/v1/voice/clone/${voiceId}`)
+  return request.delete(`${bluebookAiAgent}api/v1/my/voice/${voiceId}`)
 }
 
 // 获取指定克隆的音色记录--用于状态轮询

+ 4 - 4
src/store/agentStore.ts

@@ -73,11 +73,11 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
     return [];
   },
   fetchAgent: async (agentId: string, shareKey?:string) => {
-    const { agents } = get()
+    // const { agents } = get()
     // 如果自己的智能体列表中有 对应的 agentId,则请求自己的 agent, 否则请求无需登录的 getAgent 接口
-    const isSelf = !!agents.find((item)=> item.agentId === agentId)
-    const req = isSelf ? _getMyAgent : _getAgent; 
-    const response = await req(agentId, shareKey);
+    // const isSelf = !!agents.find((item)=> item.agentId === agentId)
+    // const req = isSelf ?  : _getAgent; 
+    const response = await _getMyAgent(agentId);
     const result = isSuccess(response.status)
     if (result && response.data) {
       const agent = response.data;

+ 0 - 1
src/utils/index.ts

@@ -233,7 +233,6 @@ export const getStrByMaxLength = (str: string, length: number) => {
       l += 0.5;
     }
     result += s;
-    console.log(l, length);
     if (Math.ceil(l) >= length) {
       return result;
     }