Jelajahi Sumber

fix: 接入文本润色功能

王晓东 2 minggu lalu
induk
melakukan
89b9cfb13d

+ 11 - 4
project.private.config.json

@@ -2,16 +2,23 @@
   "projectname": "bluebook",
   "setting": {
     "compileHotReLoad": true,
-    "urlCheck": false,
+    "urlCheck": true,
     "skylineRenderEnable": true
   },
   "condition": {
     "miniprogram": {
       "list": [
         {
-          "name": "pages/agent/index",
-          "pathName": "pages/agent/index",
-          "query": "",
+          "name": "pages/profile/index",
+          "pathName": "pages/profile/index",
+          "query": "agentId=p_2e73c9d7efaYfDo2-agent_991&shareKey=2%241%24AAAAwk3hSyfsx%20gEW1O0DrSt1JVBfT%20ATDQqwqvPP9Ebv6cgWG8%20mN0D7uu4of0o4RNPzsEXDTBD4jez44UKaARoVEkHXE2a6KiIH42aeIJSgot%2F",
+          "launchMode": "default",
+          "scene": null
+        },
+        {
+          "name": "pages/profile/index",
+          "pathName": "pages/profile/index",
+          "query": "agentId=e_d2201c7B73ac-B7d578aYKwLu-agent_213",
           "launchMode": "default",
           "scene": null
         },

+ 6 - 6
src/components/AgentPage/components/AgentSwap/index.tsx

@@ -48,12 +48,12 @@ export default ({ show, setShow }: IProps) => {
     loading = true;
     try{
       const response = await createAgent()
-      if(response?.agentId){
-        const result = await setDefaultAgent(response.agentId);
-        if (result) {
-          await fetchAgents();
-        }
-      }
+      // if(response?.agentId){
+      //   const result = await setDefaultAgent(response.agentId);
+      //   if (result) {
+      //     await fetchAgents();
+      //   }
+      // }
       Taro.hideLoading()
       loading = false;
       setShow(false)

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

@@ -42,7 +42,7 @@ export default ({agent, isVisitor}: IProps) => {
   }
 
   const confirmDelete = async () => {
-    if(agent.agentId){
+    if(agent?.agentId){
       await deleteAgent(agent.agentId)
     }
   }

+ 10 - 2
src/components/AgentPage/index.tsx

@@ -11,6 +11,7 @@ import ComponentList from "@/components/component-list";
 import { useUserStore } from "@/store/userStore";
 
 import style from './index.module.less'
+import { useDidShow } from "@tarojs/taro";
 
 
 interface IProps {
@@ -24,11 +25,18 @@ export default function Index({ agentId }: IProps) {
   const { setComponentList } = useComponentStore()
   const components = useComponentStore((state) => state.components);
 
-  useEffect(() => {
+  
+
+  useDidShow(()=> {
+    if (agentId) {
+      fetchAgent(agentId)
+    }
+  })
+  useEffect(()=> {
     if (agentId) {
       fetchAgent(agentId)
     }
-  }, [agentId]);
+  },[agentId])
 
   useEffect(()=> {
     // 过滤,1,允许显示,2、有 id 的组件防止有错误数据

+ 40 - 0
src/components/TextPolish/index.tsx

@@ -0,0 +1,40 @@
+import { View } from "@tarojs/components";
+import IconStarColor from "@/components/icon/icon-star-color";
+import { textPolishing } from '@/service/agent'
+import { isSuccess } from "@/utils";
+import Taro from "@tarojs/taro";
+
+interface Props {
+  text: string; 
+  type: "personality" | "greeting"
+  onPolished: (text:string|null) => void
+}
+const Index = ({
+  text,
+  type,
+  onPolished
+}: Props) => {
+  
+
+  const handleClick = async () => {
+    // console.log('请求服务端润色')
+    
+    Taro.showLoading()
+    const response = await textPolishing({
+      content: text,
+      type: type
+    })
+    Taro.hideLoading()
+    if(isSuccess(response.status)){
+      onPolished(response.data?.content)
+    }
+  }
+
+  return (
+    <View className="flex items-center gap-4" onClick={handleClick}>
+      <IconStarColor></IconStarColor>{" "}
+      <View className="gradient-text">润色</View>
+    </View>
+  );
+};
+export default Index;

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

@@ -75,7 +75,7 @@ export default forwardRef(({ agent }: Props, ref) => {
     if(!stage){
       return
     }
-    const avatarImg = agent.avatarUrl ?? DEFAULT_AVATAR
+    const avatarImg = agent.avatarLogo ?? DEFAULT_AVATAR
 
     const loader = new ImgLoader(stage.canvas, [
       {

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

@@ -91,7 +91,7 @@ export default (props: Props) => {
       return;
     }
 
-    let avatarImg = agent.avatarUrl ?? DEFAULT_AVATAR
+    let avatarImg = agent.avatarLogo ?? DEFAULT_AVATAR
     
     const card = new Container();
 

+ 0 - 16
src/components/wemeta-textarea/index.tsx

@@ -2,7 +2,6 @@ import { View, Textarea, InputProps } from "@tarojs/components";
 import style from "./index.module.less";
 import { useState, useRef, useEffect } from "react";
 import { countCharacters, getStrByMaxLength } from "@/utils/index";
-import IconStarColor from "@/components/icon/icon-star-color";
 interface Props {
   placeholder?: string;
   value: string;
@@ -81,19 +80,6 @@ const index = ({
     onInput && onInput(value);
   };
 
-  const handleClick = ()=> {
-    console.log('请求服务端润色')
-  }
-
-  const renderAIButton = () => {
-    return (
-      <View className="flex items-center gap-4" onClick={handleClick}>
-        <IconStarColor></IconStarColor>{" "}
-        <View className="gradient-text">润色</View>
-      </View>
-    );
-  };
-
   return (
     <View
       className={`${
@@ -124,8 +110,6 @@ const index = ({
           }}
         />
         <View className={`${style.textareaButtons} justify-end gap-8`}>
-          {ai && renderAIButton()}
-
           {extra && extra()}
           {/* <View className={`button-rounded-mini ${!value.length ? 'disabled' :''}`} onClick={handleClear}>清除</View> */}
           {maxlength && (

+ 9 - 4
src/pages/agent-gen/components/step/StepStart.tsx

@@ -20,10 +20,12 @@ export default React.memo(function StepStart({ next, setTaskId }: IProps) {
   const uploadedAvatarUrl = decodeURIComponent(avatarUrl ?? '')
   const [currentAvatarUrl, setCurrentAvatarUrl] = useState(uploadedAvatarUrl)
   const [value, setValue] = useState('');
-
+  const [loading, setLoading] = useState(false)
   const handleChange = () => {
+    setLoading(true)
     getNewAvatarPic((picUrl)=> {
-      setCurrentAvatarUrl(picUrl)
+      picUrl && setCurrentAvatarUrl(picUrl)
+      setLoading(false)
     })
   }
 
@@ -32,7 +34,10 @@ export default React.memo(function StepStart({ next, setTaskId }: IProps) {
   }
 
   const handleClick = async () => {
-    if(!currentAvatarUrl){
+    if(loading){
+      return;
+    }
+    if(!currentAvatarUrl.length){
       return
     }
     
@@ -50,7 +55,7 @@ export default React.memo(function StepStart({ next, setTaskId }: IProps) {
     Taro.hideLoading();
     if(isSuccess(response.status)){
       setTaskId(response.data.taskId)
-      next();
+      setTimeout(()=> next(), 200)
     }
   };
 

+ 7 - 1
src/pages/agent-gen/index.tsx

@@ -9,6 +9,8 @@ import { TAvatarItem } from "@/service/storage";
 
 type TStep = 'start'|'pick'|'confirm'
 
+//todo: 使用 store 实现一个状态机
+
 export default function Index() {
 
   const [state, setState] = useState<TStep>('start')
@@ -25,6 +27,10 @@ export default function Index() {
     setVideos([])
     setState('pick')
   }
+  const toStartStep = ()=> {
+    setTaskId(undefined)
+    setState('start')
+  }
   return (
     <PageCustom>
       <NavBarNormal backText="形象照"></NavBarNormal>
@@ -42,7 +48,7 @@ export default function Index() {
             videos={videos}
             setVideos={setVideos}
             setPickedAvatar={setPickedAvatar}
-            prev={()=> setState('start')} 
+            prev={()=> toStartStep()} 
             next={()=> setState('confirm')} 
           />}
         </View>

+ 9 - 3
src/pages/editor-pages/editor-greeting/index.tsx

@@ -3,6 +3,7 @@ import { View } from "@tarojs/components";
 import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/NavBarNormal/index";
 import WemetaTextarea from "@/components/wemeta-textarea/index";
+import TextPolish from '@/components/TextPolish'
 import { useAgentStore } from "@/store/agentStore";
 import useEditAgent from "@/hooks/useEditAgent";
 import BottomBar from "@/components/BottomBar";
@@ -10,8 +11,13 @@ import ButtonMain from "@/components/buttons/ButtonMain";
 export default function Index() {
 
 const agent = useAgentStore((state)=> state.agent)  
-const {handleSubmit, onChange, value} = useEditAgent('greeting', agent?.greeting ?? '')
-
+const {handleSubmit, onChange, value, setValue} = useEditAgent('greeting', agent?.greeting ?? '')
+const onPolished = (text:string|null)=> {
+  if(text){
+    setValue(text)
+  }
+  
+}
   return (
     <PageCustom>
       <NavBarNormal backText="开场白"></NavBarNormal>
@@ -24,7 +30,7 @@ const {handleSubmit, onChange, value} = useEditAgent('greeting', agent?.greeting
               placeholder="碰到TA之后,第一句话想说什么?"
               maxlength={200}
               autoFocus
-              ai
+              extra={()=> <TextPolish text={value} type="greeting" onPolished={onPolished}/>}
             />
         </View>
 

+ 9 - 3
src/pages/editor-pages/editor-personality/index.tsx

@@ -5,15 +5,21 @@ import NavBarNormal from "@/components/NavBarNormal/index";
 import ButtonMain from "@/components/buttons/ButtonMain";
 import BottomBar from "@/components/BottomBar";
 import WemetaTextarea from "@/components/wemeta-textarea/index";
+import TextPolish from '@/components/TextPolish'
 import { useAgentStore } from "@/store/agentStore";
 import useEditAgent from "@/hooks/useEditAgent";
 
 
 export default function Index() {
   const agent = useAgentStore((state)=> state.agent)  
-  const {handleSubmit, onChange, value} = useEditAgent('personality', agent?.personality ?? '')
-  
+  const {handleSubmit, onChange, value, setValue} = useEditAgent('personality', agent?.personality ?? '')
   
+  const onPolished = (text:string|null)=> {
+    if(text){
+      setValue(text)
+    }
+    
+  }
 
   return (
     <PageCustom>
@@ -28,7 +34,7 @@ export default function Index() {
               onInput={(value: string) => onChange(value)}
               placeholder="示例:你是一位汽车销售人员,拥有专业的汽车相关知识,善于耐心的解答客户提出的每一个问题,并会主动邀请客户上门试驾。"
               autoFocus
-              ai
+              extra={()=> <TextPolish text={value} type="personality" onPolished={onPolished}/>}
             />
           </View>
         

+ 4 - 2
src/pages/profile/index.tsx

@@ -14,10 +14,12 @@ import { useAgentStore } from "@/store/agentStore";
 import style from "./index.module.less";
 import { sceneUnzip } from "@/service/wechat";
 import { postLog } from "./profile";
+import { useIsLogin } from "@/xiaolanbenlib/hooks/data/useAuth";
 
 export default function Profile() {
   const { agentProfile, fetchAgentProfile } = useAgentStore();
   const params = useRouter().params;
+  const isLogin = useIsLogin()
 
   // 解码
   const decodeSceneValue = async (sceneValue: string) => {
@@ -41,7 +43,7 @@ export default function Profile() {
       }
     }
   };
-  console.log(params.scene, 1111);
+  console.log(params.scene, '场景值');
   // 通过小程序码识别打开的页面
   useEffect(()=> {
     const scene = decodeURIComponent(params.scene ?? "");
@@ -56,7 +58,7 @@ export default function Profile() {
   useEffect(() => {
     if (params.agentId) {
       fetchAgentProfile(params.agentId);
-      // postLog(params.agentId, params.shareKey);
+      isLogin && postLog(params.agentId, params.shareKey);
     }
   }, [params.agentId]);
 

+ 8 - 0
src/service/agent.ts

@@ -89,6 +89,14 @@ export const postVisitorLog = (data: {
   return request.post<TAgentDetail>(`${bluebookAiAgent}api/v1/agent/visitor/log`, data)
 }
 
+// 文本润色
+export const textPolishing = (data: {
+  content: string
+  type: 'personality'|'greeting' // 人设/开场白
+}) => {
+  return request.post<{content: string}>(`${bluebookAiAgent}api/v1/my/agent/textPolishing`, data)
+}
+
 // 获取智能体的分享信息--仅登录才能分享
 export const getAgentShareInfo = (agentId: string) => {
   return request.get<TAgentShared>(`${bluebookAiAgent}api/v1/agent/${agentId}/shareInfo`)

+ 28 - 12
src/store/agentStore.ts

@@ -66,12 +66,14 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
   ents: [],
   fetchAgents: async () => {
     const response = await getAgents();
-    if (response && response?.data?.length) {
-      const defaultAgent = response.data.find( item => item.isDefault)
-      set({ agents: response.data, defaultAgent });
-      return response.data;
+    const agentsData = response?.data
+    // const agentsData = response?.data?.filter(item => !item.isEnt)
+    if (isSuccess(response.status) && agentsData.length) {
+      const defaultAgent = agentsData.find( item => item.isDefault)
+      set({ agents: agentsData, defaultAgent });
+      return agentsData;
     }
-
+    set({ agents: [], defaultAgent: null });
     return [];
   },
   fetchAgent: async (agentId: string) => {
@@ -101,6 +103,9 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
 
       return response.data;
     }
+    set({
+      agent: null,
+    })
     return null;
   },
   // 请求无需登录的 getAgent 接口
@@ -142,10 +147,13 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
   createAgent: async () => {
     const response = await _createAgent();
     const agentDetail = response.data
-    if (agentDetail) {
+    if (agentDetail?.agentId) {
+      // 创建新智能体,自动设置为默认智能体
+      await get().setDefaultAgent(agentDetail.agentId)
+      
       const a: TAgent = {
         agentId: agentDetail.agentId ?? "",
-        isDefault: agentDetail.isDefault ?? false,
+        isDefault: true,
         isEnt: agentDetail.isEnt ?? false,
         isNewEnt: agentDetail.isNewEnt ?? false,
         name: agentDetail.name ?? "",
@@ -200,14 +208,22 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
   deleteAgent: async (agentId: string)=> {
     const response = await _deleteAgent(agentId)
     if(isSuccess(response.status)){
-      const agents = get().agents.filter((item: TAgent) => item.agentId !== agentId)
-      set({agents: [...agents]})
-      get().fetchAgents()
-      if(agents.length <= 0){
+      const de = get().agents.filter((item: TAgent) => item.agentId !== agentId).reverse()[0]
+      console.log(agentId, de, 'setDefault')
+      // 默认设置自创的智能体
+      if(de){
+        await get().setDefaultAgent(de.agentId)
+      }
+      
+      // 重新拉取智能体列表
+      const restAgents = await get().fetchAgents()
+      if(restAgents.length <= 0){
+        set({agent: null, defaultAgent: null})
         Taro.reLaunch({url: '/pages/index/index'})
         return;
       }
-      const defaultAgent = agents.find((item)=> !!item.isDefault)
+
+      const defaultAgent = restAgents.find((item)=> !!item.isDefault)
       if(defaultAgent){
         await get().fetchAgent(defaultAgent.agentId)
       }   

+ 13 - 1
src/utils/avatar.ts

@@ -5,7 +5,7 @@ import { EUploadFileScene } from "@/consts/enum";
 // import { checkPermission, showAuthModal } from "@/utils/auth";
 
 const MAX_IMAGE_SIZE = 10;
-export const getNewAvatarPic = async (cb: (result: string)=> void)=> {
+export const getNewAvatarPic = async (cb: (result: string|null)=> void)=> {
   // const authed = await checkPermission("scope.writePhotosAlbum");
   //   if (!authed) {
   //     showAuthModal("需要您相册权限");
@@ -22,6 +22,7 @@ export const getNewAvatarPic = async (cb: (result: string)=> void)=> {
           title: `文件不能超过${MAX_IMAGE_SIZE}MB`,
           icon: "none",
         });
+        cb(null)
         return;
       }
 
@@ -36,16 +37,27 @@ export const getNewAvatarPic = async (cb: (result: string)=> void)=> {
           Taro.hideLoading();
           if (response?.publicUrl) {
             cb(response?.publicUrl)
+            return 
           }
+          cb(null)
         },
+        fail(){
+          cb(null)
+        }
       });
     },
+    fail(){
+      cb(null)
+    },
   });
 }
 
 // 上传新形象,成功后跳转至 ai 生成页
 export const uploadAndNavToGenNewAvatar = () => {
   getNewAvatarPic((picUrl)=> {
+    if(!picUrl){
+      return 
+    }
     Taro.navigateTo({
       url: `/pages/agent-gen/index?avatarUrl=${picUrl}`,
     });

+ 1 - 5
src/utils/http.ts

@@ -1,11 +1,7 @@
 import Taro from "@tarojs/taro";
 // 多端上传文件,我们得引入 PostData 和 FileData 两个类
-import { getToken, removeToken } from "./index";
 import { bluebookAiAgent } from "@/xiaolanbenlib/api/index";
-import { APP_VERSION, TARO_APP_ID } from "@/config/index";
-// import { TaroAdapter } from "axios-taro-adapter";
-import { useAppStore } from '@/store/appStore'
-import { EUploadFileScene, EUploadFileBucketName } from '@/consts/enum'
+import { EUploadFileScene } from '@/consts/enum'
 import { getSimpleHeader } from "@/xiaolanbenlib/module/axios.js";
 import {OSS_PUBLIC_BUCKET_NAME_KEY} from '@/xiaolanbenlib/constant'
 

+ 9 - 5
src/utils/jsonChunkParser.ts

@@ -28,6 +28,7 @@ data: [DONE]
 */
 interface ICompleteCallback {
   content: string;
+  body: Record<string,any>
 }
 
 export default class JsonChunkParser {
@@ -40,12 +41,13 @@ export default class JsonChunkParser {
     this.complete = completeCallback;
   }
   // 解析接收到的 chunk
-  public parseChunk(chunk: string, onParsed: (json: any) => void): void {
+  public parseChunk(chunk: string, onParsed: (json: ICompleteCallback) => void): void {
     // 将新接收到的 chunk 添加到 buffer
     this.buffer += chunk;
 
     // 按换行符分割字符串
     const lines = this.buffer.split("\n");
+    let receivedJsonBody = {}
     let combinedContent: string[] = []; // 用于合并 content 字段
     let combinedReasoningContent: string[] = []; // 用于合并 reasoner 字段
     
@@ -58,9 +60,9 @@ export default class JsonChunkParser {
         if (line === "data:[DONE]") {
           // 如果遇到 DONE,合并并调用 onParsed
           if (combinedContent.length > 0) {
-            onParsed({ content: combinedContent.join("") }); // 合并 content
+            onParsed({ content: combinedContent.join("") , body: receivedJsonBody}); // 合并 content
           }
-          this.complete({ content: combinedContent.join("") });
+          this.complete({ content: combinedContent.join(""), body: receivedJsonBody });
           this.buffer = ""; // 清空 buffer
           return; // 结束解析
         }
@@ -71,9 +73,11 @@ export default class JsonChunkParser {
             const jsonStr = line.substring(5); // 移除 "data:" 前缀
             const json = JSON.parse(jsonStr);
             if (json.content) {
+              receivedJsonBody = json
               combinedContent.push(json.content); // 收集 content 字段
             }
             if (json.reasoningContent) {
+              receivedJsonBody = json
               combinedReasoningContent.push(json.reasoningContent); // 收集 content 字段
             }
           }
@@ -88,10 +92,10 @@ export default class JsonChunkParser {
 
     // 如果当前 chunk 解析完毕且有合并的内容,调用 onParsed
     if (combinedContent.length > 0) {
-      onParsed({ content: combinedContent.join("") }); // 合并并输出
+      onParsed({ content: combinedContent.join(""),  body: receivedJsonBody  }); // 合并并输出
     }
     if (combinedReasoningContent.length > 0) {
-      onParsed({ reasoningContent: combinedReasoningContent.join("") }); // 合并并输出
+      onParsed({ reasoningContent: combinedReasoningContent.join(""), body: receivedJsonBody  }); // 合并并输出
     }
 
     // 清空 buffer