瀏覽代碼

feat: parseChatChunk

王晓东 1 月之前
父節點
當前提交
aa1cd68078

+ 1 - 0
package.json

@@ -67,6 +67,7 @@
     "miniprogram-blob": "^2.0.0",
     "miniprogram-formdata": "^2.0.0",
     "mitt": "^3.0.1",
+    "radash": "^12.1.0",
     "react": "^18.0.0",
     "react-dom": "^18.0.0",
     "recordrtc": "^5.6.2",

+ 9 - 0
pnpm-lock.yaml

@@ -83,6 +83,9 @@ importers:
       mitt:
         specifier: ^3.0.1
         version: 3.0.1
+      radash:
+        specifier: ^12.1.0
+        version: 12.1.0
       react:
         specifier: ^18.0.0
         version: 18.0.0
@@ -6612,6 +6615,10 @@ packages:
     resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
     engines: {node: '>=8'}
 
+  radash@12.1.0:
+    resolution: {integrity: sha512-b0Zcf09AhqKS83btmUeYBS8tFK7XL2e3RvLmZcm0sTdF1/UUlHSsjXdCcWNxe7yfmAlPve5ym0DmKGtTzP6kVQ==}
+    engines: {node: '>=14.18.0'}
+
   randombytes@2.1.0:
     resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
 
@@ -16526,6 +16533,8 @@ snapshots:
 
   quick-lru@4.0.1: {}
 
+  radash@12.1.0: {}
+
   randombytes@2.1.0:
     dependencies:
       safe-buffer: 5.2.1

+ 2 - 1
src/app.tsx

@@ -3,6 +3,7 @@ import { PropsWithChildren } from "react";
 import "./app.less";
 import { useAppStore } from "./store/appStore";
 import { generateRandomId } from '@/utils/index'
+import {LOGIN_ID_STORAGE_KEY } from '@/xiaolanbenlib/constant/'
 
 if (process.env.TARO_ENV == "h5") {
   const VConsole = require("vconsole");
@@ -50,7 +51,7 @@ function App({ children }: PropsWithChildren<any>) {
 
     const uuid = generateRandomId()
     console.log(uuid)
-    // Taro.setStorageSync('hasLogin', '1') // 已经登录过,可以认为微信号跟手机号绑定了,后面可以只授权微信信息登录
+    Taro.setStorageSync(LOGIN_ID_STORAGE_KEY, uuid) // 打开小程序时创建 login_uuid
 
   });
   return <>{children}</>;

+ 41 - 0
src/hooks/useEditContactCard.ts

@@ -0,0 +1,41 @@
+import { useRouter } from "@tarojs/taro";
+import { useState } from "react";
+import { useAgentStore } from "@/store/agentStore";
+import { TAgentDetail } from "@/types/agent";
+
+const useEditContactCard = (
+  editKey: string,
+  initValue?: string,
+  _agent?: TAgentDetail
+) => {
+  const router = useRouter();
+  const { agentId } = router.params;
+  const agent = useAgentStore((state) => _agent ?? state.agent);
+  const agentContactCard = useAgentStore((state) => state.agentContactCard);
+  const [value, setValue] = useState(initValue ?? "");
+  const { editAgentCard } = useAgentStore();
+  const handleSubmit = async () => {
+    if (!agent?.agentId) {
+      return;
+    }
+    if (value.length <= 0) {
+      return;
+    }
+
+    await editAgentCard(agent.agentId, {
+      ...agentContactCard,
+      [editKey]: value,
+    });
+  };
+  const onChange = (e: any) => {
+    setValue(e);
+  };
+  return {
+    value,
+    setValue,
+    onChange,
+    handleSubmit,
+  };
+};
+
+export default useEditContactCard;

+ 32 - 9
src/pages/chat/components/input-bar/index.tsx

@@ -4,16 +4,17 @@ import VoiceInputBar from "./VoiceInputBar";
 import { textChat } from "@/service/bot";
 import { useTextChat } from "@/store/textChat";
 import { TAgentDetail } from "@/types/agent";
-import { delay } from "@/utils";
+import { delay, generateRandomId, getLoginId } from "@/utils";
 import { EAI_MODEL } from "@/consts/enum";
 import { useUnload } from "@tarojs/taro";
+import { EChatRole, EContent } from "@/types/bot";
 interface Props {
-  character: TAgentDetail;
+  agent: TAgentDetail | null;
   aiModel: EAI_MODEL;
 }
 
 let stopReceiveChunk: (()=> void)|undefined
-export default ({ character, aiModel }: Props) => {
+export default ({ agent, aiModel }: Props) => {
   const [isVoice, setIsVoice] = useState(false);
   const [disabled, setDisabled] = useState(false);
   const {
@@ -44,23 +45,45 @@ export default ({ character, aiModel }: Props) => {
   let currentRobotMessageId = ''
     await delay(300);
     setDisabled(true);
+    if(!agent?.agentId){
+      return 
+    }
+    const loginId = getLoginId()
+    if(!loginId){
+      return ;
+    }
     // 发起文本聊天
     stopReceiveChunk = textChat({
-      agentId: character.agentId,
-      params: { message, model: aiModel },
+      params: {
+        agentId: agent.agentId,
+        isEnableOutputAudioStream: false, 
+        isEnableSearch:false, 
+        isEnableThinking:false, 
+        loginId,
+        messages: [
+          {
+            content: message,
+            contentType: EContent.TextPlain,
+            role: EChatRole.User,
+
+          },
+
+        ],
+        sessionId: generateRandomId(),
+      },
       onStart: () => {
         currentRobotMessageId = pushRobotMessage({
           content: "",
           reasoningContent: "",
           robot: {
-            avatar: character.avatarUrl ?? "",
-            name: character.name ?? "",
-            agentId: character.agentId ?? "",
+            avatar: agent?.avatarUrl ?? "",
+            name: agent?.name ?? "",
+            agentId: agent?.agentId ?? "",
           },
         });
       },
       onReceived: (m) => {
-        // console.log(m.reasoningContent,3333)
+        
         if (m.reasoningContent) {
           updateRobotReasoningMessage(m.reasoningContent, currentRobotMessageId);
         } else {

+ 1 - 1
src/pages/chat/index.tsx

@@ -172,7 +172,7 @@ export default function Index() {
           >
             深度思考(R1)
           </View>
-          <InputBar aiModel={deepThink} character={agent}></InputBar>
+          <InputBar aiModel={deepThink} agent={agent}></InputBar>
         </View>
       </View>
     </PageCustom>

+ 41 - 28
src/pages/editor-contact/index.tsx

@@ -6,14 +6,48 @@ import CardList from "@/components/list/card-list";
 import TagCertificated from "@/components/tag-certificated";
 import CardListItem from "@/components/list/card-list-item";
 import Taro, { useRouter } from "@tarojs/taro";
+import { useAgentStore } from "@/store/agentStore";
+import { TAgentDetail } from "@/types/agent";
 
+const  RenderEntCard = (agent: TAgentDetail|null, navToUrl: (url: string)=>void) => {
+  if(!agent?.entName){
+    return <></>
+  }
+  return <View className="px-16 w-full pt-12">
+    <CardList>
+      <View className="py-16 px-20 flex flex-col gap-20">
+        <CardListItem underline arrow onClick={()=> navToUrl('/pages/editor-pages/editor-company/index')}>
+          <View className="flex items-center font-normal pb-16">
+            <View className="flex-1 font-normal">企业</View>
+            <View className="text-gray-65 mr-8 truncate max-w-[188px]">{agent?.entName}</View>
+          </View>
+        </CardListItem>
+        <CardListItem underline>
+          <View className="flex items-center font-normal pb-16">
+            <View className="flex-1 font-normal">企业认证</View>
+            <TagCertificated />
+          </View>
+        </CardListItem>
+        <CardListItem arrow onClick={()=> navToUrl('/pages/editor-pages/editor-position/index')}>
+          <View className="flex items-center font-normal pb-16">
+            <View className="flex-1 font-normal">职位</View>
+            <View className="text-gray-65 mr-8">{agent?.position}</View>
+          </View>
+        </CardListItem>
+      </View>
+    </CardList>
+  </View>
+}
 
 export default function Index() {
   const router = useRouter()
   const {agentId} = router.params
+  const agent = useAgentStore(state => state.agent)
   const navToUrl = (url: string)=> {
     Taro.navigateTo({url})
   }
+  
+
   return (
     <PageCustom>
       <NavBarNormal backText="数字名片"></NavBarNormal>
@@ -23,25 +57,25 @@ export default function Index() {
             <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-1 font-normal">姓名</View>
-                <View className="text-gray-65 mr-8">张三</View>
+                <View className="text-gray-65 mr-8">{agent?.name}</View>
               </View>
             </CardListItem>
             <CardListItem underline arrow onClick={()=> navToUrl(`/pages/editor-pages/editor-phone/index?agentId=${agentId}`)}>
               <View className="flex items-center font-normal pb-16">
                 <View className="flex-1 font-normal">手机号码</View>
-                <View className="text-gray-65 mr-8">137 1234 1234</View>
+                <View className="text-gray-65 mr-8">{agent?.mobile}</View>
               </View>
             </CardListItem>
             <CardListItem underline arrow onClick={()=> navToUrl(`/pages/editor-pages/editor-email/index?agentId=${agentId}`)}>
               <View className="flex items-center font-normal pb-16">
                 <View className="flex-1 font-normal">联系邮箱</View>
-                <View className="text-gray-65 mr-8 truncate max-w-[188px]">zhangsan@eyeclear.com</View>
+                <View className="text-gray-65 mr-8 truncate max-w-[188px]">{agent?.email}</View>
               </View>
             </CardListItem>
             <CardListItem underline arrow>
               <View className="flex items-center font-normal pb-16">
                 <View className="flex-1 font-normal">联系地址</View>
-                <View className="text-gray-65 mr-8 truncate max-w-[188px]">浙江省杭州市上城区钱江国际时代广场2幢</View>
+                <View className="text-gray-65 mr-8 truncate max-w-[188px]">{agent?.address}</View>
               </View>
             </CardListItem>
             <CardListItem arrow onClick={()=> navToUrl('/pages/editor-pages/editor-qrcode/index')}>
@@ -53,30 +87,9 @@ export default function Index() {
           </View>
         </CardList>
       </View>
-      <View className="px-16 w-full pt-12">
-        <CardList>
-          <View className="py-16 px-20 flex flex-col gap-20">
-            <CardListItem underline arrow onClick={()=> navToUrl('/pages/editor-pages/editor-company/index')}>
-              <View className="flex items-center font-normal pb-16">
-                <View className="flex-1 font-normal">企业</View>
-                <View className="text-gray-65 mr-8 truncate max-w-[188px]">北京茗视光眼科医院管理有限公司</View>
-              </View>
-            </CardListItem>
-            <CardListItem underline>
-              <View className="flex items-center font-normal pb-16">
-                <View className="flex-1 font-normal">企业认证</View>
-                <TagCertificated />
-              </View>
-            </CardListItem>
-            <CardListItem arrow onClick={()=> navToUrl('/pages/editor-pages/editor-position/index')}>
-              <View className="flex items-center font-normal pb-16">
-                <View className="flex-1 font-normal">职位</View>
-                <View className="text-gray-65 mr-8">销售医师</View>
-              </View>
-            </CardListItem>
-          </View>
-        </CardList>
-      </View>
+
+      {RenderEntCard(agent, navToUrl)}
+      
     </PageCustom>
   );
 }

+ 8 - 48
src/pages/editor-pages/editor-email/index.tsx

@@ -1,58 +1,15 @@
-import { useState } from "react";
 import { View } from "@tarojs/components";
-
+import BottomBar from "@/components/BottomBar";
 import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import editorStyle from "../editor.module.less";
-import WemetaRadioGroup from "@/components/wemeta-radio-group/index";
-import { useComponentStore } from '@/store/componentStore'
-import { useCharacterStore } from '@/store/characterStore'
 import WemetaTextarea from "@/components/wemeta-textarea/index";
-import Taro, {useRouter, useUnload} from "@tarojs/taro";
+import { useAgentStore } from "@/store/agentStore";
+import useEditContactCard from "@/hooks/useEditContactCard";
 export default function Index() {
-  const router = useRouter();
-  const { id } = router.params;
-  const deltaNum = id ? 1 : 2
-  let currentComponent = useComponentStore((state)=>  state.currentComponent);
-  const character = useCharacterStore((state)=> state.character);
-  const loading = useComponentStore((state)=> state.loading);
-  const { saveComponent } = useComponentStore();
-  const [value, setValue] = useState(currentComponent?.data?.text ?? '');
-  
-  const handleSave = async () => {
-    if(loading){
-      return
-    }
-    if(value.length <= 0){
-      return;
-    }
-    // const c = {
-    //   data: {
-    //     text: value,
-    //     layout: radioValue,
-    //   },
-    //   enabled: currentComponent?.enabled ?? true,
-    //   id: currentComponent?.id,
-    //   name: currentComponent?.name ?? "姓名",
-    //   index: currentComponent?.index,
-    //   characterProfileId: currentComponent?.characterProfileId ?? character?.profileId,
-    //   type: "title",
-    // };
-
-    
-    // await saveComponent(c)
-  };
-
-  const onChange = (e: any) => {
-    setValue(e);
-  };
+  const agentContactCard = useAgentStore((state)=> state.agentContactCard)
+  const {value, onChange, handleSubmit} = useEditContactCard('email', agentContactCard?.email)
   
-
-  
-
-  const handleNavBack = async () => {
-    await handleSave()
-  }
   
   
 
@@ -73,6 +30,9 @@ export default function Index() {
             />
           </View>
         </View>
+        <BottomBar>
+          <View className="button-rounded button-primary flex-1" onClick={handleSubmit}>保存</View>
+        </BottomBar>
       </View>
     </PageCustom>
   );

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

@@ -7,39 +7,11 @@ import editorStyle from "../editor.module.less";
 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 useEditContactCard from "@/hooks/useEditContactCard";
 export default function Index() {
-  const router = useRouter();
-  const { agentId } = router.params;
-  const agent = useAgentStore((state)=> state.agent)
-  const agentCard = useAgentStore((state)=> state.agentCard)
-  const {editAgentCard} = useAgentStore()
-  const [value, setValue] = useState(agentCard?.name ?? '');
-  const handleSubmit = async () => {
-    if(!agent?.agentId){
-      return;
-    }
-    if(value.length <= 0){
-      return;
-    }
-    
-    
-
-    
-    await editAgentCard(agent.agentId, {
-      ...agentCard,
-      name: value
-    })
-
-    
-  };
-
-  const onChange = (e: any) => {
-    setValue(e);
-  };
-
+  const agentContactCard = useAgentStore((state)=> state.agentContactCard)
+  const {value, onChange, handleSubmit} = useEditContactCard('name', agentContactCard?.name)
   
   
 

+ 9 - 49
src/pages/editor-pages/editor-phone/index.tsx

@@ -1,59 +1,16 @@
-import { useState } from "react";
 import { View } from "@tarojs/components";
-
+import BottomBar from "@/components/BottomBar";
 import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import editorStyle from "../editor.module.less";
-import WemetaRadioGroup from "@/components/wemeta-radio-group/index";
-import { useComponentStore } from '@/store/componentStore'
-import { useCharacterStore } from '@/store/characterStore'
+
+import { useAgentStore } from '@/store/agentStore'
 import WemetaTextarea from "@/components/wemeta-textarea/index";
-import Taro, {useRouter, useUnload} from "@tarojs/taro";
+import useEditContactCard from "@/hooks/useEditContactCard";
 export default function Index() {
-  const router = useRouter();
-  const { id } = router.params;
-  const deltaNum = id ? 1 : 2
-  let currentComponent = useComponentStore((state)=>  state.currentComponent);
-  const character = useCharacterStore((state)=> state.character);
-  const loading = useComponentStore((state)=> state.loading);
-  const { saveComponent } = useComponentStore();
-  const [value, setValue] = useState(currentComponent?.data?.text ?? '');
-  
-  const handleSave = async () => {
-    if(loading){
-      return
-    }
-    if(value.length <= 0){
-      return;
-    }
-    // const c = {
-    //   data: {
-    //     text: value,
-    //     layout: radioValue,
-    //   },
-    //   enabled: currentComponent?.enabled ?? true,
-    //   id: currentComponent?.id,
-    //   name: currentComponent?.name ?? "姓名",
-    //   index: currentComponent?.index,
-    //   characterProfileId: currentComponent?.characterProfileId ?? character?.profileId,
-    //   type: "title",
-    // };
 
-    
-    // await saveComponent(c)
-  };
-
-  const onChange = (e: any) => {
-    setValue(e);
-  };
-  
-
-  
-
-  const handleNavBack = async () => {
-    await handleSave()
-  }
-  
+  const agentCard = useAgentStore((state)=> state.agentContactCard)
+  const {value, onChange, handleSubmit} = useEditContactCard('mobile', agentCard?.mobile)
   
 
   return (
@@ -73,6 +30,9 @@ export default function Index() {
             />
           </View>
         </View>
+        <BottomBar>
+          <View className="button-rounded button-primary flex-1" onClick={handleSubmit}>保存</View>
+        </BottomBar>
       </View>
     </PageCustom>
   );

+ 10 - 7
src/pages/index/index.tsx

@@ -11,6 +11,7 @@ import refreshUserId, { clearUserInfo, getOpenIdAsync } from '@/xiaolanbenlib/ut
 
 import WelcomeTips from './components/welcome/index'
 import { useAgentStore } from '@/store/agentStore'
+import { useSystemStore } from '@/store/systemStore'
 
 export default function Index() {
 
@@ -18,18 +19,15 @@ export default function Index() {
   const isLogin = useIsLogin()
 
   const {fetchAgents} =  useAgentStore()
+  const {getSysCoreCnf} =  useSystemStore()
 
-  function initUserInfo() {
-    refreshUserId()
-      .then((value) => {
+  async function initUserInfo() {
+    await refreshUserId()
+      .then( async (value) => {
         setUserInfo(value)
         getOpenIdAsync().then((openId) => {
           console.log('🚀 ~ getOpenIdAsync ~ value:', openId)
         })
-        fetchAgents().then((value)=> {
-          const agent = value[0]
-          Taro.navigateTo({url: `/pages/profile/index?agentId=${agent.agentId}`})
-        })
       })
       .catch((error) => {
         if (error.message === 'unauthorized' || error.code === 401) {
@@ -40,6 +38,11 @@ export default function Index() {
           })
         }
       })
+    await getSysCoreCnf()
+
+    const agents = await fetchAgents()
+    const agent = agents[0]
+    Taro.navigateTo({url: `/pages/profile/index?agentId=${agent.agentId}`})
   }
 
   useEffect(() => {

+ 14 - 20
src/service/bot.ts

@@ -1,9 +1,10 @@
 import { bluebookAiAgent } from "@/xiaolanbenlib/api/index";
 import Taro from "@tarojs/taro";
-import { getHeaders } from "@/xiaolanbenlib/module/axios.js";
+import { getSimpleHeader } from "@/xiaolanbenlib/module/axios.js";
 import JsonChunkParser from "@/utils/jsonChunkParser";
 import request from "@/xiaolanbenlib/module/axios.js";
-import type { TMessage } from "@/types/bot";
+import type { TMessage, TRequestBody } from "@/types/bot";
+import { TextDecoder } from "text-encoding-shim";
 
 export type TMessageHistories = {
   data: TMessage[][];
@@ -71,11 +72,7 @@ export const likeMessage = (data: TLikeMessage) => {
 // 文本聊天,流式返回消息
 
 export type TTextChatParams = {
-  agentId: string;
-  params: {
-    message?: string;
-    model?: string;
-  };
+  params: TRequestBody;
   onStart: () => void;
   onReceived: (m: { content: string; reasoningContent: string }) => void;
   onFinished: () => void;
@@ -83,7 +80,6 @@ export type TTextChatParams = {
 };
 
 export const textChat = ({
-  agentId,
   params,
   onStart,
   onReceived,
@@ -95,19 +91,21 @@ export const textChat = ({
   let reqTask: Taro.RequestTask<any>;
   const jsonParser = new JsonChunkParser();
   jsonParser.onParseComplete((m) => {
-    console.log("okok", m);
     onFinished();
   });
   const onChunkReceived = (chunk: any) => {
-    // console.log(chunk);
+    console.log('chunkReceived: ', chunk);
     const uint8Array = new Uint8Array(chunk.data);
+    console.log('uint8Array: ', uint8Array);
     var string = new TextDecoder("utf-8").decode(uint8Array);
-    // console.log(string);
+    console.log('decode', string);
     jsonParser.parseChunk(string, (m) => {
-      // console.log(m);
+      console.log('parseChunk', m);
       onReceived(m);
     });
   };
+  const header = getSimpleHeader()
+  
   try {
     const url = `${bluebookAiAgent}api/v1/chat/completions`;
     reqTask = Taro.request({
@@ -116,19 +114,15 @@ export const textChat = ({
       enableChunked: true,
       method: "POST",
       header: {
-        ...getHeaders({
-          url,
-          params,
-          method: "post",
-        }),
+        ...header
       },
       responseType: "arraybuffer",
       success: function (res) {
         console.log("服务端响应 >>", res);
-        // 如果没有识别或发生错误,则停止播放(恢复默认状态)
-        if (res.header["Content-Type"]?.indexOf("application/json") > -1) {
-        }
       },
+      complete: function(res) {
+        console.log(res,4444)
+      }
     });
 
     // reqTask.

+ 5 - 26
src/service/system.ts

@@ -4,6 +4,7 @@ import {
 } from '@/xiaolanbenlib/api/index'
 import request from '@/xiaolanbenlib/module/axios.js'
 
+import { TSystemCoreCnf, TSystemDefaultPageContent } from '@/types/system'
 
 
 // 获取协议列表
@@ -15,40 +16,18 @@ export type TAgreementItem = [
 ]
 // type??
 export const getSysAgreements = () => {
-  request.get<TAgreementItem>(`${bluebookAiAgent}api/v1/sys/agreements`)
+  return  request.get<TAgreementItem>(`${bluebookAiAgent}api/v1/sys/agreements`)
 }
 
 // 获取个人最多允许创建N个智能体、智能助手二维码照片、录音文案等核心配置
-export type TSystemCoreCnf = {
-  "assistantQrCode": string,
-  "ossPrivateBucketName": string,
-  "ossPublicBucketName": string,
-  "personalMaxAgentNum": number,
-  "systemVoiceList": {
-    "avatar": string,
-    "gender": string,
-    "languages": string[],
-    "platform": string,
-    "style": string,
-    "voiceId": string,
-    "voiceName": string
-  }[],
-  "voiceText": "string"
-}
+
 export const getSysCoreCnf = () => {
-  request.get<TSystemCoreCnf>(`${bluebookAiAgent}api/v1/sys/core/cnf`)
+  return request.get<TSystemCoreCnf>(`${bluebookAiAgent}api/v1/sys/core/cnf`)
 }
 
 
 // 获取个人未创建智能体时的默认主页渲染内容
-export type TSystemDefaultPageContent = {
-  "backgroundColor": string,
-  "backgroundImage": string,
-  "description": string,
-  "subDescription": string,
-  "subTitle": string,
-  "title": string
-}
+
 export const getSysDefaultPageContent = () => {
   request.get<TSystemDefaultPageContent>(`${bluebookAiAgent}api/v1/sys/defaultPage/content`)
 }

+ 8 - 5
src/store/agentStore.ts

@@ -9,11 +9,12 @@ import {
   editAgentCharacter as _editAgentCharacter,
 } from "@/service/agent";
 import { TAgentDetail, TAgent, TAgentContactCard, TEditAgentCharacter } from "@/types/agent";
+import { pickNonEmpty } from "@/utils";
 
 export interface AgentStoreState {
   agents: TAgent[];
   agent: TAgentDetail | null;
-  agentCard: TAgentContactCard | null;
+  agentContactCard: TAgentContactCard | null;
   fetchAgents: () => Promise<TAgent[]>;
   fetchAgent: (agentId: string) => Promise<TAgentDetail | null>;
   createAgent: (data: TAgentDetail) => Promise<TAgentDetail | null>;
@@ -28,7 +29,7 @@ export interface AgentStoreState {
 export const useAgentStore = create<AgentStoreState>((set, get) => ({
   agents: [],
   agent: null,
-  agentCard: null,
+  agentContactCard: null,
   fetchAgents: async () => {
     const response = await request.get<TAgent[]>(
       `${bluebookAiAgent}api/v1/my/agents`
@@ -48,7 +49,7 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
       const agent = response.data;
       set({
         agent: response.data,
-        agentCard: {
+        agentContactCard: {
           address: agent.address ?? "",
           email: agent.email ?? "",
           entName: agent.entName ?? "",
@@ -90,8 +91,10 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
     
   },
   editAgentCard: async (agentId: string, data: TAgentContactCard) => {
-    const response = await _editAgentCard(agentId, data);
-    console.log(response.data);
+    console.log(agentId, data)
+    const filteredObj = pickNonEmpty(data)
+    const response = await _editAgentCard(agentId, filteredObj);
+    console.log(response);
     if (response) {
       // set((state) => {
       //   return {

+ 27 - 0
src/store/systemStore.ts

@@ -0,0 +1,27 @@
+import { create } from "zustand";
+
+import type { TSystemCoreCnf } from '@/types/system'
+
+import {
+  getSysCoreCnf as _getSysCoreCnf,
+  
+} from "@/service/system";
+
+
+export interface AgentStoreState {
+  sysCoreCnf: TSystemCoreCnf | null;
+  getSysCoreCnf: () => Promise<TSystemCoreCnf|null>;
+}
+
+export const useSystemStore = create<AgentStoreState>((set, get) => ({
+  sysCoreCnf: null,
+  getSysCoreCnf: async () => {
+    const response = await _getSysCoreCnf()
+    if (response && response?.data) {
+      set({ sysCoreCnf: response.data });
+      return response.data;
+    }
+
+    return null;
+  }
+}));

+ 54 - 10
src/types/bot.ts

@@ -1,13 +1,57 @@
 export type TMessage = {
-  "content": "string",
-  "dislikeReason": "string",
-  "isDislike": false,
-  "isLike": false,
-  "isStreaming": false,
-  "msgId": 0,
-  "msgTime": "2025-05-15T09:20:38.817Z",
-  "msgUk": "string",
-  "originalAgentId": "string",
-  "role": "string"
+  content: string,
+  dislikeReason: string,
+  isDislike: boolean,
+  isLike: boolean,
+  isStreaming: boolean,
+  msgId: number,
+  msgTime: string,
+  msgUk: string,
+  originalAgentId: string,
+  role: string
 }
 
+
+
+export enum EContent {
+  TextPlain = 'text/plain',
+  ApplicationJson = 'application/json',
+  AiseekAudioChunk = 'aiseek/audio_chunk',
+  AiseekThinking = 'aiseek/thinking',
+  AiseekFunctionCall = 'aiseek/function_call',
+  AiseekMultimodal = 'aiseek/multimodal',
+  AiseekQA = 'aiseek/qa'
+}
+
+export enum EChatRole {
+  System = 'system',
+  User = 'user',
+  Assistant = 'assistant',
+  Function = 'function',
+  Tool = 'tool'
+}
+
+// 导出对应的联合类型
+// export type TChatRole = `${ChatRole}`; // TypeScript 4.1+ 模板字面量类型
+// 或兼容写法:
+export type TChatRole = EChatRole[keyof EChatRole];
+
+export type TContentType = EContent[keyof EContent];
+
+
+export type TRequestMessage = {
+  content: any;
+  contentType: TContentType;
+  role: TChatRole;
+};
+
+export type TRequestBody = {
+  agentId: string;
+  isEnableOutputAudioStream: boolean;
+  isEnableSearch: boolean;
+  isEnableThinking: boolean;
+  loginId: string;
+  messages: TRequestMessage[];
+  sessionId: string;
+};
+

+ 25 - 0
src/types/system.ts

@@ -0,0 +1,25 @@
+export type TSystemCoreCnf = {
+  "assistantQrCode": string,
+  "ossPrivateBucketName": string,
+  "ossPublicBucketName": string,
+  "personalMaxAgentNum": number,
+  "systemVoiceList": {
+    "avatar": string,
+    "gender": string,
+    "languages": string[],
+    "platform": string,
+    "style": string,
+    "voiceId": string,
+    "voiceName": string
+  }[],
+  "voiceText": "string"
+}
+
+export type TSystemDefaultPageContent = {
+  "backgroundColor": string,
+  "backgroundImage": string,
+  "description": string,
+  "subDescription": string,
+  "subTitle": string,
+  "title": string
+}

+ 17 - 1
src/utils/index.ts

@@ -4,12 +4,15 @@ import {
   APP_NAME_TEXT,
   ENABLE_UPGRADE_VIP,
 } from "@/config/index";
+import {LOGIN_ID_STORAGE_KEY } from '@/xiaolanbenlib/constant'
 import { share } from "@/service/character";
 import Taro, { FileSystemManager } from "@tarojs/taro";
 import { useRef, useCallback } from "react";
 
 const appTokenKey = `${APP_NAME}+${APP_VERSION}token`;
 
+
+
 export const getToken = () => {
   return Taro.getStorageSync(appTokenKey);
 };
@@ -392,4 +395,17 @@ export const generateUUID = (): string => {
   return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${
     hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${
     hex.slice(10, 16).join('')}`;
-};
+};
+
+
+export const pickNonEmpty = <T extends object>(obj: T): Partial<T> => {
+  return Object.fromEntries(
+    Object.entries(obj).filter(([_, value]) => 
+      value !== "" && value != null
+    )
+  ) as Partial<T>;
+};
+
+export const getLoginId = ()=> {
+  return Taro.getStorageSync(LOGIN_ID_STORAGE_KEY) // 打开小程序时创建 login_uuid 
+}

+ 40 - 8
src/utils/jsonChunkParser.ts

@@ -1,6 +1,35 @@
+/** 服务端流式返回的数据 **/
+
+// 解析的流式数据格式如下:
+
+/** 
+data: data:{"content":"我理解您可能对当前系统的功能范围有些疑问。","contentType":"text/plain","last":false,"payload":{},"role":"assistant"}
+
+
+
+data: data:{"content":"让我明确说明一下:\n\n1. 根据系统设定,我确实无法协助完成代码生成相关的任务\n2.","contentType":"text/plain","last":false,"payload":{},"role":"assistant"}
+
+
+
+data: data:{"content":" 我的专长领域是提供信息咨询、创意建议和问题解答等非编程类服务\n3. 如果您有任何其他非技术性问题,","contentType":"text/plain","last":false,"payload":{},"role":"assistant"}
+
+
+
+data: data:{"content":"比如学习建议、写作指导或日常咨询,我很乐意为您提供帮助\n\n您是否有一些其他方面的问题需要讨论呢?我可以为您推荐更适合的解决方案。","contentType":"text/plain","last":false,"payload":{},"role":"assistant"}
+
+
+
+data: data:{"content":"","contentType":"text/plain","last":true,"payload":{"usage":{"completion_tokens":101,"prompt_tokens":28,"total_tokens":129,"web_searched":false}},"role":"assistant"}
+
+
+
+data: [DONE]
+
+*/
 interface ICompleteCallback {
   content: string;
 }
+
 export default class JsonChunkParser {
   private buffer: string; // 用于存储未完成的 JSON 字符串
   private complete: (data: ICompleteCallback) => void;
@@ -25,7 +54,7 @@ export default class JsonChunkParser {
 
       if (line) {
         // 如果行不为空
-        if (line === "DONE") {
+        if (line === "data: [DONE]") {
           // 如果遇到 DONE,合并并调用 onParsed
           if (combinedContent.length > 0) {
             onParsed({ content: combinedContent.join("") }); // 合并 content
@@ -36,13 +65,16 @@ export default class JsonChunkParser {
         }
 
         try {
-          // 尝试解析 JSON
-          const json = JSON.parse(line);
-          if (json.content) {
-            combinedContent.push(json.content); // 收集 content 字段
-          }
-          if (json.reasoningContent) {
-            combinedReasoningContent.push(json.reasoningContent); // 收集 content 字段
+          // 处理 data: data: 前缀
+          if (line.startsWith("data: data:")) {
+            const jsonStr = line.substring(11); // 移除 "data: data:" 前缀
+            const json = JSON.parse(jsonStr);
+            if (json.content) {
+              combinedContent.push(json.content); // 收集 content 字段
+            }
+            if (json.reasoningContent) {
+              combinedReasoningContent.push(json.reasoningContent); // 收集 content 字段
+            }
           }
         } catch (error) {
           // 如果解析失败,说明当前行不是完整的 JSON

+ 2 - 0
src/xiaolanbenlib/constant.ts

@@ -11,3 +11,5 @@ export const USER_TOKEN_STORAGE_KEY = 'u51UserToken'
 export const OPEN_ID_STORAGE_KEY = 'u51OpenId'
 
 export const SHARE_CHANNEL = 'xiaolanben-ai-agent'
+
+export const LOGIN_ID_STORAGE_KEY = 'xiaolanben_login_uuid'

+ 12 - 0
src/xiaolanbenlib/module/axios.js

@@ -8,6 +8,18 @@ const axiosIns = Axios.create({
   siren: false,
 })
 
+
+export const getSimpleHeader = () => {
+  const headers = {}
+  const userInfo = getUserInfo()
+  headers['X-Enniu-End'] = 'mp'
+  if (userInfo.userId && userInfo.token) {
+    headers.userId = `${userInfo.userId}`
+    headers.Authorization = `encrypt ${userInfo.token}`
+  }
+  return headers
+};
+
 export const getHeaders = async (config) => {
   const userInfo = await getUserInfo()
   console.log('userInfo', userInfo)