Explorar o código

feat: 微官网组件列表添加

王晓东 hai 1 mes
pai
achega
921ba2d12a

+ 1 - 1
src/components/component-list/components/new-comp-button/index.tsx

@@ -5,6 +5,6 @@ interface Props {
 }
 export default ({index}:Props) => {
   return <View className={`flex items-center justify-center gap-8 py-12 rounded-20 ${style.container}`}>
-    <Text className={`iconfont icon-icon_20_add text-16 ${style.textColor}`}></Text><Text className={`text-14 font-medium leading-28 ${style.textColor}`}>添加内容</Text>
+    <Text className={`iconfont icon-icon_20_add text-16 ${style.textColor}`}></Text><Text className={`text-14 font-medium leading-28 ${style.textColor}`}>添加组件{index}</Text>
   </View>
 }

+ 48 - 123
src/components/component-list/index.tsx

@@ -28,9 +28,11 @@ import IconMail from '@/components/icon/icon-email'
 import IconBag from '@/components/icon/icon-bag'
 import IconGroup from '@/components/icon/icon-group'
 import IconBuilding from '@/components/icon/icon-building'
+import { TComponentItem } from "@/types/agent";
+import { editAgentWebsite } from "@/service/agent";
 
 interface Props {
-  components: TEntityComponent[];
+  components: TComponentItem[];
   editMode?: boolean;
 }
 export default ({ components, editMode = false }: Props) => {
@@ -38,9 +40,8 @@ export default ({ components, editMode = false }: Props) => {
     saveComponent,
     delComponent,
     setCurrentComponent,
-    swapTwoComponent,
-    resortComponent,
     setInsertIndex,
+    swapTwoComponent,
   } = useComponentStore();
 
   const [show, setShow] = useState(true);
@@ -50,7 +51,7 @@ export default ({ components, editMode = false }: Props) => {
     useState<TSocialMediaItem | null>(null);
   const [currentLink, setCurrentLink] = useState("");
 
-  const loading = useComponentStore((state) => state.loading);
+  
 
   const showMediaLink = (mediaItem: TSocialMediaItem, link: string, c: TEntityComponent) => {
     console.log(c.type,  SocialMediaType.shiping.value)
@@ -66,7 +67,8 @@ export default ({ components, editMode = false }: Props) => {
     setShow(true);
   };
   
-  const handleDelete = (c: IEntityDocument) => {
+  const handleDelete = (c: TComponentItem) => {
+    
     delComponent(c);
   };
   const handleNavigate = (c: TEntityComponent, url: string) => {
@@ -85,9 +87,7 @@ export default ({ components, editMode = false }: Props) => {
     if(!value.address.length){
       return
     }
-    if(loading){
-      return;
-    }
+    
     const c = {
       data: {
         address: value.address, 
@@ -107,49 +107,45 @@ export default ({ components, editMode = false }: Props) => {
   };
 
   const handleChooseAddress = async (value, c:TEntityComponent) => {
-    setInsertIndex(-1);
-    setCurrentComponent(c);
-    setMapVisible(true)
+    // setInsertIndex(-1);
+    // setCurrentComponent(c);
+    // setMapVisible(true)
 
-    const option = {
-      address:  value.address,
-      latitude: value.latitude,
-      longitude: value.longitude,
-      success(result:Taro.chooseLocation.SuccessCallbackResult) {
-          console.log(result)
-          value = {
-            address: result.address, 
-            name: result.name,
-            latitude: result.latitude,
-            longitude: result.longitude
-          }
-          saveAddress(value, c)
-      }
-    }
-    Taro.chooseLocation(option)
+    // const option = {
+    //   address:  value.address,
+    //   latitude: value.latitude,
+    //   longitude: value.longitude,
+    //   success(result:Taro.chooseLocation.SuccessCallbackResult) {
+    //       console.log(result)
+    //       value = {
+    //         address: result.address, 
+    //         name: result.name,
+    //         latitude: result.latitude,
+    //         longitude: result.longitude
+    //       }
+    //       saveAddress(value, c)
+    //   }
+    // }
+    // Taro.chooseLocation(option)
 
   };
 
-  const handleSort = async (c: TEntityComponent, direction: number) => {
-    if (loading) {
-      return;
-    }
+  const handleSort = async (c: TComponentItem, direction: number) => {
+    console.log(c, direction)
     const res = await swapTwoComponent(c, direction);
-    if (res) {
-      resortComponent();
-    }
+    
   };
 
   const handleSwitchChanged = (c: TEntityComponent, checked: boolean) => {
-    saveComponent({
-      ...c,
-      enabled: checked,
-    });
+    // saveComponent({
+    //   ...c,
+    //   enabled: checked,
+    // });
   };
   const changeStyle = (c: TEntityComponent) => {
-    saveComponent({
-      ...c,
-    });
+    // saveComponent({
+    //   ...c,
+    // });
   };
 
   const handleCreateNew = (index: number) => {
@@ -160,6 +156,7 @@ export default ({ components, editMode = false }: Props) => {
     });
   };
 
+  // 添加组件
   const renderNewCompButton = (index: number) => {
     return (
       <View onClick={() => handleCreateNew(index)}>
@@ -167,13 +164,14 @@ export default ({ components, editMode = false }: Props) => {
       </View>
     );
   };
+  // 渲染组件列表
   const renderComponents = () => {
     if (!components) {
       return <></>;
     }
 
     let componentsWithJSX = components
-      .map((c: TEntityComponent, index: number) => {
+      .map((c: TComponentItem, index: number) => {
         if (!c.data) {
           return undefined;
         }
@@ -215,7 +213,7 @@ export default ({ components, editMode = false }: Props) => {
         }
         
         // 联系人
-        if(c.type === "contactList"){
+        if(c.type === "bluebook"){
           return {
             component: c,
             renderer: (
@@ -288,7 +286,7 @@ export default ({ components, editMode = false }: Props) => {
             ),
           };
         }
-        if (c.type === "textarea") {
+        if (c.type === "text") {
           return {
             component: c,
             renderer: (
@@ -329,82 +327,7 @@ export default ({ components, editMode = false }: Props) => {
           };
         }
 
-        if (c.type === "company") {
-          return {
-            component: c,
-            renderer: (
-              <>
-                <WidgetCard
-                  index={index}
-                  enabled={c.enabled}
-                  onSwitchChanged={(checked) => handleSwitchChanged(c, checked)}
-                  components={components}
-                  editMode={editMode}
-                  disableChangeStyle
-                  onDelete={() => handleDelete(c)}
-                  onClick={() =>
-                    editMode &&
-                    handleNavigate(
-                      c,
-                      `/pages/editor-pages/editor-company/index`
-                    )
-                  }
-                  onMove={(direction) => handleSort(c, direction)}
-                >
-                  <View className="flex flex-col gap-24 px-16">
-                    <WidgetTitleRow title="公司简介:">
-                      <Text>{c.data?.company}</Text>
-                    </WidgetTitleRow>
-                    <WidgetTitleRow title="业务介绍:">
-                      <Text>{c.data?.business}</Text>
-                    </WidgetTitleRow>
-                  </View>
-                </WidgetCard>
-              </>
-            ),
-          };
-        }
-
-        if (c.type === "businessCard") {
-          return {
-            component: c,
-            renderer: (
-              <>
-                <WidgetCard
-                  index={index}
-                  enabled={c.enabled}
-                  onSwitchChanged={(checked) => handleSwitchChanged(c, checked)}
-                  components={components}
-                  editMode={editMode}
-                  disableChangeStyle
-                  onDelete={() => handleDelete(c)}
-                  onMove={(direction) => handleSort(c, direction)}
-                >
-                  <View
-                    className="flex flex-col gap-16"
-                    onClick={() =>
-                      editMode &&
-                      handleNavigate(
-                        c,
-                        `/pages/editor-pages/editor-business-card/index`
-                      )
-                    }
-                  >
-                    <WidgetTypeRow type={IconBag()} editMode={editMode}>
-                      {c.data.job}
-                    </WidgetTypeRow>
-                    <WidgetTypeRow type={IconGroup()} editMode={editMode}>
-                      {c.data.department}
-                    </WidgetTypeRow>
-                    <WidgetTypeRow type={IconBuilding()} editMode={editMode}>
-                      {c.data.company}
-                    </WidgetTypeRow>
-                  </View>
-                </WidgetCard>
-              </>
-            ),
-          };
-        }
+        
 
         if (c.type === 'link') {
           return {
@@ -502,7 +425,7 @@ export default ({ components, editMode = false }: Props) => {
           };
         }
 
-        if (c.type === "images") {
+        if (c.type === "media") {
           return {
             component: c,
             renderer: (
@@ -561,11 +484,13 @@ export default ({ components, editMode = false }: Props) => {
         }
       })
       .filter((item) => !!item);
+    
+    // 如果是编辑模式则显示 “添加组件” 按钮
     if (editMode) {
-      const _components: JSX.Element[] = [renderNewCompButton(0)];
+      const _components: JSX.Element[] = [renderNewCompButton(-1)];
       for (let i = 0; i < componentsWithJSX.length; i++) {
         _components.push(componentsWithJSX[i].renderer);
-        const index = componentsWithJSX[i].component.index ?? 0;
+        const index = componentsWithJSX[i].component.data.index ?? 0;
         _components.push(renderNewCompButton(index));
       }
       return _components;

+ 1 - 1
src/components/icon/icon-minus/index.tsx

@@ -1,5 +1,5 @@
 import { Image } from '@tarojs/components'
-import Icon from '@/images/svgs/icon-change.svg'
+import Icon from '@/images/svgs/icon-minus.svg'
 export default () => {
   return (
     <Image src={Icon} mode="widthFix" style={{width: '16px', height: '16px'}}></Image>

+ 27 - 0
src/consts/enum.ts

@@ -75,4 +75,31 @@ export enum EUploadFileBucketName  {
   DOC = 'doc',
   OTHER = 'other',
   AVATAR = 'avatar'
+}
+
+export enum EComponentType {
+  title =  'title',
+  text =  'text',
+  link = 'link',
+  address = 'address',
+  media = 'media',
+  image = 'images',
+  email = 'email',
+  tel = 'tel',
+  bluebook = 'bluebook',
+  wechat = 'wechat',
+  shiping = 'shiping',
+  tiktok = 'tiktok',
+  xiaohongshu = 'xiaohongshu',
+  kwai = 'kwai',
+  bilibili = 'bilibili',
+  qq = 'qq',
+  name = 'name',
+  comp = 'comp',
+  sina = 'sina',
+  green = 'green',
+  shipingVideo = 'shipingVideo',
+  miniProgram = 'miniProgram',
+  storeProduct = 'storeProduct',
+  storeHome = 'storeHome',
 }

+ 22 - 0
src/pages/agent/components/AgentWebsite/index.tsx

@@ -0,0 +1,22 @@
+import { View } from "@tarojs/components";
+import { useState } from "react";
+import CardList from "@/components/list/card-list";
+import CardListItem from "@/components/list/card-list-item";
+
+import IconArrow from "@/components/icon/icon-arrow";
+
+import Taro from "@tarojs/taro";
+import ComponentList from "@/components/component-list";
+import { useComponentStore } from "@/store/componentStore";
+export default function Index() {
+  
+  const components = useComponentStore((state) => state.components);
+
+  return (
+    <View className="flex flex-col gap-12">
+      <ComponentList editMode components={components}></ComponentList>
+    </View>
+  );
+}
+
+

+ 23 - 15
src/pages/agent/index.tsx

@@ -1,23 +1,34 @@
-
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import { View } from "@tarojs/components";
 import PageCustom from "@/components/page-custom/index";
 
 import TabBarButtons from "@/components/wemeta-tabs/TabBarButtons";
-import AgentSetting from './components/AgentSetting/'
+import AgentSetting from "./components/AgentSetting/";
+import AgentWebsite from "./components/AgentWebsite/";
 import { useAgentStore } from "@/store/agentStore";
 import { useEffect, useState } from "react";
 import { useRouter } from "@tarojs/taro";
+import { useComponentStore } from "@/store/componentStore";
 
 export default function Index() {
   const [tabIndex, setTabIndex] = useState("1");
-  const router = useRouter()
-  const agentId = router.params.agentId
-  const {fetchAgent} = useAgentStore()
+  const router = useRouter();
+  const agentId = router.params.agentId;
+  const { fetchAgent } = useAgentStore();
+  const { setComponentList } = useComponentStore();
   const handleTabIndexChange = (index: string) => {
     setTabIndex(index);
   };
 
+  const fetchAgentDetail = async (agentId: string) => {
+    const result = await fetchAgent(agentId);
+    if (result) {
+      const components = result.components ?? []
+      // 过滤掉没有 id 的组件防止有错误数据
+      setComponentList(components.filter(c => !!c.data?.id), agentId);
+    }
+  };
+
   const tabList = [
     {
       key: "1",
@@ -28,10 +39,10 @@ export default function Index() {
       label: "微官网",
     },
   ];
-  
-  useEffect(()=> {
-    agentId && fetchAgent(agentId)
-  }, [agentId])
+
+  useEffect(() => {
+    agentId && fetchAgentDetail(agentId);
+  }, [agentId]);
 
   return (
     <PageCustom>
@@ -44,15 +55,12 @@ export default function Index() {
             onTabIndexChange={handleTabIndexChange}
           ></TabBarButtons>
         </View>
-        <View className={`${tabIndex === '1' ? 'block':'hidden'}`}>
+        <View className={`${tabIndex === "1" ? "block" : "hidden"}`}>
           <AgentSetting></AgentSetting>
         </View>
-        <View className={`${tabIndex === '2' ? 'block':'hidden'}`}>
-          components
+        <View className={`${tabIndex === "2" ? "block" : "hidden"}`}>
+          <AgentWebsite></AgentWebsite>
         </View>
-        
-
-        
       </View>
     </PageCustom>
   );

+ 8 - 7
src/pages/component-library/components/comp-item/compItem.tsx

@@ -2,7 +2,7 @@ import { View, Input } from '@tarojs/components'
 import style from './index.module.less'
 import IconMinus from '@/components/icon/icon-minus';
 import IconPlus from '@/components/icon/icon-plus';
-
+import { EComponentType } from "@/consts/enum";
 export const CompType = {
   title: style.compIconTitle,
   text: style.compIconText,
@@ -31,28 +31,29 @@ export const CompType = {
 
 interface Props {
   children?: React.ReactChild |  React.ReactChild[];
-  type: string;
+  type: EComponentType;
+  typeStyle: string;
   num: number;
-  onChange: (num: number, type: string) => void
+  onChange: (num: number, type: EComponentType, typeStyle: string, ) => void
 }
 
-const Index =  ({children, type, num, onChange,}: Props)=> {
+const Index =  ({children, type, typeStyle, num, onChange,}: Props)=> {
   
   const handlePlus = () =>{
     if(num >= 9){
       return;
     }
-    onChange(num+1, type)
+    onChange(num+1, type, typeStyle)
   }
   const handleMinus = () =>{
     if(num <= 0){
       return;
     }
-    onChange(num-1, type)
+    onChange(num-1, type, typeStyle)
   }
   return(
     <View className={`flex gap-8 ${style.compItem}`}>
-      <View className={type}></View>
+      <View className={typeStyle}></View>
       <View className={style.compText}>{children}</View>
       <View className='flex items-center gap-14 w-70'>
         <View onClick={handleMinus}><IconMinus></IconMinus></View>

+ 98 - 0
src/pages/component-library/components/createComponentData.ts

@@ -0,0 +1,98 @@
+import { EComponentType } from "@/consts/enum";
+export function createComponentData(type: EComponentType): Record<string, any> | null {
+  if(type === EComponentType.title){
+    return {
+      text: '默认标题',
+      layout: 'left'
+    }
+  }
+  if(type === EComponentType.text){
+    return {
+      text: '默认文本内容',
+      layout: 'left'
+    }
+  }
+  if(type === EComponentType.link){
+    return {
+      link: '',
+      layout: 'left',
+      poster: '',
+      linkType: '',
+      title: '默认链接',
+    }
+  }
+  if(type === EComponentType.tel){
+    return {
+      text: '默认电话',
+      layout: 'left'
+    }
+  }
+  if(type === EComponentType.address){
+    return  {
+      address: '默认地址',
+      latitude: 39.916527,
+      longitude:116.397128,
+    }
+  }
+  // 图片/视频
+  if(type === EComponentType.media){
+    return  {
+      media: [],
+      layout: 'mini',
+    }
+  }
+  // 小蓝本
+  if(type === EComponentType.bluebook){
+    return  {
+      values: [],
+      layout: 'mini',
+    }
+  }
+  // 微信公众号
+  // wx.openOfficialAccountProfile 
+  if(type === EComponentType.wechat){
+    return  {
+      value: '',
+      text: '微信公众号',
+      layout: 'left',
+    }
+  }
+
+  // 视频号,与 普通媒体链接共用同个组件
+  // editor-link-social
+  if(type === EComponentType.shiping){
+    return  {
+      layout: 'left',
+      value: '',
+      text: '微信公众号',
+    }
+  }
+  // 小程序
+  // editor-mii-program
+  if(type === EComponentType.miniProgram){
+    return  {
+      value: {
+        name: '',
+        shortLink: '',
+        poster: '',
+      },
+      layout: 'full',
+    }
+  }
+  // 视频号视频
+  // editor-channels
+  if(type === EComponentType.shipingVideo){
+    return  {
+      value: {
+        accountId: '',
+        videoId: '',
+        desc: '',
+        poster: '',
+      },
+    }
+  }
+
+
+
+  return null
+}

+ 93 - 16
src/pages/component-library/index.tsx

@@ -4,31 +4,43 @@ import CompItem, { CompType } from "./components/comp-item/compItem";
 import Taro from "@tarojs/taro";
 import { SocialMediaType } from "@/consts/socialMedia";
 import { useComponentStore } from "@/store/componentStore";
-import { useCurrentCharacter } from "@/store/characterStore";
+import { generateRandomId } from '@/utils/index'
 
 import CardList from "@/components/list/card-list";
 import CardListItem from "@/components/list/card-list-item";
 import { useState } from "react";
+import { EComponentType } from "@/consts/enum";
+import { TComponentItem } from "@/types/agent";
+import { createComponentData } from './components/createComponentData'
+import { useAgentStore } from "@/store/agentStore";
 
+type TWidget = {
+  type: EComponentType,
+  typeStyle: string,
+  num: number,
+  text: string,
+}
 export default () => {
-  // const character = useCurrentCharacter();
+  const {insertComponent} = useComponentStore()
+  const { agent, editAgentWebsite, fetchAgent } = useAgentStore()
   
 
 
-  const [commonWidget, setCommonWidget] = useState([
-    {type: CompType.title, num: 0, text: '章节标题'},
-    {type: CompType.link, num: 0, text: '链接'},
-    {type: CompType.image, num: 0, text: '图片/视频'},
-    {type: CompType.tel, num: 0, text: '电话'},
-    {type: CompType.local, num: 0, text: '地图'},
-    {type: CompType.bluebook, num: 0, text: '小蓝本'},
+  const [commonWidget, setCommonWidget] = useState<TWidget[]>([
+    {type: EComponentType.title , typeStyle: CompType.title, num: 0, text: '章节标题'},
+    {type: EComponentType.text , typeStyle: CompType.link, num: 0, text: '文本内容'},
+    {type: EComponentType.link , typeStyle: CompType.link, num: 0, text: '链接'},
+    {type: EComponentType.media , typeStyle: CompType.image, num: 0, text: '图片/视频'},
+    {type: EComponentType.tel , typeStyle: CompType.tel, num: 0, text: '电话'},
+    {type: EComponentType.address , typeStyle: CompType.local, num: 0, text: '地图'},
+    {type: EComponentType.bluebook , typeStyle: CompType.bluebook, num: 0, text: '小蓝本'},
   ])
   
-  const [wechatWidget, setWechatWidget] = useState([
-    {type: CompType.wechat, num: 0, text: '微信公众号'},
-    {type: CompType.shiping, num: 0, text: '视频号'},
-    {type: CompType.miniProgram, num: 0, text: '小程序'},
-    {type: CompType.shipingVideo, num: 0, text: '视频号视频'},
+  const [wechatWidget, setWechatWidget] = useState<TWidget[]>([
+    {type: EComponentType.wechat , typeStyle: CompType.wechat, num: 0, text: '微信公众号'},
+    {type: EComponentType.shiping , typeStyle: CompType.shiping, num: 0, text: '视频号'},
+    {type: EComponentType.miniProgram , typeStyle: CompType.miniProgram, num: 0, text: '小程序'},
+    {type: EComponentType.shipingVideo , typeStyle: CompType.shipingVideo, num: 0, text: '视频号视频'},
   ])
 
   const handleChange = (num: number, type: string) => {
@@ -39,6 +51,69 @@ export default () => {
       )
     );
   };
+  const handleWechatWidgeChange = (num: number, type: string) => {
+    console.log(num, type)
+    setWechatWidget(prevArr => 
+      prevArr.map(item => 
+        item.type === type ? { ...item, num } : item
+      )
+    );
+  };
+
+  const getComponents = (widgets: TWidget[])=> {
+    let list = widgets.filter( w => w.num > 0)
+    .reduce((prev:EComponentType[], current)=> {
+        let arr:EComponentType[] = []
+        for(let i=0; i<current.num; i++){
+          arr.push(current.type)
+        }
+        prev.push(...arr)
+      return prev
+    }, [])
+
+    const results = list.map(item => {
+      
+      let data  = createComponentData(item)
+      if(data === null){
+        console.warn('没有对应的组件')
+        return null
+      }
+      data.id = generateRandomId()
+
+      return {
+          type: item,
+          data,
+          enabled: true
+      }
+    })
+    return results.filter(item => !!item)
+  }
+
+  const handleSubmit = async () => {
+    const a = getComponents(commonWidget) as TComponentItem[]
+    const b = getComponents(wechatWidget) as TComponentItem[]
+    
+    // 统一增加 index 值
+    const results =  [...a, ...b].map( (item, index) => {
+      item.data.index = index
+      return item
+    })
+    console.log(results)
+    if(!agent?.agentId){
+      return 
+    }
+    
+    const inserted  = await insertComponent(results)
+    if(!inserted){
+      return 
+    }
+    
+    const result = await editAgentWebsite(agent.agentId, inserted)
+    if(result){
+      await fetchAgent(agent.agentId)
+      Taro.navigateBack()
+    }
+  }
 
   return (
     <View className={`global-gray-bg ${style.container}`}>
@@ -51,6 +126,7 @@ export default () => {
               <CompItem
                 num={item.num}
                 onChange={handleChange}
+                typeStyle={item.typeStyle}
                 type={item.type}
               >
                 {item.text}
@@ -69,7 +145,8 @@ export default () => {
             <View className="px-16 py-16">
               <CompItem
                 num={item.num}
-                onChange={handleChange}
+                onChange={handleWechatWidgeChange}
+                typeStyle={item.typeStyle}
                 type={item.type}
               >
                 {item.text}
@@ -81,7 +158,7 @@ export default () => {
       </View>
 
       <View className="bottom-bar">
-        <View className="px-20 pt-12">
+        <View className="px-20 pt-12" onClick={handleSubmit}>
           <View className="button-rounded-big">添加组件</View>
         </View>
       </View>

+ 11 - 6
src/pages/knowledge-item/index.tsx

@@ -8,7 +8,6 @@ import PageCustom from "@/components/page-custom/index";
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import BottomBar from "@/components/BottomBar";
 import FigureListItem from "@/components/list/figure-list-item";
-import IconFIleTxt from "@/components/icon/IconFIleTxt";
 import IconEye from "@/components/icon/IconEye";
 import IconA from "@/components/icon/IconA";
 import IconQ from "@/components/icon/IconQ";
@@ -22,6 +21,7 @@ import {
   deleteKnowledgeQa,
   updateExactAnswer,
   deleteKnowledge,
+  shareToEnt,
 } from "@/service/knowledge";
 import { TKnowledgeDetail,TQAListItem } from "@/types/knowledge";
 import { isSuccess } from "@/utils";
@@ -44,10 +44,15 @@ export default function Index() {
       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 shareKnowledgeToEnt = async (entId: string|number) => {
+    await shareToEnt({
+      knowledgeIds: [knowledgeId],
+      toEntId: entId,
+    })
+  }
+  const handleShare = async () => {
+    
   };
   // 删除问答项
   const handleDeleteItem = async (qaId: number | string) => {
@@ -260,7 +265,7 @@ export default function Index() {
           >
             删除
           </View>
-          <View className="button-rounded button-primary flex-1">
+          <View className="button-rounded button-primary flex-1" onClick={handleShare}>
             共享到企业知识
           </View>
         </BottomBar>}

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

@@ -43,7 +43,7 @@ const ViewStyleChat = () => {
         height: "100%", // 高度自适应
       }}
     >
-      <View className="flex flex-col gap-20 pb-120">
+      <View className="flex flex-col gap-20 pb-80">
         {/* 欢迎语 */}
         <MessageRobotRich data={avatarData}>
           <WelcomeCard />

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

@@ -6,5 +6,5 @@ page {
   overflow: hidden;
 }
 .tabContent{
-  height: calc(100vh - 210px);
+  height: calc(100vh - 160px);
 }

+ 2 - 2
src/service/knowledge.ts

@@ -59,8 +59,8 @@ export const getKnowledgeList = ({startId, pageSize = 1}: {
 // 共享我的知识库至企业
 export const shareToEnt = (data: 
   {
-    "knowledgeIds": number[],
-    "toEntId": string
+    "knowledgeIds": numbe|string[],
+    "toEntId": string|number
   }
 ) => {
   return request.post(`${bluebookAiAgent}api/v1/my/knowledge/shareToEnt`, data)

+ 14 - 0
src/store/agentStore.ts

@@ -8,12 +8,14 @@ import {
   deleteAgent as _deleteAgent,
   editAgentCard as _editAgentCard,
   editAgentCharacter as _editAgentCharacter,
+  editAgentWebsite as _editAgentWebsite,
 } from "@/service/agent";
 import {
   TAgentDetail,
   TAgent,
   TAgentContactCard,
   TEditAgentCharacter,
+  TComponentItem,
 } from "@/types/agent";
 import { isSuccess, pickNonEmpty } from "@/utils";
 
@@ -35,6 +37,10 @@ export interface AgentStoreState {
     agentId: string,
     data: TAgentContactCard
   ) => Promise<boolean>;
+  editAgentWebsite: (
+    agentId: string,
+    data: TComponentItem[]
+  ) => Promise<boolean>;
   // deleteAgent: (agentId: string) => Promise<void>
 }
 
@@ -141,6 +147,14 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
     
     return result
   },
+  editAgentWebsite: async (agentId: string, data: TComponentItem[]) => {
+    console.log(agentId, data);
+    const response = await _editAgentWebsite(agentId, {components: data});
+    console.log(response);
+    const result = isSuccess(response.status)
+    
+    return result
+  },
   // deleteAgent: async (agentId: string)=> {
   //   const response = await _deleteAgent(agentId)
   //   if(response.status === 200){

+ 173 - 226
src/store/componentStore.ts

@@ -1,293 +1,240 @@
-import { create } from 'zustand'
-import { saveComponent as _save, saveComponentBatch as _saveBatch, getComponentList, delComponent as _del, sortComponent as _sort } from '@/service/component'
-import { TEntityComponent } from '@/types/index'
+import { create } from "zustand";
+import { editAgentWebsite as _editAgentWebsite, editAgentAvatar, editAgentWebsite } from "@/service/agent";
+import { TComponentItem } from "@/types/agent";
+
+
+function safeSwap(arr:any[], index1:number, index2: number) {
+  if (
+    index1 >= 0 &&
+    index1 < arr.length &&
+    index2 >= 0 &&
+    index2 < arr.length
+  ) {
+    [arr[index1], arr[index2]] = [arr[index2], arr[index1]];
+  }
+  return arr;
+}
 
 export interface ComponentState {
-  loading: boolean
-  maxIndex: number // 最大组件索引
-  insertIndex: number // 插入组件的索引
-  components: TEntityComponent[] | [] // 后期是否需要改成链表方便中间插入删除等操作??
-  currentComponent: TEntityComponent | null
-  fetchComponentList: (profileID: string) => Promise<TEntityComponent[]>
-  delComponent: (c: TEntityComponent) => Promise<void>
-  saveComponent: (c: TEntityComponent) => Promise<TEntityComponent | null>
-  insertComponent: (c: TEntityComponent) => Promise<TEntityComponent | null>
-  saveBatch: (c: TEntityComponent[]) => Promise<TEntityComponent[] | null>
-  setCurrentComponent: (component: TEntityComponent | null) => TEntityComponent | null
-  calcMaxIndex: (components?: TEntityComponent[]) => void
-  resortComponent: () => void
-  swapTwoComponent: (c: TEntityComponent, direction: number) => Promise<boolean>
-  setInsertIndex: (index: number) => void
+  agentId: string,
+  maxIndex: number; // 最大组件索引
+  insertIndex: number; // 插入组件的索引
+  components: TComponentItem[] | []; // 后期是否需要改成链表方便中间插入删除等操作??
+  currentComponent: TComponentItem | null;
+  setComponentList: (list: TComponentItem[], agentId: string) => void;
+  delComponent: (c: TComponentItem) => Promise<void>;
+  saveComponent: (c: TComponentItem) => Promise<TComponentItem | null>;
+  insertComponent: (c: TComponentItem[]) => Promise<TComponentItem[] | null>;
+  swapTwoComponent: (c: TComponentItem, direction: number) => Promise<void>;
+  setCurrentComponent: (
+    component: TComponentItem | null
+  ) => TComponentItem | null;
+  setInsertIndex: (index: number) => void;
 }
 
 // 索引位置最大值
-const getMaxIndex = (components: TEntityComponent[]) => {
+const getMaxIndex = (components: TComponentItem[]) => {
   return components.reduce((acc, cur) => {
-    return Math.max(acc, cur.index ?? 1)
-  }, 0)
-}
+    return Math.max(acc, cur.data.index ?? 1);
+  }, 0);
+};
 // 根据索引位置 index 值 从小到大 排序
-export const sortComponentsByIndex = (a: TEntityComponent, b: TEntityComponent) => {
-  if (a.index === b.index) return 0
-  if (a.index === undefined || b.index === undefined) {
-    return 0
+export const sortComponentsByIndex = (a: TComponentItem, b: TComponentItem) => {
+  if (a.data.index === b.data.index) return 0;
+  if (a.data.index === undefined || b.data.index === undefined) {
+    return 0;
   }
-  return a.index - b.index
-}
+  return a.data.index - b.data.index;
+};
 
 export const useComponentStore = create<ComponentState>((set, get) => ({
   loading: false,
+  agentId: '',
   components: [],
   currentComponent: null,
   maxIndex: 1,
   insertIndex: -1,
-  fetchComponentList: async (profileId: string) => {
-    const response = await getComponentList(profileId)
-    // 兼容旧数据 images 转 media
-    if (response.code === 0 && response.data) {
-      response.data.map( item => {
-        if(item.type === 'images' && item.data?.images?.length){
-          item.data.media = item.data.images.map((img:any)=> {
-            return {
-              url: img.src,
-              fileType: 'image',
-            }
-          })
-        }
-        return item
-      })
-      let sorted = response.data.sort(sortComponentsByIndex)
-      set({ components: sorted, maxIndex: getMaxIndex(sorted) })
-    }
-    return response?.data
+  setComponentList: (list: TComponentItem[], agentId: string) => {
+    let sorted = list.sort(sortComponentsByIndex);
+    set({agentId, components: sorted, maxIndex: getMaxIndex(sorted) });
   },
-  insertComponent: async (c: TEntityComponent) => {
-    const insertIndex = get().insertIndex
-    let _components = get().components.sort(sortComponentsByIndex)
-    set({loading: false})
-    if (insertIndex === -1) {
-      return null
-    }
-    console.log('insertIndex:', insertIndex)
-    if (insertIndex === 0) {
-      // 顶部插入
-      c.index = 1;
-    }else if(insertIndex === _components.length){
-      // 底部插入
-      c.index = insertIndex + 1
-    }else{
-      // 中间插入
-      c.index = insertIndex + 1
-    }
-    console.log('插入位置', c.index)
-    
-    // 先保存生成 id 
-    const res = await _save(c)
-    const saved = res?.data
-    if (!saved) {
-      set({loading: false})
-      return null
-    }
-    
-    // 如果插入的是最后一个位置则其余无需变动
-    if (insertIndex === _components.length) {
-      set({
-        components: [..._components, saved],
-        loading: false
-      })
-      return saved
-    }
+  insertComponent: async (list: TComponentItem[]) => {
 
-    // 在最顶上插入
-    if (insertIndex === 0) {  
-      // 其余组件索引+1
-      _components = _components.map((item: TEntityComponent) => {
-        if (item.index !== undefined) {
-          item.index = item.index + 1
-        }
-        return item
+
+    const insertIndex = get().insertIndex;
+    let _components = get().components.sort(sortComponentsByIndex);
+    console.log('current components list:', _components)
+    const _componentsLen = _components.length
+
+    
+    console.log("insertIndex:", insertIndex);
+    if (insertIndex === -1) {
+      console.log('顶部插入')
+      // 顶部插入, 原组件列表所有 index + list.length
+      _components = _components.map((item: TComponentItem) => {
+        item.data.index = item.data.index + list.length;
+        return item;
+      });
+      _components = [...list, ..._components];
+    } else if (insertIndex === _componentsLen - 1) {
+      console.log('底部插入')
+      // 底部插入, 所有新插入的组件 index 需要加上已存在组件列表长度
+      list = list.map( c => {
+        c.data.index =  c.data.index + _componentsLen
+        return c
       })
-      _components = [saved, ..._components]
+      _components = [..._components, ...list];
     } else {
-      // 中间位置插入
-      // 插入位置之后的组件索引+1
-      const restIndex = insertIndex
+      // 中间插入, 
+      console.log('中间插入')
+      const restIndex = insertIndex + 1;
+      list = list.map( c => {
+        c.data.index = c.data.index + restIndex
+        return c 
+      })
+
       let rest = _components.slice(restIndex).map((item) => {
-        if (item.index) {
-          item.index = item.index + 1
+        if (item.data.index) {
+          item.data.index = item.data.index + list.length;
         }
-        console.log(item.index, item.data)
-        return item
-      })
-      
-      _components = [..._components.slice(0, restIndex), saved, ...rest]
+        console.log(item.data.index, item.data);
+        return item;
+      });
+
+      _components = [..._components.slice(0, restIndex), ...list, ...rest];
+      console.log(_components,111)
     }
+
+
+    set({components: _components})
     
-    // 顶上和中间位置插入需要调整整个组件列表
-    await get().saveBatch(_components)
-    return saved
+    return _components;
   },
-  saveComponent: async (c: TEntityComponent) => {
-    console.log('saveComponent')
-    
+  saveComponent: async (c: TComponentItem) => {
+    console.log("saveComponent");
+
     // insertIndex 是组件列表插入组件时提前设置的
     const insertIndex = get().insertIndex;
-    console.log(c.id, insertIndex)
+    console.log(c.id, insertIndex);
     // 没有 id  且 insertIndex > -1 说明是插入组件
-    if (c.id === undefined &&  insertIndex > -1) {
-      console.log('insertComponentBatch:', c, insertIndex)
-      
-      return await get().insertComponent(c)
+    if (c.id === undefined && insertIndex > -1) {
+      console.log("insertComponentBatch:", c, insertIndex);
+
+      return await get().insertComponent(c);
     }
 
     // 简单更新组件
-    console.log('updateComponent: ', c, insertIndex)
+    console.log("updateComponent: ", c, insertIndex);
     // 如果是普通保存(直接 tabbar 点击添加组件按钮进入,非插入)
-    if(c.id === undefined){
-      
-      return null
+    if (c.id === undefined) {
+      return null;
     }
     // 普通更新或新建
-    const res = await _save(c)
+    const res = await _save(c);
     if (res.code !== 0) {
-      
-      return null
+      return null;
     }
     set((state) => {
-      let _components = state.components
+      let _components = state.components;
       if (c.id) {
-        _components = _components.filter((item: TEntityComponent) => item?.id !== c.id)
+        _components = _components.filter(
+          (item: TComponentItem) => item?.id !== c.id
+        );
       }
-      let sorted = [..._components, res.data].sort(sortComponentsByIndex)
-      state.calcMaxIndex(sorted)
+      let sorted = [..._components, res.data].sort(sortComponentsByIndex);
+      state.calcMaxIndex(sorted);
       return {
         components: sorted,
-        loading: false
-      }
-    })
-    
-    return res?.data
+        loading: false,
+      };
+    });
+
+    return res?.data;
   },
-  // 批量保存
-  saveBatch: async (batchComponent: TEntityComponent[]) => {
-    
-    if(!batchComponent.length){
-      return null
-    }
-    const res = await _saveBatch(batchComponent)
-    if (res.code !== 0) {
-      
-      return null
-    }
-    
-    let sorted = (res.data ?? []).sort(sortComponentsByIndex)
-    set((state) => {
-      state.calcMaxIndex(sorted)
-      return {
-        components: sorted,
-        loading: false
-      }
-    })
-    return res?.data
+  setInsertIndex: (index) => {
+    console.log(index,' setInsertIndex')
+    set({ insertIndex: index });
   },
-  setCurrentComponent: (component: TEntityComponent | null) => {
-    set({ currentComponent: component })
+  setCurrentComponent: (component: TComponentItem | null) => {
+    set({ currentComponent: component });
 
     return component;
   },
   delComponent: async (c) => {
-    if(!c.id){
-      return
-    }
-    const res = await _del(c.id)
-    if (res.code === 0) {
-      set((state) => {
-        const filtered = state.components.filter((item: TEntityComponent) => item?.id !== c.id)
-        .sort(sortComponentsByIndex).map((item: TEntityComponent, index)=> {
-          return {
-            ...item,
-            index: index + 1
-          }
-        })
-        get().saveBatch(filtered)
-        
-        return {
-          components: [...filtered]
-        }
-      })
-    }
-  },
-  setLoading: (loading: boolean) => {
-    set({ loading })
+    set({components: []})
+    
+    // if (!c.data.id) {
+    //   return;
+    // }
+    // set((state) => {
+    //   const filtered = state.components
+    //   .filter((item: TComponentItem) => item?.data.id !== c.data.id)
+    //   .sort(sortComponentsByIndex)
+    //   .map((item: TComponentItem, index) => {
+    //     return {
+    //       ...item,
+    //       index: index + 1,
+    //     };
+    //   });
+    //   return {
+    //     components: [...filtered],
+    //   };
+    // });
   },
-  calcMaxIndex: (components?: TEntityComponent[]) => {
+  
+  calcMaxIndex: (components?: TComponentItem[]) => {
     set((state) => {
-      return { maxIndex: getMaxIndex(components?? state.components) }
-    })
+      return { maxIndex: getMaxIndex(components ?? state.components) };
+    });
   },
   resortComponent: () => {
-    
     set((state) => {
-      let _comp = state.components
+      let _comp = state.components;
 
-      let r = [..._comp].sort(sortComponentsByIndex)
-      console.log(r)
+      let r = [..._comp].sort(sortComponentsByIndex);
+      console.log(r);
       return {
         components: r,
-        loading: false
-      }
-    })
+        loading: false,
+      };
+    });
   },
   // 交换两个组件上下位置
-  swapTwoComponent: async (c: TEntityComponent, direction: number) => {
-    
-    const cur = { ...c }
-    const components = get().components
-    const arrIndex = components.findIndex((item) => item.id === c.id)
-    let destComponent: TEntityComponent | null = null;
+  swapTwoComponent: async (c: TComponentItem, direction: number) => {
+    const cur = { ...c };
+    const components = get().components;
+    const arrIndex = components.findIndex((item) => item.data.id === c.data.id);
+    let destComponent: TComponentItem | null = null;
     if (direction === 0) {
-      destComponent = components[arrIndex - 1]
-
+      destComponent = components[arrIndex - 1];
     } else if (direction === 1) {
-      destComponent = components[arrIndex + 1]
+      destComponent = components[arrIndex + 1];
     }
+    
+    
+    const tmpList = [...components]
+
+    
     if (destComponent) {
-      destComponent = { ...destComponent }
-      const i = cur.index
-      cur.index = destComponent.index
-      destComponent.index = i;
-      const res = await _sort([cur, destComponent])
-      if (res.code === 0 && res.data) {
-        let temp = [...components]
-        res.data.forEach(element => {
-          temp = temp.map(item => {
-            if (item.id === element.id) {
-              return element
-            }
-            return item
-          })
-        });
-        set({ components: temp, loading: false })
-        return true;
-      }
-      return false
+      destComponent = { ...destComponent };
+      const destComponentIndex = components.findIndex((item) => item.data.id === destComponent?.data.id);
+      const i = cur.data.index;
+      cur.data.index = destComponent.data.index;
+      destComponent.data.index = i;
+      const r = safeSwap(tmpList, arrIndex, destComponentIndex) as TComponentItem[]
+      await editAgentWebsite(get().agentId, {components: r})
+      set({components: r})
     }
-    
-    return false
   },
-  setInsertIndex(index: number) {
-    set({ insertIndex: index })
-  },
-}))
+}));
 
 // 获取组件列表中某个组件
 export const getComponentById = (id: number) => {
   return useComponentStore((state) => {
-    return state.components.find(c => c.id === id)
-  })
-}
+    return state.components.find((c) => c.id === id);
+  });
+};
 // 当前 component 便捷hook
-export const useCurrentComponent = ()=> {
-  return useComponentStore((state)=> state.currentComponent)
-}
-
+export const useCurrentComponent = () => {
+  return useComponentStore((state) => state.currentComponent);
+};

+ 8 - 4
src/types/agent.ts

@@ -1,4 +1,4 @@
-
+import {EComponentType} from '@/consts/enum'
 export type TAgent = {
   address: string|null
   agentId: string
@@ -16,9 +16,13 @@ export type TAgent = {
   qrCodeUrl: string
 }
 export type TComponentItem = {
-  "data"?: any,
-  "enabled"?: boolean,
-  "type"?: string
+  data: {
+    id: string,
+    index: number,
+    [property: string]: any;
+  },
+  enabled: boolean,
+  type: string|EComponentType
 }
 export type TAgentDetail = {
   address?: string,