Browse Source

fix: 聊天时定时上报聊天消息

王晓东 5 days ago
parent
commit
fe902d16de
36 changed files with 348 additions and 107 deletions
  1. 8 1
      project.private.config.json
  2. 5 2
      src/app.less
  3. 2 2
      src/components/AgentPage/components/AgentSwap/index.module.less
  4. 13 6
      src/components/AgentPage/components/AgentSwap/index.tsx
  5. 1 0
      src/components/ContactIcon/index.module.less
  6. 3 2
      src/components/EmptyData/index.tsx
  7. 1 1
      src/components/KnowledgeList/index.tsx
  8. 3 3
      src/components/LoginPopup/index.tsx
  9. 2 2
      src/components/chat-message/MessageRobot.tsx
  10. 1 1
      src/components/chat-message/index.module.less
  11. 1 1
      src/components/chat-message/index.tsx
  12. 7 0
      src/images/svgs/index/IconIndexChat.svg
  13. 1 0
      src/images/svgs/index/IconIndexContent.svg
  14. 6 0
      src/images/svgs/index/IconIndexProfile.svg
  15. 46 10
      src/pages/chat/components/input-bar/chatInput.ts
  16. 132 3
      src/pages/chat/components/input-bar/message.ts
  17. 1 1
      src/pages/chat/components/personal-card/index.tsx
  18. 1 1
      src/pages/chat/index.module.less
  19. 18 8
      src/pages/chat/index.tsx
  20. 1 1
      src/pages/contact/index.tsx
  21. 1 1
      src/pages/dislike-messages/index.tsx
  22. 8 4
      src/pages/index/components/WelcomeTips/index.module.less
  23. 6 0
      src/pages/index/components/WelcomeTips/index.tsx
  24. 1 1
      src/pages/knowledge/components/CompanyList/index.tsx
  25. 1 1
      src/pages/knowledge/components/CompanyTab/components/ScrollList.tsx
  26. 1 1
      src/pages/knowledge/components/CompanyTab/components/ScrollListChat.tsx
  27. 1 1
      src/pages/knowledge/components/CorrectionTab/index.tsx
  28. 1 1
      src/pages/knowledge/components/PersonalTab/components/ScrollList.tsx
  29. 1 1
      src/pages/visiteor-detail/index.tsx
  30. 1 0
      src/pages/voice/components/MyVoiceList/components/popup-recorder/index.tsx
  31. 1 1
      src/pages/voice/components/MyVoiceList/index.tsx
  32. 1 1
      src/pages/voice/components/VoiceList/index.tsx
  33. 5 1
      src/service/bot.ts
  34. 24 15
      src/store/textChat.ts
  35. 39 33
      src/types/bot.ts
  36. 3 0
      tailwind.config.js

+ 8 - 1
project.private.config.json

@@ -11,10 +11,17 @@
         {
           "name": "pages/profile/index",
           "pathName": "pages/profile/index",
-          "query": "agentId=p_8e726e825bagi5Ki-agent_1001",
+          "query": "agentId=e_d4426640dca3-6719d6aYig5s-agent_435",
           "scene": null,
           "launchMode": "default"
         },
+        {
+          "name": "pages/profile/index",
+          "pathName": "pages/profile/index",
+          "query": "agentId=p_8e726e825bagi5Ki-agent_1001",
+          "launchMode": "default",
+          "scene": null
+        },
         {
           "name": "pages/contact/index",
           "pathName": "pages/contact/index",

+ 5 - 2
src/app.less

@@ -6,7 +6,7 @@
 /* 确保变量定义在全局作用域 */
 /* 为 RootPortal 容器单独定义变量 */
 :root, .taro-portal-container, page  {
-  font-family: PingFangSC-Medium;
+  font-family: PingFangSC-Regular;
   --color-primary: #317CFA;
   --color-primary-rgb: 49, 124, 250;
   --color-primary-light: rgba(49, 124, 250, 0.1);
@@ -22,12 +22,15 @@
 .w-full{
   box-sizing: border-box;
 }
+.pingfang-SC-Medium{
+  font-family: PingFangSC-Medium;
+}
 .global-color{
-  font-family: PingFang SC;
   font-weight: 400;
   font-size: 14px;
   line-height: 22px;
 }
+
 .global-color-new{
   .global-color{
     color: yellowgreen;

+ 2 - 2
src/components/AgentPage/components/AgentSwap/index.module.less

@@ -6,8 +6,8 @@
 .card{
   margin-bottom: 12px;
   padding: 20px;
-  width: 315px;
-  height: 144px;
+  width: 100%;
+  min-height: 144px;
   border-radius: 12px;
   background-color: rgba(#000, .03);
   border: 1px solid transparent;

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

@@ -10,6 +10,7 @@ import { TAgent } from "@/types/agent";
 import Taro from "@tarojs/taro";
 import ContactIcon from "@/components/ContactIcon";
 import { useEffect } from "react";
+import EmptyData from "@/components/EmptyData";
 interface IProps {
   show: boolean;
   setShow: (show: boolean) => void;
@@ -70,9 +71,9 @@ export default ({ show, setShow }: IProps) => {
         <View
           className="flex items-start mb-24"
         >
-          <View className="flex flex-col flex-1">
-            <View className="flex items-end gap-8 text-gray-65">
-              <View className="text-20 font-medium leading-28 text-black">
+          <View className="flex flex-col flex-1 truncate">
+            <View className="flex items-end gap-8 text-gray-65 truncate">
+              <View className="text-20 font-medium leading-28 text-black truncate">
                 {item.name}
               </View>
               <View className="text-12 leading-20">
@@ -98,6 +99,9 @@ export default ({ show, setShow }: IProps) => {
   };
 
   const renderPersonalAgents = () => {
+    if(personalAgents.length <= 0){
+      return <EmptyData type='search' className="mt-44"></EmptyData>
+    }
     return personalAgents.map((item) => {
       return renderCard(item, false);
     });
@@ -134,10 +138,13 @@ export default ({ show, setShow }: IProps) => {
       label: "个人",
       children: (
         <>
-          <View className="pt-12">
+          <View className="pt-12 relative">
             <View className={style.tabContainer}>
-              {renderPersonalAgents()}
-
+              <View className="pb-52">
+                {renderPersonalAgents()}
+              </View>
+            </View>
+            <View className="absolute left-0 right-0 bottom-0 z-10 bg-white">
               <View className="button-rounded button-primary-light gap-8 mb-15" onClick={handleCreate}>
                 <IconPlusBlue />
                 <View>创建新的智能体</View>

+ 1 - 0
src/components/ContactIcon/index.module.less

@@ -5,6 +5,7 @@
   width: 24px;
   height: 24px;
   border-radius: 100%;
+  flex-shrink: 0;
   background-color: rgba(#F3F3F3, 1);
 }
 .iconActive{

+ 3 - 2
src/components/empty-data/index.tsx → src/components/EmptyData/index.tsx

@@ -3,10 +3,11 @@ interface IProps {
   type: 'plane'|'search'|'chat' | 'box' | 'whiteboard' | (string & {}),
   text?: string,
   children?: JSX.Element|JSX.Element[]
+  className?: string
 }
-export default ({type, text = '暂无数据', children}: IProps)=> {
+export default ({type, className='', text = '暂无数据', children}: IProps)=> {
   return (
-    <View className="flex flex-col items-center">
+    <View className={`flex flex-col items-center ${className}`}>
       <View className={`data-empty data-empty${type}`}></View>
       {children ? children : <View className='text-16 text-black font-medium text-center leading-24 mt-20'>{text}</View>}
     </View>

+ 1 - 1
src/components/KnowledgeList/index.tsx

@@ -12,7 +12,7 @@ import { EKnowlegeTypes } from "@/consts/enum";
 import { useDidShow } from "@tarojs/taro";
 import { useEffect } from "react";
 
-import EmptyData from "../empty-data";
+import EmptyData from "../EmptyData";
 export interface IProps {
   multi?: boolean; // 是否多选
   types?: EKnowlegeTypes[]; // 列表类型

+ 3 - 3
src/components/LoginPopup/index.tsx

@@ -48,8 +48,8 @@ export default function Index({showPopup, setShowPopup, onEnd}:IProps) {
 
   return (
     <Popup setShow={setShowPopup} show={showPopup}>
-      <View className="text-24 text-center font-medium leading-36 text-black mb-12">欢迎来到小蓝本智能体</View>
-      <View className="text-gray-45 text-center text-14 leading-24 mb-40">
+      <View className="text-24 text-center font-medium leading-36 text-black mb-12 -mt-22">欢迎来到小蓝本智能体</View>
+      <View className="text-gray-45 text-center text-14 leading-24 mb-40 font-normal">
         <View>激活您的AI商务分身,开启智能商务</View>
         <View>7x24h随时应答·智能管理知识库·主动拓展人脉</View>
       </View>
@@ -67,7 +67,7 @@ export default function Index({showPopup, setShowPopup, onEnd}:IProps) {
       >
         手机号快速登录
       </Button>
-      <View className="flex items-center justify-center text-12 mb-86 text-center">
+      <View className="flex items-center justify-center text-12 mb-66 text-center">
         <View className="flex-center text-gray-45 gap-8" onClick={handleChecked}><WemetaRadio checkbox checked={checked}></WemetaRadio>同意</View>
         {agreements.map(item=> <Text onClick={()=> navToWebView(item.link)} className="primary-color">《{item.name}》</Text>)}
       </View>

+ 2 - 2
src/components/chat-message/MessageRobot.tsx

@@ -143,7 +143,7 @@ export default ({ agent, text, message, textReasoning = "" }: Props) => {
           <View className={style.avatarContainer}>
             <AvatarMedia source={agent?.avatarLogo || ''} className={style.avatar} mode="aspectFill"></AvatarMedia>
           </View>
-          <View className="font-medium text-16 leading-24">{agent?.name}</View>
+          <View className="font-medium text-16 leading-24 truncate">{agent?.name}</View>
         </View>
       )}
 
@@ -160,7 +160,7 @@ export default ({ agent, text, message, textReasoning = "" }: Props) => {
           <Text>{text}</Text>
           {renderMessageBody()}
         </View>
-        <View className="flex gap-8">
+        <View className="flex gap-12">
           <View onClick={(e) => handleCopy(e, text)}>
             <IconCopy />
           </View>

+ 1 - 1
src/components/chat-message/index.module.less

@@ -47,7 +47,7 @@
   line-height: 28px;
   color: #111A34;
   word-break: break-all;
-  // max-width: 280px;
+  font-family: PingFang SC;
 }
 .deepThinkContainer{
   margin-bottom: 16px;

+ 1 - 1
src/components/chat-message/index.tsx

@@ -6,7 +6,7 @@ import { TAgentDetail } from "@/types/agent";
 interface Props {
   agent?: TAgentDetail|null,
   role: TChatRole,
-  text: string
+  text: string|Record<string, any>
   textReasoning?: string
   message: TMessage
 }

+ 7 - 0
src/images/svgs/index/IconIndexChat.svg

@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="design-iconfont">
+  <g fill="#414A64" fill-rule="nonzero">
+    <path d="M8.1850918,9.82400781 L4.47736133,9.82400781 C4.09612109,9.82400781 3.69338867,10.0480762 3.48210352,10.3666035 L2.93341016,10.8871875 L2.93231641,10.6866348 C2.93166553,10.6046685 2.91156848,10.5240273 2.87367773,10.4513418 C2.6817793,10.0884082 2.24226953,9.82454102 1.82730078,9.82454102 L1.02081055,9.82454102 L1.02081055,4.08336523 L1.19084766,4.08336523 C1.47269336,4.08336523 1.70120508,3.85485352 1.70120508,3.57291211 C1.70120508,3.29103906 1.47269336,3.06252734 1.19084766,3.06252734 L0.850882813,3.06252734 C0.381773438,3.06252734 0,3.45912109 0,3.94650977 L0,9.96186133 C0,10.44925 0.382798828,10.844832 0.852892578,10.844832 L1.82675391,10.844832 C1.85738969,10.8501934 1.88658491,10.8618352 1.91250391,10.8790254 L1.91708398,11.610498 C1.91761328,11.7220528 1.95474652,11.8303496 2.02278125,11.9187578 C2.18454687,12.1295781 2.42138477,12.2505469 2.67203125,12.2499921 C2.90785742,12.2499921 3.13137891,12.1428125 3.29166797,11.9555215 L4.23445312,11.0592344 C4.26554297,11.0296211 4.31045508,10.9663203 4.33297266,10.9295566 C4.37023497,10.8860155 4.42111626,10.8563424 4.47736133,10.8453516 L8.33720508,10.8453516 C8.65851318,10.8426164 8.95064117,10.6584071 9.0915918,10.3696523 C9.15431528,10.2829574 9.18791489,10.178597 9.18756315,10.0715918 L9.18756315,9.96184766 C9.18756315,9.67991992 8.9590293,9.4514082 8.67708789,9.4514082 C8.44282031,9.4514082 8.24476953,9.60967383 8.1850918,9.82400781 Z" transform="translate(2 2)"/>
+    <path d="M10.7188184,6.762 L9.91231445,6.762 C9.65662305,6.762 9.39829297,6.8697207 9.18754102,7.03148633 C9.13900586,7.06879688 9.08800977,7.10244336 9.04564063,7.14581055 C8.97483465,7.21814321 8.91437017,7.29991887 8.86596484,7.38881445 C8.82801332,7.46130893 8.80788376,7.54180373 8.80724414,7.62362891 L8.80623242,7.82520703 L8.25753906,7.30407617 C8.21929883,7.24635352 8.16923242,7.19636914 8.11976758,7.14581055 C7.89569922,6.91613672 7.57457422,6.762 7.26226758,6.762 L3.57289844,6.762 L3.57289844,1.02081055 L10.7188184,1.02081055 L10.7188184,6.762 Z M11.6574609,0.510439453 C11.521166,0.209808594 11.2291758,0 10.8887461,0 L3.4029707,0 C3.06254102,0 2.77055078,0.209808594 2.63425586,0.510439453 C2.58073892,0.627566372 2.55273065,0.754731374 2.55208789,0.883503906 L2.55208789,6.89932031 C2.55208789,6.98561719 2.56789258,7.06723828 2.58987695,7.14581055 C2.69345508,7.51281836 3.01658984,7.78283789 3.40242383,7.78283789 L7.2617207,7.78283789 C7.31757644,7.79359154 7.36823775,7.82269966 7.4056582,7.86553906 C7.43136624,7.91445275 7.46499846,7.95877059 7.50518945,7.99669336 L8.44797461,8.89298047 C8.60818164,9.08083203 8.83178516,9.18754102 9.06707813,9.18754102 L9.06761133,9.18754102 C9.31823047,9.18754102 9.555,9.06705078 9.71686133,8.85628516 C9.78487365,8.76784404 9.82197767,8.65952431 9.82247656,8.54795703 L9.82707031,7.81600586 C9.85282769,7.7990394 9.88189122,7.78772992 9.9123418,7.78282422 L10.8867363,7.78282422 C11.2735957,7.78282422 11.5977559,7.51280469 11.701334,7.14579687 C11.7238379,7.06722461 11.7396563,6.98558984 11.7396563,6.89930664 L11.7396563,0.883503906 C11.7389912,0.754730919 11.7109742,0.627568681 11.6574609,0.510439453 Z" transform="translate(2 2)"/>
+    <path d="M5.20667383,3.44564063 C5.06989909,3.68264694 5.06998249,3.97462459 5.20689258,4.21155273 C5.34380636,4.44846315 5.59669297,4.59435305 5.87032031,4.59428325 C6.29315039,4.59411914 6.63583594,4.25120117 6.63567199,3.82837109 C6.63553516,3.40554102 6.29267188,3.0628418 5.86975977,3.06300502 C5.59616046,3.06260217 5.34338799,3.20864733 5.20667383,3.44564063 Z M7.75877539,3.44564063 C7.62200066,3.68264694 7.62208405,3.97462459 7.75899414,4.21155273 C7.89590792,4.44846315 8.14879453,4.59435305 8.42242187,4.59428325 C8.84525195,4.59411914 9.18792383,4.25120117 9.18777354,3.82837109 C9.18763672,3.40554102 8.84477344,3.0628418 8.42186133,3.06300502 C8.14826202,3.06260217 7.89548955,3.20864733 7.75877539,3.44564063 Z" transform="translate(2 2)"/>
+  </g>
+</svg>

File diff suppressed because it is too large
+ 1 - 0
src/images/svgs/index/IconIndexContent.svg


+ 6 - 0
src/images/svgs/index/IconIndexProfile.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="design-iconfont">
+  <g fill="#414A64" fill-rule="nonzero">
+    <path d="M10.3134609,3.14942745e-06 L1.02694922,3.14942745e-06 C0.459962891,0.000881313175 0.000546875,0.460461391 0,1.02757077 L0,10.3211508 C0,10.8875219 0.461138672,11.3476626 1.02749609,11.3476626 L10.3201602,11.3476626 C10.8868594,11.347061 11.3462617,10.8883149 11.3476562,10.3216977 L11.3476562,1.02757077 C11.3453867,0.45841061 10.8826074,-0.00138821808 10.3134609,3.14942745e-06 L10.3134609,3.14942745e-06 Z M6.18961328,10.3185669 L1.03157031,10.3211508 L1.03054492,8.76854538 L1.02954688,6.18942819 L1.02897266,5.15772116 L1.02749609,2.57860397 L1.02694922,1.03118014 L10.3134746,1.03118014 L10.3160859,1.02804928 L10.3201738,10.3165161 L6.18961328,10.3185669 L6.18961328,10.3185669 Z" transform="translate(2 2)"/>
+    <path d="M3.04089844,2.63308639 C2.75597656,2.63308639 2.52507227,2.8640317 2.52507227,3.14896725 C2.52507227,3.43382077 2.75599023,3.66473874 3.04089844,3.66473874 C3.32573828,3.66473874 3.55665625,3.43382077 3.55665625,3.14896725 C3.55665625,2.8640317 3.32573828,2.63308639 3.04089844,2.63308639 Z M3.04089844,5.21223092 C2.75597656,5.21223092 2.52507227,5.44314889 2.52507227,5.72808444 C2.52507227,6.01293795 2.75599023,6.24388327 3.04089844,6.24388327 C3.32573828,6.24388327 3.55665625,6.01293795 3.55665625,5.72808444 C3.55665625,5.44314889 3.32573828,5.21223092 3.04089844,5.21223092 L3.04089844,5.21223092 Z M3.04089844,7.79134811 C2.75597656,7.79134811 2.52507227,8.02226608 2.52507227,8.30720163 C2.52507227,8.59205514 2.75599023,8.82300045 3.04089844,8.82300045 C3.32573828,8.82300045 3.55665625,8.59205514 3.55665625,8.30720163 C3.55665625,8.02226608 3.32573828,7.79134811 3.04089844,7.79134811 Z M8.33771094,2.63308639 L4.72699609,2.63308639 C4.44215625,2.63308639 4.21126562,2.8640317 4.21126562,3.14896725 C4.21126562,3.43382077 4.44215625,3.66473874 4.72699609,3.66473874 L8.33769727,3.66473874 C8.62253711,3.66473874 8.85345508,3.43382077 8.85345508,3.14896725 C8.85345508,2.8640317 8.62255078,2.63308639 8.33771094,2.63308639 Z M8.33771094,7.79134811 L4.72699609,7.79134811 C4.44215625,7.79134811 4.21126562,8.02226608 4.21126562,8.30720163 C4.21126562,8.59205514 4.44215625,8.82300045 4.72699609,8.82300045 L8.33769727,8.82300045 C8.62253711,8.82300045 8.85345508,8.59205514 8.85345508,8.30720163 C8.85345508,8.02226608 8.62255078,7.79134811 8.33771094,7.79134811 Z M8.33771094,5.21223092 L4.72699609,5.21223092 C4.44215625,5.21223092 4.21126562,5.44314889 4.21126562,5.72808444 C4.21126562,6.01293795 4.44215625,6.24388327 4.72699609,6.24388327 L8.33769727,6.24388327 C8.62253711,6.24388327 8.85345508,6.01293795 8.85345508,5.72808444 C8.85345508,5.44314889 8.62255078,5.21223092 8.33771094,5.21223092 L8.33771094,5.21223092 Z" transform="translate(2 2)"/>
+  </g>
+</svg>

+ 46 - 10
src/pages/chat/components/input-bar/chatInput.ts

@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { useEffect, useState } from "react";
 import TextInputBar from "./TextInputBar";
 import VoiceInputBar from "./VoiceInputBar";
 import { textChat } from "@/service/bot";
@@ -9,7 +9,7 @@ import { EAI_MODEL } from "@/consts/enum";
 import { useUnload } from "@tarojs/taro";
 import { EChatRole, EContentType } from "@/types/bot";
 
-import { saveMessageToServer } from './message'
+import { usePostMessage } from './message'
 
 import { getRecommendPrompt } from "@/service/bot"
 
@@ -34,6 +34,7 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
     setQuestions,
     questions,
   } = useTextChat();
+  const { startTimedMessage, stopTimedMessage, isTimedMessageRunning, saveMessageToServer } = usePostMessage(getCurrentRobotMessage);
   
   let myMsgUk = '';
   let mySessionId = '';
@@ -65,17 +66,22 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
       contentType: EContentType.TextPlain,
       role: EChatRole.User,
     }
-    
-    saveMessageToServer({
+    // 等发送的消息上报完成
+    const myMsgResponse = await saveMessageToServer({
       loginId,
       messages: [{
         ...newMsg,
+        saveStatus: 2,
         isStreaming: false,
         msgUk,
       }],
       agentId: agent.agentId,
       sessionId,
     })
+    
+    if(!isSuccess(myMsgResponse.status)){
+      return setDisabled?.(false);
+    }
 
     // 发起文本聊天
     stopReceiveChunk = textChat({
@@ -89,17 +95,34 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
         sessionId,
       },
       onStart: () => {
-        currentRobotMsgUk = pushRobotMessage({
+        // 推一个空回复,用于展示 ui
+        const blankMessage = {
           role: EChatRole.Assistant,
-          saveStatus: 2,
+          contentType: EContentType.TextPlain,
+          saveStatus: 0,
           content: "",
           reasoningContent: "",
+          isStreaming: false,
+          msgUk: currentRobotMsgUk,
+          dislikeReason: '',
           robot: {
             avatar: agent?.avatarUrl ?? "",
             name: agent?.name ?? "",
             agentId: agent?.agentId ?? "",
           },
-        });
+        }
+        currentRobotMsgUk = pushRobotMessage(blankMessage);
+        // 先暂停
+        stopTimedMessage()
+        // 开始定时发送,每5秒发送一次
+        startTimedMessage({
+          loginId,
+          messages: [{
+            ...blankMessage,
+          }],
+          agentId: agent.agentId ?? '',
+          sessionId,
+        }, 5000);
       },
       onReceived: (m) => {
         console.log("received:", m);
@@ -116,6 +139,8 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
       onFinished: async () => {
         const currentRobotMessage = getCurrentRobotMessage();
         console.log("回复完毕 ok, 当前robotmessage: ", currentRobotMessage);
+        
+        stopTimedMessage()
         if(!agent.agentId){
           return
         }
@@ -128,10 +153,13 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
         
         // 将智能体的回答保存至服务器
         // currentRobotMessage.content 保存的是当前完整的智能体回复信息文本
+        const content = currentRobotMessage.content ?? currentRobotMessage?.body?.content
+        updateRobotMessage(content, currentRobotMessage?.body, 2)
         await saveMessageToServer({
           loginId,
           messages: [{
-            content: currentRobotMessage.content ?? currentRobotMessage?.body?.content,
+            saveStatus: 2,
+            content: content,
             contentType: currentRobotMessage?.body?.contentType ?? EContentType.TextPlain,
             isStreaming: false,
             role: currentRobotMessage.role,
@@ -151,9 +179,12 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
         }
 
       },
+      onComplete: ()=> {
+        stopTimedMessage()
+        setDisabled?.(false);
+      },
       onError: () => {
         deleteMessage(currentRobotMsgUk);
-        setDisabled?.(false);
       },
     });
   };
@@ -183,10 +214,15 @@ export const useChatInput = ({ agent, setShowWelcome, setDisabled, }: Props) =>
   const handleVoiceError = () => {
     deleteMessage(myMsgUk);
   };
-
+  useEffect(()=> {
+    return ()=> {
+      stopTimedMessage();
+    }
+  }, [])
   useUnload(() => {
     if (stopReceiveChunk) {
       stopReceiveChunk();
+      stopTimedMessage();
     }
   });
   return {

+ 132 - 3
src/pages/chat/components/input-bar/message.ts

@@ -1,6 +1,8 @@
 import { appendMessages } from "@/service/bot"
-import { type TMessageHistories, type TRequestBody, type TAppendMessages, EContentType } from "@/types/bot";
-export const saveMessageToServer = async(data: TAppendMessages) => {
+import { type TMessageHistories, type TRequestBody, type TAppendMessages, TRobotMessage, EContentType } from "@/types/bot";
+import { useRef, useEffect, useState } from "react";
+
+export const saveMessageToServer = (data: TAppendMessages) => {
   const postData = {
     ...data,
     messages: data.messages.map((message)=> {
@@ -12,5 +14,132 @@ export const saveMessageToServer = async(data: TAppendMessages) => {
       return message
     })
   }
-  await appendMessages(postData)
+  return appendMessages(postData)
 }
+
+// 定时上报智能体回复的消息体
+
+export const usePostMessage = (getCurrentRobotMessage:() => TRobotMessage | undefined)=> {
+  const timerRef = useRef<NodeJS.Timeout | null>(null);
+  const isRunningRef = useRef(false);
+  const [isRunning, setIsRunning] = useState(false);
+
+  // 组件卸载时清理定时器
+  useEffect(() => {
+    return () => {
+      if (timerRef.current) {
+        clearInterval(timerRef.current);
+        timerRef.current = null;
+      }
+      isRunningRef.current = false;
+      setIsRunning(false);
+    };
+  }, []);
+
+  // 开始定时发送消息
+  const startTimedMessage = (data: TAppendMessages, interval: number = 5000) => {
+    if (isRunningRef.current) {
+      console.warn('定时任务已在运行中');
+      return;
+    }
+
+    isRunningRef.current = true;
+    setIsRunning(true);
+    console.log('开始定时发送消息,间隔:', interval, 'ms');
+
+    const sendMessage = async () => {
+      try {
+        // 获取当前智能体回答,上报至服务端
+        const msg = getCurrentRobotMessage()
+        if(!msg){
+          return 
+        }
+        await saveMessageToServer({
+          ...data,
+          messages: [{
+            ...msg,
+            saveStatus: msg.saveStatus ?? 1
+          }]
+        });
+        console.log('定时发送消息成功');
+      } catch (error) {
+        console.error('定时发送消息失败:', error);
+      }
+    };
+
+    // 立即发送一次
+    // sendMessage();
+
+    // 设置定时器,每 interval 毫秒发送一次
+    timerRef.current = setInterval(sendMessage, interval);
+  };
+
+  // 停止定时发送消息
+  const stopTimedMessage = () => {
+    if (timerRef.current) {
+      clearInterval(timerRef.current);
+      timerRef.current = null;
+    }
+    isRunningRef.current = false;
+    setIsRunning(false);
+    console.log('定时发送消息已停止');
+  };
+
+  // 检查定时任务是否正在运行
+  const isTimedMessageRunning = () => {
+    return isRunning;
+  };
+
+  return {
+    saveMessageToServer,
+    startTimedMessage,
+    stopTimedMessage,
+    isTimedMessageRunning,
+  }
+}
+
+/*
+使用示例:
+
+import { usePostMessage } from './message';
+
+const MyComponent = () => {
+  const { startTimedMessage, stopTimedMessage, isTimedMessageRunning } = usePostMessage();
+  
+  const handleStartTimer = () => {
+    const messageData = {
+      agentId: 'your-agent-id',
+      loginId: 'your-login-id',
+      sessionId: 'your-session-id',
+      messages: [{
+        content: '定时消息内容',
+        contentType: EContentType.TextPlain,
+        isStreaming: false,
+        msgUk: 'unique-message-id',
+        role: EChatRole.User
+      }]
+    };
+    
+    // 开始定时发送,每5秒发送一次
+    startTimedMessage(messageData, 5000);
+  };
+  
+  const handleStopTimer = () => {
+    stopTimedMessage();
+  };
+  
+  const isRunning = isTimedMessageRunning();
+  
+  return (
+    <View>
+      <Button onClick={handleStartTimer} disabled={isRunning}>
+        开始定时发送
+      </Button>
+      <Button onClick={handleStopTimer} disabled={!isRunning}>
+        停止定时发送
+      </Button>
+      <Text>状态: {isRunning ? '运行中' : '已停止'}</Text>
+    </View>
+  );
+};
+*/

+ 1 - 1
src/pages/chat/components/personal-card/index.tsx

@@ -23,7 +23,7 @@ export default ({size='large', agent}:IProps) => {
             {agent?.isEnt && <View className="text-12 leading-12"><IconCertificateColor/></View>}
           </View>
           {agent?.entId && <View className="flex items-center gap-2">
-            <View className="text-gray-45 text-12 leading-12 truncate max-w-[180px]">
+            <View className="text-12 leading-12 truncate max-w-[180px]">
               {agent?.entName}
             </View>
           </View>}

+ 1 - 1
src/pages/chat/index.module.less

@@ -24,7 +24,7 @@
   left: 0;
   right: 0;
   z-index: 1;
-  height: 652px;
+  height: 100vh;
   width: 100%;
   background-repeat: no-repeat;
   background-position: center center;

+ 18 - 8
src/pages/chat/index.tsx

@@ -17,7 +17,7 @@ import { useAgentStore } from "@/store/agentStore";
 
 import { useLoadMoreInfinite, createKey } from "@/utils/loadMoreInfinite";
 import { getMessageHistories } from "@/service/bot";
-import { useAppStore } from "@/store/appStore";
+// import { useAppStore } from "@/store/appStore";
 
 import RecommendQuestions from './components/RecommendQuestions'
 import {useKeyboard} from './components/keyboard'
@@ -25,7 +25,7 @@ import {useKeyboard} from './components/keyboard'
 
 export default function Index() {
   const router = useRouter();
-  const bottomSafeHeight = useAppStore((state) => state.bottomSafeHeight);
+  // const bottomSafeHeight = useAppStore((state) => state.bottomSafeHeight);
   const { agentId, isVisitor } = router.params;
   if (!agentId) {
     return <View>没有相应的智能体</View>;
@@ -49,8 +49,9 @@ const agent = useAgentStore((state) => {
   
 
   
-  const { destroy, setScrollTop, genSessionId } = useTextChat();
+  const { destroy, setScrollTop, genSessionId, setAutoScroll } = useTextChat();
   const scrollTop = useTextChat((state) => state.scrollTop);
+  // const autoScroll = useTextChat((state) => state.autoScroll);
 
   const fetcher = async ([_url,{ nextId, pageSize}]) => {
     if (!agent) {
@@ -75,7 +76,7 @@ const agent = useAgentStore((state) => {
         const contentJson = JSON.parse(item.content as string)
         item.content = contentJson.answer.text
         // 把消息详情放入统一 body 中
-        item.body = {...item, content: contentJson,}
+        item.body = {...item, content: contentJson, contentType: EContentType.AiseekQA}
       }catch(e){
         // console.error(e)
       }
@@ -90,6 +91,13 @@ const agent = useAgentStore((state) => {
     console.log("onscroll");
     loadMore();
   };
+
+  const handleTouchMove = ()=> {
+    console.log('set auto scroll false')
+    setAutoScroll(false)
+  }
+
+
   useDidShow(()=> {
     mutate(undefined,{revalidate: true})
   })
@@ -145,7 +153,7 @@ const agent = useAgentStore((state) => {
   };
 
   
-
+  // 大背景可以是视频,也可以是图片
   const renderTopBg = ()=> {
     if(!agent?.avatarUrl || !!!agent?.enabledChatBg){
       return <></>;
@@ -172,7 +180,7 @@ const agent = useAgentStore((state) => {
   return (
     <PageCustom fullPage style={{ overflow: "hidden" }}>
       <NavBarNormal blur leftColumn={renderNavLeft}>
-        {/* {marginTopOffset} */}
+        {/* <>{`${scrollTop}`}--{autoScroll ? 'true': 'false'}</> */}
       </NavBarNormal>
       {renderTopBg()}
       <View
@@ -190,15 +198,17 @@ const agent = useAgentStore((state) => {
           scrollTop={scrollTop}
           scrollWithAnimation
           onScrollToUpper={onScrollToUpper}
+          onScrollToLower={()=> setAutoScroll(true)}
         >
           {showWelcome && <ChatWelcome agent={agent} />}
-          <View id="messageList" className="flex flex-col gap-8 px-18">
+          <View id="messageList" className="flex flex-col gap-8 px-18" onTouchMove={handleTouchMove}>
             {/* 复制 histories 再 reverse 否则会影响 state */}
             {[...[...parsedList].reverse(), ...messageList].map((message) => {
+              const reasoningContent = message.role === EChatRole.Assistant ? message.reasoningContent : ''
               return (
                 <ChatMessage
                   key={message.msgUk}
-                  textReasoning={message?.reasoningContent}
+                  textReasoning={reasoningContent}
                   agent={agent}
                   role={message.role}
                   text={message.content}

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

@@ -1,6 +1,6 @@
 import Taro, { useDidShow, useReachBottom } from "@tarojs/taro";
 import { View, Text, ScrollView } from "@tarojs/components";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 import NavBarNormal from "@/components/NavBarNormal/index";
 import SearchBar from "@/components/search-bar/index";
 import style from "./index.module.less";

+ 1 - 1
src/pages/dislike-messages/index.tsx

@@ -20,7 +20,7 @@ import { TVisitorChat } from "@/types/visitor";
 import { useModalStore } from "@/store/modalStore";
 import { isSuccess } from "@/utils";
 import { useLoadMoreInfinite, createKey } from "@/utils/loadMoreInfinite";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 import { EContentType } from "@/types/bot";
 
 export default function Index() {

+ 8 - 4
src/pages/index/components/WelcomeTips/index.module.less

@@ -1,8 +1,8 @@
 .container{
   width: 100%;
-  padding: 12px;
+  padding: 16px;
   position: fixed;
-  bottom: 16px;
+  bottom: 0;
   left: 0;
   right: 0;
   z-index: 2;
@@ -24,6 +24,7 @@
 .content{
   position: relative;
   padding-top: 260px;
+  width: 100%;
   z-index: 2;
   display: flex;
   justify-content: center;
@@ -36,7 +37,7 @@
   border-radius: 8px;
   width: 312px;
   background-color:rgba(255, 255, 255, 0.4);
-  backdrop-filter: blur(7px) brightness(0.94) contrast(146%) grayscale(3%) opacity(81%);
+  backdrop-filter: blur(7px) brightness(0.86) contrast(146%) grayscale(3%) opacity(81%);
   margin-bottom: 8px;
 }
 .hello {
@@ -65,18 +66,21 @@
 .box {
   border-radius: 12px;
   padding: 16px;
+  width: 100%;
   background-color: white;
 }
 
 .boxInner {
   padding: 16px;
-  min-height: 184px;
+  width: 100%;
+  height: 184px;
   margin-bottom: 16px;
   background-image: linear-gradient(45deg, #f2fcff 0%, #EBF5FF 49%, #E2EAFF 100%);
   border-radius: 8px;
 }
 
 .headline {
+  font-family: PingFangSC-Medium;
   margin-bottom: 16px;
   font-weight: 500;
   font-size: 16px;

+ 6 - 0
src/pages/index/components/WelcomeTips/index.tsx

@@ -4,6 +4,9 @@ import Taro from "@tarojs/taro";
 import LoginPopup from '@/components/LoginPopup'
 import { useAgentStore } from "@/store/agentStore";
 import { useState } from "react";
+import IconIndexProfile from '@/images/svgs/index/IconIndexProfile.svg'
+import IconIndexChat from '@/images/svgs/index/IconIndexChat.svg'
+import IconIndexContent from '@/images/svgs/index/IconIndexContent.svg'
 interface IProps {
   // children: JSX.Element|JSX.Element[]
 }
@@ -50,12 +53,15 @@ export default function Index({}: IProps) {
             </View>
             <View className={style.list}>
                 <View className="flex items-center gap-6">
+                  <Image src={IconIndexProfile} className="w-16 h-16"></Image>
                   <View>企业 + 个人资料统一管理</View>
                 </View>
                 <View className="flex items-center gap-6">
+                  <Image src={IconIndexChat} className="w-16 h-16"></Image>
                   <View>客户问题,AI 自动回应</View>
                 </View>
                 <View className="flex items-center gap-6">
+                  <Image src={IconIndexContent} className="w-16 h-16"></Image>
                   <View>你的内容,一页呈现</View>
                 </View>
             </View>

+ 1 - 1
src/pages/knowledge/components/CompanyList/index.tsx

@@ -1,6 +1,6 @@
 import { View } from "@tarojs/components";
 
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 import { useEffect, useState } from "react";
 
 import PickerSingleColumn from "@/components/Picker/PickerSingleColumn";

+ 1 - 1
src/pages/knowledge/components/CompanyTab/components/ScrollList.tsx

@@ -4,7 +4,7 @@ import FigureList from "@/components/list/FigureList";
 import FigureListItem from "@/components/list/FigureListItem";
 import { useDidShow } from "@tarojs/taro";
 import { useEffect, useState } from "react";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 import RotateLoading from "@/components/rotate-loading";
 import Taro from "@tarojs/taro";
 import IconError from '@/images/svgs/knowledge/IconError.svg'

+ 1 - 1
src/pages/knowledge/components/CompanyTab/components/ScrollListChat.tsx

@@ -4,7 +4,7 @@ import MessageRich from "@/components/chat-message/MessageRich";
 
 import FigureList from "@/components/list/FigureList";
 import FigureListItem from "@/components/list/FigureListItem";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 
 import { useEffect, useRef, useState } from "react";
 import Taro, { useDidShow } from "@tarojs/taro";

+ 1 - 1
src/pages/knowledge/components/CorrectionTab/index.tsx

@@ -1,5 +1,5 @@
 import { View } from "@tarojs/components";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 
 import StyleFilter, { TListStyle } from "../StyleFilter";
 import { useRef, useState } from "react";

+ 1 - 1
src/pages/knowledge/components/PersonalTab/components/ScrollList.tsx

@@ -11,7 +11,7 @@ import Taro from "@tarojs/taro";
 
 import { EKnowlegeTypes } from "@/consts/enum";
 import KnowledgeIcon from "@/components/KnowledgeIcon";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 
 import type { TKnowledgeItem } from "@/types/knowledge";
 

+ 1 - 1
src/pages/visiteor-detail/index.tsx

@@ -15,7 +15,7 @@ import { getVisitorSessions } from "@/service/visitor";
 
 import style from "./index.module.less";
 import { useLoadMoreInfinite, createKey } from "@/utils/loadMoreInfinite";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 
 export default () => {
   const router = useRouter();

+ 1 - 0
src/pages/voice/components/MyVoiceList/components/popup-recorder/index.tsx

@@ -105,6 +105,7 @@ export default ({
     console.log(response?.publicUrl, 'publicUrl');
     if (response && response.publicUrl) {
       Taro.showLoading();
+      console.log({sourceUrl: response.publicUrl, entId}, 'clone started');
       const res = await cloneVoice({sourceUrl: response.publicUrl, voiceText: readText, entId});
       Taro.hideLoading();
       if(isSuccess(res.status)){

+ 1 - 1
src/pages/voice/components/MyVoiceList/index.tsx

@@ -1,4 +1,4 @@
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 import CardListItem from "@/components/list/card-list-item/index";
 
 import WemetaRadio from "@/components/WemetaRadio/index";

+ 1 - 1
src/pages/voice/components/VoiceList/index.tsx

@@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
 import CardListItem from "@/components/list/card-list-item";
 import { TVoiceItem } from "@/types/voice";
 import { TAgentDetail } from "@/types/agent";
-import EmptyData from "@/components/empty-data";
+import EmptyData from "@/components/EmptyData";
 
 export default function Index({
   onPlay,

+ 5 - 1
src/service/bot.ts

@@ -81,6 +81,7 @@ export type TTextChatParams = {
   onStart: () => void;
   onReceived: (m: ICompleteCallback) => void;
   onFinished: () => void;
+  onComplete?: () => void; // 无论失败或成功都会执行
   onError: () => void;
 };
 
@@ -89,6 +90,7 @@ export const textChat = ({
   onStart,
   onReceived,
   onFinished,
+  onComplete,
   onError,
 }: TTextChatParams) => {
   onStart();
@@ -124,15 +126,17 @@ export const textChat = ({
       responseType: "arraybuffer",
       success: function (res) {
         console.log("服务端响应 >>", res);
+        onComplete?.()
       },
       complete: function(res) {
-        console.log(res,4444)
+        onComplete?.()
       }
     });
 
     // reqTask.
     reqTask.onChunkReceived(onChunkReceived);
   } catch (e) {
+    onComplete?.()
     onError();
   }
 

+ 24 - 15
src/store/textChat.ts

@@ -5,8 +5,8 @@
 import { create } from "zustand";
 import { generateUUID } from '@/utils/index'
 
-import { getMessageHistories as _getMessageHistories, appendMessages, type TGetMessageHistoriesParams,  } from '@/service/bot'
-import { EChatRole, EContentType, TChatRole } from "@/types/bot";
+import { getMessageHistories, type TGetMessageHistoriesParams,  } from '@/service/bot'
+import { EChatRole, TAnyMessage, TRobotMessage, TMessage } from "@/types/bot";
 
 
 
@@ -21,10 +21,12 @@ const INIT_CURRENT_ROBOT_MSG_UK = ''
 export interface TextChat {
   currentRobotMsgUk: string; // 当前正在说话的 AI 机器人 id, 可用于控制是否继续输出文本至当前 message 框内
   scrollTop: number; // 控制聊天内容变化后滚动至最底部
-  list: (TMessage | TRobotMessage)[];
+  autoScroll: boolean
+  list: TAnyMessage[];
   questions: string[]; //推荐问题
   sessionId: string|null
   // 显示聊天历史
+  setAutoScroll: (b: boolean) => void // 是否自动滚动
   genSessionId: () => void // 进入聊天界面后,本次的 sessionId
   setQuestions: (q:string[]) => void // 设置推荐问题
   setScrollTop: () => void
@@ -35,13 +37,13 @@ export interface TextChat {
   // 更新自己发出的气泡框
   updateMessage: (content: string, msgUk: string) => string;
   // 更新机器人汽泡框内的内容实现 gpt 的效果
-  updateRobotMessage: (content: string, body?: Record<string,any>) => void;
+  updateRobotMessage: (content: string, body?: Record<string,any>, saveStatus?: number) => void;
   updateRobotReasoningMessage: (msgUk: string, reasoningContent: string, body?:Record<string,any>) => void;
   getCurrentRobotMessage:() => TRobotMessage|undefined
   deleteMessage: (msgUk: string) => void;
   // 清空
   destroy: () => void;
-  getMessageHistories: (data: TGetMessageHistoriesParams) => void
+  fetchMessageHistories: (data: TGetMessageHistoriesParams) => void
 }
 
 // 新messageId 为 index 加 1
@@ -51,10 +53,14 @@ const generateUk = () => {
 
 export const useTextChat = create<TextChat>((set, get) => ({
   currentRobotMsgUk: INIT_CURRENT_ROBOT_MSG_UK,
-  scrollTop: 9999,
+  scrollTop: 999999,
+  autoScroll: true,
   list: [],
   sessionId: null,
   questions: [],
+  setAutoScroll: (b)=> {
+    set({autoScroll: b})
+  },
   setQuestions: (q:string[])=> {
     set({questions: q})
   },
@@ -77,8 +83,9 @@ export const useTextChat = create<TextChat>((set, get) => ({
   pushRobotMessage: (message) => {
     const msgUk = generateUk()
     set((state) => {
+      const newRobotMessage = { ...message, msgUk, role: EChatRole.Assistant } as TRobotMessage
       return {
-        list: [...state.list, { ...message, msgUk, role: EChatRole.Assistant }],
+        list: [...state.list, newRobotMessage],
         currentRobotMsgUk: msgUk,
         scrollTop: state.scrollTop + 1,
       };
@@ -122,7 +129,7 @@ export const useTextChat = create<TextChat>((set, get) => ({
     set((state) => {
       const updatedList = state.list.map((message) => {
         if (message.msgUk === msgUk) {
-          return { ...message, content: message.content + content }; // 更新 content
+          return { ...message, content: message.content + content, saveStatus: 0  }; // 更新 content
         }
         return message; // 返回未修改的 message
       });
@@ -130,15 +137,17 @@ export const useTextChat = create<TextChat>((set, get) => ({
     });
     return msgUk
   },
-  updateRobotMessage: (content, body={}) => {
+  updateRobotMessage: (content, body={}, saveStatus: number = 0) => {
     set((state) => {
       const updatedList = state.list.map((message) => {
         if (message.msgUk === state.currentRobotMsgUk) {
-          return { ...message, content: message.content + content, body }; // 更新 content
+          // 更新消息后, saveStatus 变为 0,说明又需要上报此消息
+          return { ...message, content: message.content + content, body, saveStatus: saveStatus } as TRobotMessage  // 更新 content
         }
         return message; // 返回未修改的 message
       });
-      return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态
+      
+      return { list: updatedList, scrollTop:  state.autoScroll ?   state.scrollTop + 1 : state.scrollTop}; // 返回新的状态
     });
   },
   getCurrentRobotMessage: ()=> {
@@ -153,11 +162,11 @@ export const useTextChat = create<TextChat>((set, get) => ({
       const updatedList = state.list.map((message) => {
         if (message.msgUk === msgUk) {
           //@ts-ignore
-          return { ...message, body, reasoningContent: message.reasoningContent + reasoningContent }; // 更新 reasoningContent
+          return { ...message, body, reasoningContent: message.reasoningContent + reasoningContent } as TRobotMessage // 更新 reasoningContent
         }
         return message; // 返回未修改的 message
       });
-      return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态
+      return { list: updatedList, scrollTop: state.autoScroll ?   state.scrollTop + 1 : state.scrollTop}; // 返回新的状态
     });
   },
   deleteMessage: (msgUk)=> {
@@ -174,8 +183,8 @@ export const useTextChat = create<TextChat>((set, get) => ({
   stopCurrentRobotMessaging: ()=> {
     set({currentRobotMsgUk: INIT_CURRENT_ROBOT_MSG_UK})
   },
-  getMessageHistories: async (data: TGetMessageHistoriesParams) => {
-    const response = await _getMessageHistories(data)
+  fetchMessageHistories: async (data: TGetMessageHistoriesParams) => {
+    const response = await getMessageHistories(data)
     console.log(response)
     if(response.status){
       

+ 39 - 33
src/types/bot.ts

@@ -1,3 +1,28 @@
+export enum EContentType {
+  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 = EContentType[keyof EContentType];
+
 
 // contentType === "aiseek/qa" 消息体内容
 export type TMessageBodyContent = {
@@ -17,55 +42,35 @@ export type TMessageBody = {
 
 export type TMessage = {
   content: string|Record<string, any>,
-  contentType: EContentType
-  dislikeReason: string,
+  contentType?: EContentType
+  dislikeReason?: string,
   isDislike?: boolean,
   isLike?: boolean,
-  isStreaming: boolean,
-  msgId: number,
-  msgTime: string,
+  isStreaming?: boolean,
+  msgId?: number,
+  saveStatus?: number 
+  msgTime?: string,
   msgUk: string,
-  originalAgentId: string,
-  role: string
+  originalAgentId?: string,
+  role: EChatRole.User,
   body?: TMessageBody
 }
 
 export type TRobotMessage = {
   reasoningContent: string
-  body?: Record<string,any>
-  robot: {
+  role:  EChatRole.Assistant | EChatRole.System | EChatRole.Function
+  robot?: {
     avatar: string;
     agentId: string;
     name: string;
   };
 } & TMessage;
 
+export type TAnyMessage = TMessage | TRobotMessage;
 
 
-export enum EContentType {
-  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 = EContentType[keyof EContentType];
 
 
 export type TRequestMessage = {
@@ -87,8 +92,9 @@ export type TRequestBody = {
 export type TAppendMessage  = {
     content: any,
     contentType: TContentType,
-    isStreaming: false,
+    isStreaming: boolean,
     msgUk: string,
+    saveStatus: number,  //0|1|2
     role: TChatRole
 }
 export type TAppendMessages = {
@@ -101,5 +107,5 @@ export type TAppendMessages = {
 export type TMessageHistories = {
   data: TMessage|TRobotMessage[];
   nextId: string;
-  totalCount: 0;
+  totalCount: number|null;
 };

+ 3 - 0
tailwind.config.js

@@ -64,6 +64,9 @@ module.exports = {
       ...configFontSize,
     },
     extend: {
+      fontFamily: {
+        pingfangSCMedium: ['PingFangSC-Medium'],
+      },
       lineHeight: {
         '0': '0px',
         ...configLineHeight,

Some files were not shown because too many files changed in this diff