Browse Source

feat: 接入企业知识库接口

王晓东 1 month ago
parent
commit
d43b250797

+ 2 - 1
src/app.less

@@ -317,7 +317,8 @@
   left: 0;
   width: 100%;
   background: #fff;
-  z-index: 1000;
+  z-index: 3000;
+  box-shadow: 0px -2px 20px #999;
 }
 
 .picker-header {

+ 50 - 36
src/components/AgentPage/components/AgentSwap/index.tsx

@@ -24,6 +24,7 @@ export default ({ show, setShow }: IProps) => {
   const { agents, setDefaultAgent, fetchAgents } = useAgentStore()
   let loading = false
   const personalAgents = agents.filter( item => !item.isEnt)
+  const entAgents = agents.filter( item => item.isEnt)
 
   const handleClick = async (item: TAgent)=> {
     if(loading){
@@ -40,43 +41,62 @@ export default ({ show, setShow }: IProps) => {
     Taro.hideLoading()
   }
 
-  const renderPersonalAgents = ()=> {
-    return personalAgents.map((item) => {
-      return <View className={item.isDefault ? style.cardActive : style.card}>
-        <View className="flex items-start mb-24" onClick={()=> handleClick(item)}>
-          <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">
-                {item.name}
-              </View>
-              <View className="text-12 leading-20">销售医师</View>
-            </View>
-            <View className="flex items-center gap-2">
-              <View className="text-12 leading-20 truncate max-w-[188px]">
-                北京茗视光眼科医院管理有限公司
-              </View>
-              <TagCertificated />
-            </View>
+  const renderCard = (item: TAgent, isEnt: boolean) => {
+    return <View className={item.isDefault ? style.cardActive : style.card}>
+    <View className="flex items-start mb-24" onClick={()=> handleClick(item)}>
+      <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">
+            {item.name}
           </View>
+          <View className="text-12 leading-20">{item.position ?? '暂无职位信息'}</View>
         </View>
-        <View className={style.icons}>
-          <View className={style.icon}>
-            <IconPhoneGray />
-          </View>
-          <View className={style.icon}>
-            <IconMailGray />
-          </View>
-          <View className={style.icon}>
-            <IconLocationGray />
-          </View>
-          <View className={style.icon}>
-            <IconQRCodeGray />
+        <View className="flex items-center gap-2">
+          <View className="text-12 leading-20 truncate max-w-[188px]">
+            {item.entName ?? '暂无公司信息'}
           </View>
+          {isEnt && <TagCertificated />}
         </View>
       </View>
+    </View>
+    <View className={style.icons}>
+      <View className={style.icon}>
+        <IconPhoneGray />
+      </View>
+      <View className={style.icon}>
+        <IconMailGray />
+      </View>
+      <View className={style.icon}>
+        <IconLocationGray />
+      </View>
+      <View className={style.icon}>
+        <IconQRCodeGray />
+      </View>
+    </View>
+  </View>
+  }
+
+  const renderPersonalAgents = ()=> {
+    return personalAgents.map((item) => {
+      return renderCard(item, false)
     })
   }
 
+  const renderEntAgents = () => {
+    if(entAgents.length){
+      return entAgents.map((item) => {
+        return renderCard(item, true)
+      }) 
+    }
+    return <View className={style.card}>
+    <View className="flex flex-col items-center">
+      <View className="text-16 leading-24 font-medium mb-4">你还没有企业配置的名片</View>
+      <View className="text-12 text-gray-45 leading-20 mb-24">企业小蓝本由公司创建并授权,可引用企业知识内容</View>
+      <View className="text-primary font-medium leading-22">联系我们</View>
+    </View>
+  </View>
+  }
+
   const tabList = [
     {
       key: "1",
@@ -137,13 +157,7 @@ export default ({ show, setShow }: IProps) => {
         <>
           <View className="pt-12">
             <View className={style.tabContainer}>
-              <View className={style.card}>
-                <View className="flex flex-col items-center">
-                  <View className="text-16 leading-24 font-medium mb-4">你还没有企业配置的名片</View>
-                  <View className="text-12 text-gray-45 leading-20 mb-24">企业小蓝本由公司创建并授权,可引用企业知识内容</View>
-                  <View className="text-primary font-medium leading-22">联系我们</View>
-                </View>
-              </View>
+            {renderEntAgents()}
             </View>
           </View>
         </>

+ 1 - 1
src/components/list/figure-list-item/index.tsx

@@ -14,7 +14,7 @@ const Index = ({ figure, arrow, underline, rightRenderer, children, onClick }: I
   return (
     <View className={`flex items-center gap-12 w-full ${underline ? 'border-bottom1-gray pb-12' : ''}`} onClick={ ()=> { onClick && onClick()}}>
       {figure()}
-      <View className="flex flex-col flex-1 gap-2 w-full">{children}</View>
+      <View className="flex flex-col flex-1 gap-2 w-full overflow-hidden">{children}</View>
       {rightRenderer && rightRenderer()}
       {arrow && (
         <View className="flex items-center justify-center">

+ 20 - 18
src/pages/knowledge-item-editor/index.tsx

@@ -30,14 +30,15 @@ import { isSuccess } from "@/utils";
 
 type TFormdata = {q:string, a: string, links: string[], mediaList: TMediaType[]}
 
+
 interface IProps {
   initialData?: TFormdata
 }
 export default function Index() {
 
   const router = useRouter()
-  const { knowledgeId, qaId } = router.params
-  const loadingRef = useRef(false)
+  const { knowledgeId, qaId, knowledgeTitle } = router.params
+  
   const [formData, setFormData] = useState<TFormdata>(
     {
       q: '',
@@ -80,7 +81,7 @@ export default function Index() {
   };
 
   // 更新单个链接
-  const handleLinkChange = (index, value) => {
+  const handleLinkChange = (index:number, value: string) => {
     const newLinks = [...formData.links];
     newLinks[index] = value;
     setFormData({
@@ -109,10 +110,13 @@ export default function Index() {
       pics: formData.mediaList.map( item => item.url)
     }
     console.log(dataToSubmit)
-    await updateKnowledgeQa(knowledgeId, qaId, dataToSubmit)
+    const {status} = await updateKnowledgeQa(knowledgeId, qaId, dataToSubmit)
+    if(isSuccess(status)){
+      Taro.showToast({title: '保存成功', icon: 'success'})
+    }
   }
   const getQaDetail = async (knowledgeId: string, qaId: string)=> {
-    const {status, data} = await  getKnowledgeQa(knowledgeId, qaId)
+    const {status, data} = await getKnowledgeQa(knowledgeId, qaId)
     if(isSuccess(status)){
       setFormData({
         q: data.questions[0],
@@ -132,21 +136,17 @@ export default function Index() {
       mediaType: ["image"],
       sourceType: ["album", "camera"],
       async success(r) {
-        const tempFiles = r.tempFiles
-        // const tmpPath = tempFile.tempFilePath;
-        for(let i =0; i< tempFiles.length;i++){
-          const result = await uploadFile(tempFiles[0].tempFilePath, EUploadFileScene.OTHER)
+        // const tempFiles = r.tempFiles;
+        for (const tempFile of r.tempFiles){
+          const result = await uploadFile(tempFile.tempFilePath, EUploadFileScene.OTHER)
           if(result?.publicUrl){
-            setFormData({
-              ...formData,
-              mediaList: [{fileType:'image', url: result.publicUrl}, ...formData.mediaList]
-            });
+            setFormData(prev => {
+              return {...prev, mediaList: [{fileType:'image', url: result.publicUrl}, ...prev.mediaList]}
+            })
           }
         }
-        
-        
-      },
-    });
+      }
+    })
   }
 
   useEffect(()=> {
@@ -156,9 +156,11 @@ export default function Index() {
     
   }, [knowledgeId, qaId])
 
+  
+
   return (
     <PageCustom>
-      <NavBarNormal scrollFadeIn backText="飞秒小知识"></NavBarNormal>
+      <NavBarNormal scrollFadeIn backText={knowledgeTitle ?? '...'}></NavBarNormal>
       <View className="w-full pb-120">
         <View className="p-16">
           <View className="flex flex-col gap-16">

+ 4 - 0
src/pages/knowledge-item/index.module.less

@@ -4,4 +4,8 @@ page{
 .scrollContainer{
   height: calc(100vh - 400px);
   overflow: auto;
+}
+.scrollContainerHigher{
+  height: calc(100vh - 300px);
+  overflow: auto;
 }

+ 172 - 91
src/pages/knowledge-item/index.tsx

@@ -2,7 +2,7 @@
  * 知识库
  */
 
-import { Text, View,Image, ScrollView } from "@tarojs/components";
+import { Text, View, Image, ScrollView } from "@tarojs/components";
 
 import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
@@ -15,68 +15,112 @@ import IconQ from "@/components/icon/IconQ";
 import WemetaSwitch from "@/components/wemeta-switch";
 import { useEffect, useState } from "react";
 import CardEditable from "@/components/card/card-editable/index";
-import Taro, { useRouter } from "@tarojs/taro";
-import { getMyKnowledgeDetail, deleteKnowledgeQa, updateExactAnswer } from "@/service/knowledge";
-import { TKnowledgeDetail } from "@/types/knowledge";
+import Taro, { useRouter, useDidShow } from "@tarojs/taro";
+import {
+  getMyKnowledgeDetail,
+  getEntKnowledgeDetail,
+  deleteKnowledgeQa,
+  updateExactAnswer,
+  deleteKnowledge,
+} from "@/service/knowledge";
+import { TKnowledgeDetail,TQAListItem } from "@/types/knowledge";
 import { isSuccess } from "@/utils";
 import { useModalStore } from "@/store/modalStore";
-import style from './index.module.less'
+import style from "./index.module.less";
 
 export default function Index() {
-  const router = useRouter()
-  const { knowledgeId } = router.params
+  const router = useRouter();
+  const { knowledgeId, entId } = router.params;
   const [checked, setChecked] = useState(false);
-  const [detail, setDetail] = useState<TKnowledgeDetail|null>(null)
-  
-  const { showModal } = useModalStore()
+  const [detail, setDetail] = useState<TKnowledgeDetail | null>(null);
+
+  const isEnt = (entId !== undefined)
+  const { showModal } = useModalStore();
+
   
-  const handleEdit = (qaId: number)=> {
+
+  const handleEdit = (qaId: number | string) => {
     Taro.navigateTo({
-      url: `/pages/knowledge-item-editor/index?knowledgeId=${knowledgeId}&qaId=${qaId}`
-    })
-  }
+      url: `/pages/knowledge-item-editor/index?knowledgeId=${knowledgeId}&qaId=${qaId}&knowledgeTitle=${detail?.title}`,
+    });
+  };
+  const handleView = (qaId: number | string) => {
+    Taro.navigateTo({
+      url: `/pages/knowledge-item-detail/index?knowledgeId=${knowledgeId}&qaId=${qaId}&knowledgeTitle=${detail?.title}`,
+    });
+  };
   // 删除问答项
-  const handleDeleteItem = async (qaId: number)=> {
-    if(!detail){
-      return
+  const handleDeleteItem = async (qaId: number | string) => {
+    if (!detail) {
+      return;
     }
     showModal({
-      content: '确定删除该问答项吗?',
+      content: "确定删除该问答项吗?",
       onConfirm: async () => {
-        const { status }  = await deleteKnowledgeQa(detail.knowledgeId, qaId)
-        if(isSuccess(status)){
-          Taro.showToast({title: '删除成功', icon: 'success'})
-          getDetail(detail.knowledgeId)
+        const { status } = await deleteKnowledgeQa(detail.knowledgeId, qaId);
+        if (isSuccess(status)) {
+          Taro.showToast({ title: "删除成功", icon: "success" });
+          getDetail(detail.knowledgeId);
         }
-      }
-    })
-    
-  }
+      },
+    });
+  };
 
   // 获取详情
-  const getDetail = async (knowledgeId: number)=> {
-    const response = await getMyKnowledgeDetail(knowledgeId)
-    if(isSuccess(response.status) && response.data){
-      setDetail(response.data)
-      setChecked(response.data.enableExactAnswer)
+  const getDetail = async (knowledgeId: number) => {
+    const response =  !isEnt ? await getMyKnowledgeDetail(knowledgeId) : await getEntKnowledgeDetail(knowledgeId, entId);
+    if (isSuccess(response.status) && response.data) {
+      setDetail(response.data);
+      setChecked(response.data.enableExactAnswer);
     }
-  }
+  };
 
-  // 开启/关闭 精准问答模式 
+  // 开启/关闭 精准问答模式
   const handleEnableExactAnswer = async () => {
-    if(!detail?.knowledgeId){
-      return
+    if (!detail?.knowledgeId) {
+      return;
     }
-    const {status} = await updateExactAnswer(detail.knowledgeId, !checked)
-    if(isSuccess(status)){
-      setChecked(!checked)
+    const { status } = await updateExactAnswer(detail.knowledgeId, !checked);
+    if (isSuccess(status)) {
+      setChecked(!checked);
     }
-  }
-  
+  };
 
-  useEffect(()=> {
-    knowledgeId && getDetail(parseInt(knowledgeId))
-  }, [knowledgeId])
+  const handleDeleteKnowledge = async () => {
+    if (!detail) {
+      return;
+    }
+    showModal({
+      content: "确定删除该问答项吗?",
+      onConfirm: async () => {
+        const { status } = await deleteKnowledge(detail.knowledgeId);
+        if (isSuccess(status)) {
+          await Taro.showToast({ title: "删除成功", icon: "success" });
+          setTimeout(() => {
+            Taro.navigateBack();
+          }, 2000);
+        }
+      },
+    });
+  };
+
+
+
+  useDidShow(() => {
+    knowledgeId && getDetail(parseInt(knowledgeId));
+  });
+
+  const createCardOptions = (item: TQAListItem) => {
+    if(isEnt){
+      return []
+    }
+    return [
+      <View onClick={() => handleDeleteItem(item.qaId)}>
+        删除
+      </View>,
+      <View onClick={() => handleEdit(item.qaId)}>编辑</View>,
+    ]
+  }
 
   return (
     <PageCustom>
@@ -85,24 +129,34 @@ export default function Index() {
         <View className="p-16">
           <View className="mb-16">
             <FigureListItem
-              figure={()=> {
-                return <>{detail?.icon && <Image src={detail?.icon} mode="widthFix" style={{width: '36px', height: '36px'}}></Image>}</>
+              figure={() => {
+                return (
+                  <>
+                    {detail?.icon && (
+                      <Image
+                        src={detail?.icon}
+                        mode="widthFix"
+                        style={{ width: "36px", height: "36px" }}
+                      ></Image>
+                    )}
+                  </>
+                );
               }}
               rightRenderer={() => (
-                <View>
+                !isEnt ? <View>
                   <IconEye />
-                </View>
+                </View> : <></>
               )}
             >
-              <View className="flex flex-col flex-1 gap-2 w-full">
-                <View className="text-14 leading-22 truncate">{detail?.title}</View>
-                <View className="text-12 leading-20 text-gray-45">
-                  {detail?.createTime} | {detail?.fileSizeStr}
-                </View>
+              <View className="text-14 leading-22 truncate">
+                {detail?.title}
+              </View>
+              <View className="text-12 leading-20 text-gray-45">
+                {detail?.createTime} | {detail?.fileSizeStr}
               </View>
             </FigureListItem>
           </View>
-          <View className="flex rounded-12 p-16 gap-16 bg-white">
+          {!isEnt && <View className="flex rounded-12 p-16 gap-16 bg-white">
             <View className="flex-1">
               <View className="text-14 font-medium leading-22 text-black pb-2">
                 精准QA模式
@@ -118,49 +172,70 @@ export default function Index() {
                 onChange={handleEnableExactAnswer}
               ></WemetaSwitch>
             </View>
-          </View>
+          </View>}
         </View>
-            
-        
+
         <View className="pb-100">
           <View className="rounded-container-header">
             <View className="text-14 font-medium leading-22 px-16 pb-16">
-              问答列表共<Text className="text-primary">{detail?.qaList.length}</Text>条
+              问答列表共
+              <Text className="text-primary">{detail?.qaList.length}</Text>条
             </View>
           </View>
-          <View className={style.scrollContainer}>
-            {detail?.qaList.map((item)=> {
-              return <View className="flex flex-col gap-16 px-16 mb-16">
-              <CardEditable buttons={[<View onClick={()=> handleDeleteItem(item.qaId)}>删除</View>, <View onClick={()=> handleEdit(item.qaId)}>编辑</View>]}>
-                <View className="flex items-start mb-8 gap-8">
-                  <View className="flex-center h-28"><IconQ/></View>
-                  <View className="flex-1 font-medium text-14 leading-28">{item.questions[0]}</View>
-                </View>
-
-                <View className="flex items-start gap-8">
-                  <View className="flex-center  h-28"><IconA/></View>
-                  <View className="flex-1 text-12 leading-20 text-gray-45 truncate">
-                    <View className="truncate">{item.answer}</View>
+          <View className={isEnt ? style.scrollContainerHigher : style.scrollContainer}>
+            {detail?.qaList.map((item) => {
+              return (
+                <View className="flex flex-col gap-16 px-16 mb-16">
+                  <CardEditable
+                    buttons={createCardOptions(item)}
+                  >
+                    <View className="flex items-start mb-8 gap-8">
+                      <View className="flex-center h-28">
+                        <IconQ />
+                      </View>
+                      <View className="flex-1 font-medium text-14 leading-28">
+                        {item.questions[0]}
+                      </View>
+                    </View>
 
-                    {(!!item.links.length) && <View className="pb-12">
-                      {item.links.map((link)=> {
-                        return <View>查看链接 <Text>{link}</Text></View>
-                      })}
+                    <View className="flex items-start gap-8">
+                      <View className="flex-center  h-28">
+                        <IconA />
                       </View>
-                    }
-                    {(!!item.pics.length) && <View className="pb-12">
-                      {item.pics.map((pic)=> {
-                        return <View>
-                          <Image src={pic} mode="widthFix" className="w-full"></Image>
-                        </View>
-                      })}
+                      <View className="flex-1 text-12 leading-20 text-gray-45 truncate">
+                        <View className="truncate">{item.answer}</View>
+
+                        {!!item.links.length && (
+                          <View className="pb-12">
+                            {item.links.map((link) => {
+                              return (
+                                <View>
+                                  查看链接 <Text>{link}</Text>
+                                </View>
+                              );
+                            })}
+                          </View>
+                        )}
+                        {!!item.pics.length && (
+                          <View className="pb-12">
+                            {item.pics.map((pic) => {
+                              return (
+                                <View>
+                                  <Image
+                                    src={pic}
+                                    mode="widthFix"
+                                    className="w-full"
+                                  ></Image>
+                                </View>
+                              );
+                            })}
+                          </View>
+                        )}
                       </View>
-                    }
-                  </View>
+                    </View>
+                  </CardEditable>
                 </View>
-
-              </CardEditable>
-            </View>
+              );
             })}
           </View>
           {/* <View className="flex flex-col gap-16 px-16">
@@ -178,11 +253,17 @@ export default function Index() {
             </CardEditable>
           </View> */}
         </View>
-        <BottomBar>
-          <View className="button-rounded button-plain button-warn w-88">删除</View>
-          <View className="button-rounded button-primary flex-1">共享到企业知识</View>
-        </BottomBar>
-        
+        {!isEnt && <BottomBar>
+          <View
+            className="button-rounded button-plain button-warn w-88"
+            onClick={handleDeleteKnowledge}
+          >
+            删除
+          </View>
+          <View className="button-rounded button-primary flex-1">
+            共享到企业知识
+          </View>
+        </BottomBar>}
       </View>
     </PageCustom>
   );

+ 35 - 13
src/pages/knowledge/components/CompanyTab/index.tsx

@@ -4,38 +4,42 @@ import IconFilterFeeds from "@/components/icon/IconFilterFeeds";
 import IconFilterBatch from "@/components/icon/IconFilterBatch";
 import IconFilterList from "@/components/icon/IconFilterList";
 
-import IconFIleTxt from "@/components/icon/IconFIleTxt";
-import IconFIlePDF from "@/components/icon/IconFIlePDF";
-import IconFIleXLSX from "@/components/icon/IconFIleXLSX";
 
-import FigureList from "@/components/list/figure-list";
-import FigureListItem from "@/components/list/figure-list-item";
 
 import Popup from "@/components/popup/popup";
 import WemetaSwitch from "@/components/wemeta-switch";
 import { useEffect, useState } from "react";
 
-import ViewStyleChat from '../view-style/ViewStyleChat'
-import ViewStyleList from '../view-style/ViewStyleList'
+import ViewStyleChatEnt from '../view-style/ViewStyleChatEnt'
+import ViewStyleListEnt from '../view-style/ViewStyleListEnt'
 
 import  PickerSingleColumn from "@/components/Picker/PickerSingleColumn";
 import IconArrowDownRounded from '@/components/icon/IconArrowDownRounded';
+import { useAgentStore } from "@/store/agentStore";
+import { useKnowledgeEntStore } from "@/store/knowledgeEnt";
 
 type TListStyle = "chat" | "list";
 
 const Index = () => {
-  
+  const agents = useAgentStore(state => state.agents)
+  const ents = useAgentStore(state => state.ents)
   const [checked, setChecked] = useState(false);
   const [showPopup, setShowPopup] = useState(false);
   const [listStyle, setListStyle] = useState<TListStyle>("chat");
+  const {ent, setEnt, total, listTotalCount } = useKnowledgeEntStore()
+  
 
   const handleListStyleChange = (listStyle: TListStyle) => {
     setListStyle(listStyle);
   };
 
+  // 如果没有当前企业,则默认第一个
+  if(!ent){
+    setEnt(ents[0])
+  }
 
   // 当前选中的值
-  const options = ['北京茗视光眼科医院管理有限公司', '杭州小蓝本有限公司']
+  const options = ents.map( item => item.entName)
   // 是否显示选择器
   const [showPicker, setShowPicker] = useState(false)
 
@@ -44,9 +48,24 @@ const Index = () => {
 
   const handleChange = (value: string) => {
     setSelected(value)
+    const ent = ents.find(item=> item.entName === value)
+    if(ent){
+      setEnt(ent)
+    }
   }
 
   
+  const renderContent = () => {
+
+    if(!ent?.entId){
+      return <></>
+    }
+    if(listStyle === 'chat'){ 
+      return <ViewStyleChatEnt entId={ent.entId}/>
+    }
+    return <ViewStyleListEnt entId={ent.entId} />
+  }
+
 
   useEffect(() => {
     console.log("hellow");
@@ -54,7 +73,7 @@ const Index = () => {
 
   return (
     <>
-      <View className="pt-12">
+      <View className="pt-12 h-full">
         <View className="rounded-container-header"></View>
         <View className="px-16 pb-20">
           <View className="pb-8">
@@ -70,7 +89,7 @@ const Index = () => {
           <View className="flex items-center">
             
             <View className="flex-1 text-12 leading-20 text-gray-45">
-              共102个文件
+              共 {listStyle === 'chat' ? total : listTotalCount} 个文件
             </View>
             <View className="flex items-center">
               {listStyle === "chat" ? (
@@ -90,6 +109,9 @@ const Index = () => {
                   ></RoundedLabel>
                   <RoundedLabel
                     text="列表"
+                    onClick={() => {
+                      setShowPopup(true)
+                    }}
                     icon={IconFilterList}
                   ></RoundedLabel>
                 </>
@@ -97,8 +119,8 @@ const Index = () => {
             </View>
           </View>
         </View>
-        <View className="px-16">
-          {listStyle === "chat" ? <ViewStyleChat/> : <ViewStyleList />}
+        <View className="px-16 h-full">
+          {renderContent()}
         </View>
       </View>
       

+ 5 - 2
src/pages/knowledge/components/personal-tab/index.tsx

@@ -29,7 +29,7 @@ const Index = () => {
   const [showAiAsistant, setShowAiAsistant] = useState(false);
   const [listStyle, setListStyle] = useState<TListStyle>("chat");
 
-  const { loadMore } = useKnowledgeStore()
+  const { total } = useKnowledgeStore()
 
   const handleListStyleChange = (listStyle: TListStyle) => {
     setListStyle(listStyle);
@@ -64,7 +64,7 @@ const Index = () => {
         <View className="px-16 pb-20">
           <View className="flex items-center">
             <View className="flex-1 text-12 leading-20 text-gray-45">
-              共102个文件
+              共{total}个文件
             </View>
             <View className="flex items-center">
               {listStyle === "chat" ? (
@@ -84,6 +84,9 @@ const Index = () => {
                   ></RoundedLabel>
                   <RoundedLabel
                     text="列表"
+                    onClick={() => {
+                      setShowPopup(true)
+                    }}
                     icon={IconFilterList}
                   ></RoundedLabel>
                 </>

+ 3 - 4
src/pages/knowledge/components/view-style/ViewStyleChat.tsx

@@ -13,7 +13,6 @@ import FigureListItem from "@/components/list/figure-list-item";
 import { useEffect, useRef, useState } from "react";
 import Taro, { useDidShow } from "@tarojs/taro";
 
-import type { TKnowledgeStreamResponseData } from "@/types/knowledge";
 import { useUserStore } from "@/store/userStore";
 import { useKnowledgeStore } from "@/store/knowledge";
 
@@ -30,9 +29,9 @@ const ViewStyleChat = () => {
     loadMore();
   };
 
-  useDidShow(() => {
-    loadMore();
-  });
+  useEffect(() => {
+    loadMore()
+  }, []);
 
   return (
     <ScrollView

File diff suppressed because it is too large
+ 22 - 0
src/pages/knowledge/components/view-style/ViewStyleChatEnt.tsx


+ 24 - 49
src/pages/knowledge/components/view-style/ViewStyleList.tsx

@@ -1,66 +1,40 @@
-import { ScrollView, View } from "@tarojs/components";
-import MessageRobotRich from "@/components/chat-message/MessageRobotRich";
-import MessageRich from "@/components/chat-message/MessageRich";
-import { WelcomeCard, AddSuccessfulTips } from "../asistant-message";
-
-import IconFIleTxt from "@/components/icon/IconFIleTxt";
-import IconFIlePDF from "@/components/icon/IconFIlePDF";
-import IconFIleXLSX from "@/components/icon/IconFIleXLSX";
+import { ScrollView, View, Image } from "@tarojs/components";
 
 import FigureList from "@/components/list/figure-list";
 import FigureListItem from "@/components/list/figure-list-item";
 import { useDidShow } from "@tarojs/taro";
-import { useEffect, useState } from "react";
+import { useEffect } from "react";
 
 import RotateLoading from "@/components/rotate-loading";
 import Taro from "@tarojs/taro";
 
-import { getKnowledgeList } from "@/service/knowledge";
-import { isSuccess } from "@/utils";
-import type { TKnowledgeListItem, TQAListItem } from "@/types/knowledge";
+import { useKnowledgeStore } from "@/store/knowledge";
+import type { TKnowledgeItem } from "@/types/knowledge";
 
 const Index = () => {
+  const { listItems, listScrollTop, loadMoreList, initLoadList } = useKnowledgeStore();
 
-  const [scrollTop, setScrollTop] = useState(9999)
-  const [list, setList] = useState<TKnowledgeListItem[]>([])
-  
-  let startId:string|undefined = undefined
-  let loading = false
-  const loadMore = async () => {
-    if(loading){
-      return
-    }
-    loading = true
-    const response = await getKnowledgeList({
-      startId: startId,
-      pageSize: 10
-    })
-    
-    const result = isSuccess(response.status)
-    if(result){
-      const newData = [...response.data.data, ...list]
-      setList(newData)
-      startId = response.data.nextId
-    }
-    loading = false
-  }
   const onScrollToUpper = async () => {
     console.log('toUpper')
-    loadMore()
-    
+    loadMoreList()
   }
 
-  useDidShow(()=> {
-    console.log(1111)
-    loadMore()
-  })
+  useEffect(()=> {
+    initLoadList()
+  }, [])
 
-  const handleEdit = ()=> {
+  const handleEdit = (item: TKnowledgeItem)=> {
+    if(item.parseStatus !== 'parsed'){
+      return ;
+    }
     Taro.navigateTo({
-      url: '/pages/knowledge-item/index'
+      url: `/pages/knowledge-item/index?knowledgeId=${item.knowledgeId}`
     })
   }
-  const rightRenderer = () => {
+  const rightRenderer = (item: TKnowledgeItem) => {
+    if(item.parseStatus !== 'parsed'){
+      return <></>
+    }
     return (
       <View className="flex items-center gap-4">
         <RotateLoading />
@@ -73,19 +47,20 @@ const Index = () => {
     <ScrollView
       scrollY
       onScrollToUpper={onScrollToUpper}
-      scrollTop={scrollTop}
+      scrollTop={listScrollTop}
       style={{
         flex: 1,
         height: "100%", // 高度自适应
       }}
     >
       <FigureList>
-      {list.map(item => {
+      {listItems.map(item => {
         return <FigureListItem
-            figure={IconFIleTxt}
+            figure={()=> <Image src={item.icon} mode="widthFix" style={{width: '36px', height: '36px'}}></Image>}
             underline
-            arrow
-            onClick={handleEdit}
+            arrow={item.parseStatus === 'parsed'}
+            onClick={()=> handleEdit(item)}
+            rightRenderer={()=> rightRenderer(item)}
           >
             <View className="flex flex-col flex-1 gap-2 w-full">
               <View className="text-14 leading-22">{item.title}</View>

+ 104 - 0
src/pages/knowledge/components/view-style/ViewStyleListEnt.tsx

@@ -0,0 +1,104 @@
+import { ScrollView, View, Image } from "@tarojs/components";
+
+import FigureList from "@/components/list/figure-list";
+import FigureListItem from "@/components/list/figure-list-item";
+import { useDidShow } from "@tarojs/taro";
+import { useEffect } from "react";
+
+import RotateLoading from "@/components/rotate-loading";
+import Taro from "@tarojs/taro";
+
+import { useKnowledgeEntStore } from "@/store/knowledgeEnt";
+import type { TKnowledgeItem } from "@/types/knowledge";
+export interface Iprops {
+  entId: string|number
+}
+const Index = ({entId}:Iprops) => {
+  const { listItems, listScrollTop, loadMoreList, initLoadList } = useKnowledgeEntStore();
+
+  const onScrollToUpper = async () => {
+    console.log('toUpper')
+    loadMoreList()
+  }
+
+  useEffect(()=> {
+    initLoadList()
+  }, [])
+
+  const handleEdit = (item: TKnowledgeItem)=> {
+    if(item.parseStatus !== 'parsed'){
+      return ;
+    }
+    Taro.navigateTo({
+      url: `/pages/knowledge-item/index?knowledgeId=${item.knowledgeId}&entId=${entId}`
+    })
+  }
+  const rightRenderer = (item: TKnowledgeItem) => {
+    if(item.parseStatus !== 'parsed'){
+      return <></>
+    }
+    return (
+      <View className="flex items-center gap-4">
+        <RotateLoading />
+        <View className="text-primary text-12">解析中</View>
+      </View>
+    );
+  };
+
+  return (
+    <ScrollView
+      scrollY
+      onScrollToUpper={onScrollToUpper}
+      scrollTop={listScrollTop}
+      style={{
+        flex: 1,
+        height: "100%", // 高度自适应
+      }}
+    >
+      <FigureList>
+      {listItems.map(item => {
+        return <FigureListItem
+            figure={()=> <Image src={item.icon} mode="widthFix" style={{width: '36px', height: '36px'}}></Image>}
+            underline
+            arrow={item.parseStatus === 'parsed'}
+            onClick={()=> handleEdit(item)}
+            rightRenderer={()=> rightRenderer(item)}
+          >
+            <View className="flex flex-col flex-1 gap-2 w-full">
+              <View className="text-14 leading-22">{item.title}</View>
+              <View className="text-12 leading-20 text-gray-45">
+              {item.createTime} | {item.fileSize}
+              </View>
+            </View>
+          </FigureListItem>
+      })}
+        {/* <FigureListItem
+          figure={IconFIleTxt}
+          underline
+          arrow
+          onClick={handleEdit}
+        >
+          <View className="flex flex-col flex-1 gap-2 w-full">
+            <View className="text-14 leading-22">飞秒小知识</View>
+            <View className="text-12 leading-20 text-gray-45">
+              03-24 12:20 | 822.KB
+            </View>
+          </View>
+        </FigureListItem>
+        <FigureListItem
+          figure={IconFIlePDF}
+          rightRenderer={rightRenderer}
+        >
+          <View className="flex flex-col flex-1 gap-2 w-full">
+            <View className="text-14 leading-22">飞秒小知识.pdf</View>
+            <View className="text-12 leading-20 text-gray-45">
+              03-24 12:20 | 822.KB
+            </View>
+          </View>
+        </FigureListItem> */}
+      </FigureList>
+    </ScrollView>
+  );
+};
+
+export default Index;

+ 20 - 15
src/pages/knowledge/index.tsx

@@ -8,17 +8,31 @@ import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import WemetaTabs from "@/components/wemeta-tabs/index";
 import PersonalTab from './components/personal-tab'
-import CompanyTab from './components/CompanyTab';
+import CompanyTab from './components/CompanyTab'
 import style from "./index.module.less";
-import Taro from "@tarojs/taro";
-
-
+import Taro, { useDidShow } from "@tarojs/taro";
+import { useAgentStore } from "@/store/agentStore";
 
 
 export default function Index() {
   
+const agents = useAgentStore(state => state.agents)
+const entAgents = agents.filter((item)=> item.isEnt)
 
-  
+const renderCompanyTab = ()=> {
+  if(entAgents.length){
+    return <CompanyTab/>
+  }
+  return <View className="flex-center pt-40">
+  <View className="text-center text-14 leading-28 text-gray-45 mb-44 w-172">
+    <View className="text-center text-16 leading-24 font-medium text-black">绑定企业,知识自动到位</View>
+    <View>访问公司统一知识内容</View>
+    <View>一键同步到你的智能体</View>
+    <View>提升回复效率与专业度</View>
+    <View className="button-rounded button-primary" onClick={()=> Taro.navigateTo({url: '/pages/contact-us/index'})}>联系我们</View>
+  </View>
+</View>        
+}
 
   const tabList = [
     {
@@ -38,16 +52,7 @@ export default function Index() {
       key: "2",
       label: "企业知识",
       children: <View className={style.tabContent}>
-          <View className="flex-center pt-40">
-            <View className="text-center text-14 leading-28 text-gray-45 mb-44 w-172">
-              <View className="text-center text-16 leading-24 font-medium text-black">绑定企业,知识自动到位</View>
-              <View>访问公司统一知识内容</View>
-              <View>一键同步到你的智能体</View>
-              <View>提升回复效率与专业度</View>
-              <View className="button-rounded button-primary" onClick={()=> Taro.navigateTo({url: '/pages/contact-us/index'})}>联系我们</View>
-            </View>
-          </View>
-          {/* <CompanyTab/> */}
+          {renderCompanyTab()}
       </View>,
     },
   ];

+ 9 - 5
src/service/knowledge.ts

@@ -100,7 +100,7 @@ export const deleteKnowledge = (knowledgeId: number) => {
   return request.delete(`${bluebookAiAgent}api/v1/my/knowledge/${knowledgeId}`,)
 }
 // 删除指定知识库的 QA 项
-export const deleteKnowledgeQa = (knowledgeId: number, qaId: number) => {
+export const deleteKnowledgeQa = (knowledgeId: number, qaId: number|string) => {
   return request.delete(`${bluebookAiAgent}api/v1/my/knowledge/${knowledgeId}/${qaId}`,)
 }
 
@@ -117,7 +117,7 @@ export const updateKnowledgeQa = (knowledgeId: number|string, qaId: number|strin
 
 // 企业知识库--列表
 export const getEntKnowledgeList = (data: {
-  entId: string;
+  entId: string|number;
   startId?: string;
   pageSize: number;
 }) => {
@@ -127,14 +127,18 @@ export const getEntKnowledgeList = (data: {
   );
 };
 // 获取指定知识库项的详情信息
-export const getEntKnowledgeDetail = (knowledgeId: string) => {
-  return request.get(`${bluebookAiAgent}api/v1/ent/knowledge/${knowledgeId}`)
+export const getEntKnowledgeDetail = (knowledgeId: string|number, entId: string|number) => {
+  return request.get(`${bluebookAiAgent}api/v1/ent/knowledge/${knowledgeId}?entId=${entId}`)
 }
 
 // 企业知识库--信息流
-export const getEntKnowledgeStream = (data: {entId: string, startId?: string, pageSize:number} ) => {
+export const getEntKnowledgeStream = (data: {entId: string|number, startId?: string, pageSize:number} ) => {
   return request.get<TKnowLedgeStreamResponse>(`${bluebookAiAgent}api/v1/ent/knowledge/stream`, {params: data})
 }
 
 
+export const getEntKnowledgeQa = (knowledgeId: number|string, qaId: number|string) => {
+  return request.get<TQAListItem>(`${bluebookAiAgent}api/v1/ent/knowledge/${knowledgeId}/${qaId}`)
+}
+
 

+ 6 - 1
src/store/agentStore.ts

@@ -22,6 +22,7 @@ export interface AgentStoreState {
   agent: TAgentDetail | null;
   agentContactCard: TAgentContactCard | null;
   agentCharacter: TEditAgentCharacter | null;
+  ents: {entName: string, entId: string|number}[]
   fetchAgents: () => Promise<TAgent[]>;
   fetchAgent: (agentId: string) => Promise<TAgentDetail | null>;
   createAgent: (data: TAgentDetail) => Promise<TAgentDetail | null>;
@@ -42,12 +43,16 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
   agent: null,
   agentContactCard: null,
   agentCharacter: null,
+  ents: [],
   fetchAgents: async () => {
     const response = await request.get<TAgent[]>(
       `${bluebookAiAgent}api/v1/my/agents`
     );
     if (response && response?.data?.length) {
-      set({ agents: response.data });
+      const ents = response.data.filter(item => item.isEnt).map( item => {
+        return {entName: item.entName ?? '', entId: item.entId}
+      })
+      set({ agents: response.data, ents });
       return response.data;
     }
 

+ 66 - 2
src/store/knowledge.ts

@@ -1,12 +1,12 @@
 import { create } from "zustand";
 
 import { isSuccess } from "@/utils";
-import type { TKnowledgeStreamResponseData } from "@/types/knowledge";
+import type { TKnowledgeStreamResponseData, TKnowledgeItem } from "@/types/knowledge";
 
 import {
   getMyKnowledgeStream as _getMyKnowledgeStream,
+  getKnowledgeList as _getKnowledgeList,
 } from "@/service/knowledge";
-import Taro from "@tarojs/taro";
 
 export interface KnowledgeStoreState {
   scrollTop: number;
@@ -14,7 +14,17 @@ export interface KnowledgeStoreState {
   list: TKnowledgeStreamResponseData[];
   isLoading: boolean;
   startId?: string;
+  // List view specific state
+  listScrollTop: number;
+  listTotalCount: number;
+  listItems: TKnowledgeItem[];
+  listStartId?: string;
+  listLoading: boolean;
   loadMore: (force?: boolean) => Promise<void>;
+  initLoad: () => Promise<void>;
+  // List view specific functions
+  loadMoreList: (force?: boolean) => Promise<void>;
+  initLoadList: () => Promise<void>;
 }
 
 export const useKnowledgeStore = create<KnowledgeStoreState>((set, get) => ({
@@ -23,6 +33,12 @@ export const useKnowledgeStore = create<KnowledgeStoreState>((set, get) => ({
   list: [],
   isLoading: false,
   startId: undefined,
+  // List view specific state
+  listScrollTop: 9999,
+  listTotalCount: 9999,
+  listItems: [],
+  listStartId: undefined,
+  listLoading: false,
   loadMore: async (force) => {
     const { list, total, isLoading, startId } = get();
     
@@ -52,5 +68,53 @@ export const useKnowledgeStore = create<KnowledgeStoreState>((set, get) => ({
       set({ isLoading: false, scrollTop: get().scrollTop + 1 });
     }
   },
+  // 重新初始化加载
+  initLoad: async() => {
+    set({
+      list: [],
+      startId: undefined,
+      total: 9999,
+      isLoading: false,
+    })
+    console.log('initLoad')
+    await get().loadMore()
+  },
+  // 列表视图-加载
+  loadMoreList: async (force) => {
+    const { listItems, listTotalCount, listLoading, listStartId } = get();
+    
+    if (!force && (listItems.length >= listTotalCount || listLoading)) {
+      return;
+    }
+
+    set({ listLoading: true });
+    
+    try {
+      const response = await _getKnowledgeList({
+        startId: listStartId,
+        pageSize: 10,
+      });
 
+      const result = isSuccess(response.status);
+      if (result) {
+        const newData = [...response.data.data, ...listItems];
+        set({
+          listItems: newData,
+          listStartId: response.data.nextId,
+          listTotalCount: response.data.totalCount,
+        });
+      }
+    } finally {
+      set({ listLoading: false, listScrollTop: get().listScrollTop + 1 });
+    }
+  },
+  initLoadList: async() => {
+    set({
+      listItems: [],
+      listStartId: undefined,
+      listTotalCount: 9999,
+      listLoading: false,
+    })
+    await get().loadMoreList()
+  }
 }));

+ 145 - 0
src/store/knowledgeEnt.ts

@@ -0,0 +1,145 @@
+/**
+ * 企业知识库
+ */
+import { create } from "zustand";
+
+import { isSuccess } from "@/utils";
+import type { TKnowledgeStreamResponseData, TKnowledgeItem } from "@/types/knowledge";
+
+import {
+  getEntKnowledgeStream as _getMyKnowledgeStream,
+  getEntKnowledgeList as _getKnowledgeList,
+} from "@/service/knowledge";
+
+type TEnt = {entId: string|number, entName: string}
+
+export interface KnowledgeEntStoreState {
+  scrollTop: number;
+  total: number;
+  list: TKnowledgeStreamResponseData[];
+  isLoading: boolean;
+  startId?: string;
+  ent?: TEnt|null;
+  // List view specific state
+  listScrollTop: number;
+  listTotalCount: number;
+  listItems: TKnowledgeItem[];
+  listStartId?: string;
+  listLoading: boolean;
+  loadMore: (force?: boolean) => Promise<void>;
+  initLoad: () => Promise<void>;
+  // List view specific functions
+  loadMoreList: (force?: boolean) => Promise<void>;
+  initLoadList: () => Promise<void>;
+  
+  setEnt: (ent: TEnt) => void
+}
+
+// todo: 可用工厂函数方式与 useKnowledgeStore 合并成一个 store
+export const useKnowledgeEntStore = create<KnowledgeEntStoreState>((set, get) => ({
+  scrollTop: 9999,
+  total: 10000,
+  list: [],
+  isLoading: false,
+  startId: undefined,
+  ent: null,
+  // List view specific state
+  listScrollTop: 9999,
+  listTotalCount: 9999,
+  listItems: [],
+  listStartId: undefined,
+  listLoading: false,
+  loadMore: async (force) => {
+    const { list, total, isLoading, startId, ent } = get();
+    
+    if (!force && (list.length >= total || isLoading)) {
+      return;
+    }
+    if(!ent?.entId){
+      return
+    }
+    set({ isLoading: true });
+    
+    try {
+      const response = await _getMyKnowledgeStream({
+        startId,
+        entId: ent?.entId,
+        pageSize: 10,
+      });
+
+      const result = isSuccess(response.status);
+      if (result) {
+        // 请求到的数组倒序后排在数组前面
+        const newData = [...response.data.data.reverse(), ...list];
+        set({
+          list: newData,
+          startId: response.data.nextId,
+          total: response.data.totalCount ?? 0,
+        });
+      }
+    } finally {
+      set({ isLoading: false, scrollTop: get().scrollTop + 1 });
+    }
+  },
+  // 重新初始化加载
+  initLoad: async() => {
+    set({
+      list: [],
+      startId: undefined,
+      total: 9999,
+      isLoading: false,
+    })
+    console.log('initLoad')
+    await get().loadMore()
+  },
+  // 列表视图-加载
+  loadMoreList: async (force) => {
+    const { listItems, listTotalCount, listLoading, listStartId, ent } = get();
+    
+    if (!force && (listItems.length >= listTotalCount || listLoading)) {
+      return;
+    }
+
+    if(!ent?.entId){
+      return
+    }
+
+    set({ listLoading: true });
+    
+    try {
+      const response = await _getKnowledgeList({
+        startId: listStartId,
+        entId: ent?.entId,
+        pageSize: 10,
+      });
+
+      const result = isSuccess(response.status);
+      if (result) {
+        const newData = [...response.data.data, ...listItems];
+        set({
+          listItems: newData,
+          listStartId: response.data.nextId,
+          listTotalCount: response.data.totalCount,
+        });
+      }
+    } finally {
+      set({ listLoading: false, listScrollTop: get().listScrollTop + 1 });
+    }
+  },
+  initLoadList: async() => {
+    set({
+      listItems: [],
+      listStartId: undefined,
+      listTotalCount: 9999,
+      listLoading: false,
+    })
+    await get().loadMoreList()
+  },
+  setEnt: (ent)=> {
+    set(
+      {
+        ent: ent
+      }
+    )
+  }
+}));

+ 1 - 0
src/types/agent.ts

@@ -8,6 +8,7 @@ export type TAgent = {
   entName: string|null
   isDefault: boolean
   isEnt: boolean
+  entId: number|string
   isNewEnt: boolean
   mobile: string
   name: string

+ 0 - 1
src/xiaolanbenlib/hooks/data/useAuth.tsx

@@ -132,7 +132,6 @@ export function useIsLogin() {
     if (newState !== isLogin) {
       setIsLogin(newState)
     }
-    console.log(newState,222)
     if(!newState){
       
       Taro.navigateTo({url: '/pages/login/index'})

+ 1 - 1
src/xiaolanbenlib/module/axios.js

@@ -22,7 +22,7 @@ export const getSimpleHeader = () => {
 
 export const getHeaders = async (config) => {
   const userInfo = await getUserInfo()
-  console.log('userInfo', userInfo)
+  // console.log('userInfo', userInfo)
   config.params = config.params || {}
   config.headers = config.headers || {}
   config.headers['X-Enniu-End'] = 'mp'

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