Procházet zdrojové kódy

feat: 分享小程序码

王晓东 před 1 měsícem
rodič
revize
9c8a96fce7
46 změnil soubory, kde provedl 332 přidání a 1329 odebrání
  1. 1 4
      src/app.config.ts
  2. 4 7
      src/app.tsx
  3. 0 1
      src/components/AgentPage/components/AgentQRcode/index.tsx
  4. 3 3
      src/components/AgentPage/components/SummaryBar/index.tsx
  5. 0 4
      src/components/component-list/components/card-contacts/index.tsx
  6. 0 20
      src/components/custom-share/CustomShareComponent.tsx
  7. 0 0
      src/components/custom-share/SharePopup/index.module.less
  8. 15 27
      src/components/custom-share/SharePopup/index.tsx
  9. 0 0
      src/components/custom-share/ShareWxaCard/index.module.less
  10. 20 62
      src/components/custom-share/ShareWxaCard/index.tsx
  11. 83 0
      src/components/custom-share/ShareWxaCard/shareCard.ts
  12. 6 2
      src/components/custom-share/index.tsx
  13. 1 0
      src/components/custom-share/shareUtils.ts
  14. 2 1
      src/config/index.ts
  15. 0 1
      src/pages/agent-gen/components/step/StepStart.tsx
  16. 1 0
      src/pages/agent/components/AgentSetting/components/AgentCard/index.module.less
  17. 50 44
      src/pages/agent/components/AgentSetting/components/AgentKnowledgeLib/index.tsx
  18. 3 20
      src/pages/agent/components/AgentSetting/index.tsx
  19. 7 3
      src/pages/agent/index.tsx
  20. 0 5
      src/pages/chat-history/index.config.ts
  21. 0 66
      src/pages/chat-history/index.module.less
  22. 0 64
      src/pages/chat-history/index.tsx
  23. 4 4
      src/pages/chat/components/personal-card/index.tsx
  24. 0 5
      src/pages/choose-contact/index.config.ts
  25. 0 3
      src/pages/choose-contact/index.module.less
  26. 0 212
      src/pages/choose-contact/index.tsx
  27. 0 4
      src/pages/contact/index.tsx
  28. 0 5
      src/pages/editor-pages/editor-company/index.config.ts
  29. 0 2
      src/pages/editor-pages/editor-company/index.module.less
  30. 0 79
      src/pages/editor-pages/editor-company/index.tsx
  31. 0 5
      src/pages/editor-pages/editor-position/index.config.ts
  32. 0 2
      src/pages/editor-pages/editor-position/index.module.less
  33. 0 79
      src/pages/editor-pages/editor-position/index.tsx
  34. 1 1
      src/pages/profile/index.module.less
  35. 61 30
      src/pages/profile/index.tsx
  36. 6 0
      src/pages/profile/profile.ts
  37. 1 13
      src/pages/test/index.tsx
  38. 1 2
      src/pages/voice/components/MyVoiceList/index.tsx
  39. 4 2
      src/service/agent.ts
  40. 0 287
      src/service/character.ts
  41. 0 12
      src/service/stats.ts
  42. 53 0
      src/service/wechat.ts
  43. 4 3
      src/store/agentStore.ts
  44. 0 178
      src/store/characterStore.ts
  45. 0 66
      src/utils/auth.ts
  46. 1 1
      src/utils/index.ts

+ 1 - 4
src/app.config.ts

@@ -24,8 +24,7 @@ export default defineAppConfig({
     'pages/test/index',
     'pages/component-library/index',
     'pages/editor-pages/editor-name/index',
-    'pages/editor-pages/editor-company/index',
-    'pages/editor-pages/editor-position/index',
+    
     'pages/editor-pages/editor-phone/index',
     'pages/editor-pages/editor-tel/index',
     'pages/editor-pages/editor-email/index',
@@ -47,8 +46,6 @@ export default defineAppConfig({
     'pages/editor-pages/editor-textarea/index',
     'pages/editor-pages/editor-title/index',
     
-    'pages/chat-history/index',
-    
     'pages/webview/index',
 
   ],

+ 4 - 7
src/app.tsx

@@ -3,7 +3,7 @@ import { PropsWithChildren } from "react";
 import "./app.less";
 import { useAppStore } from "./store/appStore";
 import { generateRandomId } from '@/utils/index'
-import {LOGIN_ID_STORAGE_KEY } from '@/xiaolanbenlib/constant/'
+import {LOGIN_ID_STORAGE_KEY } from '@/xiaolanbenlib/constant'
 
 if (process.env.TARO_ENV == "h5") {
   const VConsole = require("vconsole");
@@ -12,12 +12,9 @@ if (process.env.TARO_ENV == "h5") {
 function App({ children }: PropsWithChildren<any>) {
   const { setSystemInfo } = useAppStore();
 
-  useLaunch(() => {
-    console.log("App launched.");
-
-    if (process.env.TARO_ENV == "h5") {
-      return;
-    }
+  useLaunch((options) => {
+    console.log("App launched.", options.query);
+    
 
     const updateManager = Taro.getUpdateManager();
 

+ 0 - 1
src/components/AgentPage/components/AgentQRcode/index.tsx

@@ -19,7 +19,6 @@ export default ({ show, setShow, isVisitor }: IProps) => {
   const agentContactCard = useAgentStore((state) => state.agentContactCard);
   const agent = useAgentStore((state) => state.agent);
   const isMine = (!isVisitor) 
-  console.log(isVisitor,1111)
   // ?? (agent?.isMineAgent !== false)
   // const agents = useAgentStore((state) => state.agents);
   // const existed = agents.find((item)=> agent?.agentId === item.agentId)

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

@@ -13,7 +13,7 @@ import ContactIcon from '@/components/ContactIcon'
 import { useAppStore } from "@/store/appStore";
 import AgentSwap from "../AgentSwap/index";
 import AgentQRCode from "../AgentQRcode/index";
-import SharePopup from "@/components/custom-share/share-popup";
+import SharePopup from "@/components/custom-share/SharePopup";
 import Taro from "@tarojs/taro";
 import PopupSheets from "@/components/popup/popup-sheets";
 
@@ -76,13 +76,13 @@ export default ({agent, isVisitor}: IProps) => {
               <View className="flex flex-col flex-1">
                 <View className="flex items-end gap-8">
                   <View className="text-24 font-medium leading-32">{agent?.name}</View>
-                  <View className="text-12 leading-20">{agent?.position ?? '--'}</View>
+                  <View className="text-12 leading-20">{agent?.position ?? ''}</View>
                 </View>
                 <View className="flex items-center gap-2">
                   <View className="text-12 leading-20 truncate max-w-[188px]">
                     {agent?.entName ?? '--'}
                   </View>
-                  <TagCertificated />
+                  {agent?.isEnt && <TagCertificated />}
                 </View>
               </View>
               {!isVisitor && <View

+ 0 - 4
src/components/component-list/components/card-contacts/index.tsx

@@ -1,14 +1,10 @@
 import Taro from "@tarojs/taro";
 import { View, Image } from "@tarojs/components";
 import WidgetCard from "@/components/widgets/widget-card/index";
-import { batchGet } from "@/service/character";
 import ContactCard from "@/components/contact-card/index";
 import style from "./index.module.less";
 import IconArrowRight from "@/images/icon_24_right.png";
 import { axios } from "taro-axios";
-import type {
-  ICharacter,
-} from "@/types/index";
 import { useEffect, useState } from "react";
 import { TAgent, TComponentItem } from "@/types/agent";
 import { TContactItem } from "@/types/contact";

+ 0 - 20
src/components/custom-share/CustomShareComponent.tsx

@@ -1,20 +0,0 @@
-import {useMemo} from 'react'
-import CustomShare from '@/components/custom-share/index';
-import { TAgent } from '@/types/agent';
-
-interface Props {
-  agent: TAgent | null;
-}
-const CustomShareComponent = (props: Props) => {
-  const { agent } = props;
-  const renderedComponent = useMemo(() => {
-    if (!agent) {
-      return null;
-    }
-    return <CustomShare agent={agent} />;
-  }, [agent]);
-
-  return renderedComponent;
-};
-
-export default CustomShareComponent

+ 0 - 0
src/components/custom-share/share-popup/index.module.less → src/components/custom-share/SharePopup/index.module.less


+ 15 - 27
src/components/custom-share/share-popup/index.tsx → src/components/custom-share/SharePopup/index.tsx

@@ -1,51 +1,39 @@
+/**
+ * 分享弹层
+ */
+
 import { useMemo, useRef } from "react";
 import { View, Image, Button, RootPortal } from "@tarojs/components";
 import style from "./index.module.less";
 import IconShareWechat from "@/images/icon-share-wechat.png";
 import IconShareQrcode from "@/images/icon-share-qrcode.png";
-import ShareCard, {type IShareCard} from "@/components/custom-share/share-card/index";
-import CustomShareComponent from "@/components/custom-share/CustomShareComponent";
+import ShareWxaCard, {type IShareCard} from "@/components/custom-share/ShareWxaCard/index";
+import CustomShare from '../index';
 import Popup from "@/components/popup/popup";
-import { TAgent } from "@/types/agent";
-import Taro from "@tarojs/taro";
+import { TAgentDetail } from "@/types/agent";
+
 
 
 interface Props {
   show: boolean;
-  agent: TAgent | null;
+  agent: TAgentDetail | null;
   setShow: (show:boolean) => void;
 }
 export default ({ show, setShow, agent }: Props) => {
   const shareCardRef = useRef<IShareCard>(null)
-  // todo: 优化至点击后再去生成小程序二维码
-  const ShareCardComponent = useMemo(
-    () => {
-      if(agent){
-        return <ShareCard ref={shareCardRef} agent={agent}></ShareCard>
-      }
-    }, [agent]
-  );
-  
 
   const handleSavePicture = () => {
     console.log(shareCardRef?.current)
-    Taro.showToast({title: '暂不支持此功能', icon: 'none'})
-    // shareCardRef?.current?.saveCardToAlbum(); // 调用子组件的保存方法
+    shareCardRef?.current?.saveCardToAlbum(); // 调用子组件的保存方法
   }
 
   
-  // 默认要生成分享图
-  const renderSharePicture = ()=> {
-    if(agent?.agentId){
-      return <CustomShareComponent agent={agent} />
-    }
-    return <></>
-  }
   
-
   return (
     <RootPortal>
-      { renderSharePicture() }
+      {/* 默认要生成分享图, 分享时会主动调用内部逻辑 */}
+      {agent && <CustomShare agent={agent} />}
+
       <Popup show={show} setShow={setShow}>
         {/* 显示分享弹窗后再进行分享逻辑 */}
         <View className={style.container}>
@@ -60,8 +48,8 @@ export default ({ show, setShow, agent }: Props) => {
                 <View className={style.buttonText}>保存图片</View>
               </View>
             </View>
-          
-          {ShareCardComponent}
+            {/* 保存小程序码 */}
+            {agent && <ShareWxaCard ref={shareCardRef} agent={agent}></ShareWxaCard>}
         </View>
       </Popup> 
     </RootPortal>

+ 0 - 0
src/components/custom-share/share-card/index.module.less → src/components/custom-share/ShareWxaCard/index.module.less


+ 20 - 62
src/components/custom-share/share-card/index.tsx → src/components/custom-share/ShareWxaCard/index.tsx

@@ -1,8 +1,13 @@
+/**
+ *  生成微信小程序码卡片
+ */
+
 import { Canvas } from "@tarojs/components";
 import style from "./index.module.less";
 import { getCanvasTempPath, savePicture } from "@/utils/index";
 import { checkPermission, showAuthModal } from "@/utils/auth";
-import { APP_ENV_VERSION, APP_NAME_TEXT } from '@/config'
+import { APP_NAME_TEXT, DEFAULT_AVATAR } from '@/config'
+
 import {
   Application,
   ImgLoader,
@@ -13,81 +18,33 @@ import {
 } from "@/libs/duducanvas/index";
 import Stage from "@/libs/duducanvas/Stage";
 import Taro from "@tarojs/taro";
-import { genCharacterQrcode } from "@/service/character";
+import { genQrcode, getCanvasSize } from './shareCard'
+
 import { forwardRef, useImperativeHandle } from "react";
-import { getAvatarImageSrc } from "../shareUtils";
-import { TAgent } from "@/types/agent";
+import { TAgentDetail } from "@/types/agent";
 
 export interface IShareCard {
   saveCardToAlbum: () => void;
 }
 
-const getCanvasSize = () => {
-  const designWidth = 319;
-  const designHeight = 447;
-  // 宽高放大一倍
-  const ratio = 5;
-  const canvasWidth = designWidth * ratio;
-  const canvasHeight = designHeight * ratio;
-  return {
-    canvasWidth,
-    canvasHeight,
-    ratio,
-    rValue: (v: number) => v * ratio,
-  };
-};
-
-// 生成微信小程序二维码
-const genQrcode = async (
-  profileId: string,
-  qrcodeWidth: number,
-  qrcodeHeight: number,
-  stage: Stage,
-  container: Container
-) => {
-  const res = await genCharacterQrcode(profileId, {
-    scene: profileId,
-    page: `pages/profile/index`,
-    width: qrcodeWidth,
-    envVersion: APP_ENV_VERSION,
-  });
-  if (res.code !== 0) {
-    return;
-  }
-  const loader = new ImgLoader(stage.canvas, [
-    {
-      id: "qrcode",
-      src: `data:image/png;base64,${res.data}`,
-    },
-  ]);
-  await loader.load();
-  const qrcodeTexture = loader.get("qrcode");
-  if (qrcodeTexture) {
-    const qrcodeImage = new DuduImage({
-      image: qrcodeTexture.image,
-      width: qrcodeWidth,
-      height: qrcodeHeight,
-    });
-    container.addChild(qrcodeImage);
-  }
-};
-
 interface Props {
-  agent: TAgent;
+  agent: TAgentDetail;
 }
 
+
 export default forwardRef(({ agent }: Props, ref) => {
-  const { canvasWidth, canvasHeight, ratio, rValue } = getCanvasSize();
+  const { canvasWidth, canvasHeight, rValue } = getCanvasSize();
   let stage: Stage|null;
 
   // 保存至相册
   const saveCardToAlbum = async () => {
-    if(!stage){
-      return
-    }
+    
     Taro.showLoading();
     // 延迟获取 canvas
     await initCanvas();
+    if(!stage){
+      return
+    }
     let tmpImage = await getCanvasTempPath(stage.canvas, "shareCard");
     const authed = await checkPermission("scope.writePhotosAlbum");
     if (!authed) {
@@ -118,7 +75,7 @@ export default forwardRef(({ agent }: Props, ref) => {
     if(!stage){
       return
     }
-    const avatarImg = getAvatarImageSrc(agent.avatarUrl ?? "")
+    const avatarImg = agent.avatarUrl ?? DEFAULT_AVATAR
 
     const loader = new ImgLoader(stage.canvas, [
       {
@@ -191,8 +148,9 @@ export default forwardRef(({ agent }: Props, ref) => {
     card.addChild(tips);
 
     stage.addChild(card);
-    
-    // await genQrcode(agent.agentId, rValue(227), rValue(234), stage, qrcodeView);
+    if(agent.agentId){
+      await genQrcode(agent.agentId, rValue(255), rValue(255), stage, qrcodeView);
+    }
     stage.update();
     Taro.hideLoading();
     return stage;

+ 83 - 0
src/components/custom-share/ShareWxaCard/shareCard.ts

@@ -0,0 +1,83 @@
+import { getAgentShareInfo } from '@/service/agent';
+import { isSuccess } from "@/utils/index";
+import { genWechatQrcode, sceneZip } from "@/service/wechat";
+import { APP_ENV_VERSION } from '@/config/index'
+import {
+  ImgLoader,
+  Container,
+  Image as DuduImage,
+  Stage,
+} from "@/libs/duducanvas/index";
+
+// 生成微信小程序二维码
+export const genQrcode = async (
+  agentId: string,
+  qrcodeWidth: number,
+  qrcodeHeight: number,
+  stage: Stage,
+  container: Container
+) => {
+  const respnose = await getAgentShareInfo(agentId)
+  if(!isSuccess(respnose.status)){
+    return;
+  }
+  
+  const sceneStr = JSON.stringify({agentId: agentId, shareKey: respnose.data.shareKey})
+  
+
+  // 压缩参数
+  const zipResponse = await sceneZip(sceneStr)
+  if(!isSuccess(zipResponse.status)){
+    return;
+  }
+  // 生成小程序二维码
+  const genResponse = await genWechatQrcode({
+    scene: zipResponse.data.shortScene,
+    page: `pages/profile/index`,
+    width: qrcodeWidth,
+    check_path: false,
+    auto_color: true,
+    is_hyaline: false,
+    line_color: {r:30, g: 111, b: 248 },
+    env_version: APP_ENV_VERSION,
+  }, 'base64');
+  if(!isSuccess(genResponse.status)){
+    return
+  }
+  if (!genResponse.data.imgBase64) {
+    return;
+  }
+
+  const loader = new ImgLoader(stage.canvas, [
+    {
+      id: "qrcode",
+      src: `data:image/png;base64,${genResponse.data.imgBase64}`,
+    },
+  ]);
+  await loader.load();
+  
+  const qrcodeTexture = loader.get("qrcode");
+  if (qrcodeTexture) {
+    const qrcodeImage = new DuduImage({
+      image: qrcodeTexture.image,
+      width: qrcodeWidth,
+      height: qrcodeHeight,
+    });
+    container.addChild(qrcodeImage);
+  }
+};
+
+export const getCanvasSize = () => {
+  const designWidth = 319;
+  const designHeight = 447;
+  // 宽高放大一倍
+  const ratio = 2;
+  const canvasWidth = designWidth * ratio;
+  const canvasHeight = designHeight * ratio;
+  return {
+    canvasWidth,
+    canvasHeight,
+    ratio,
+    rValue: (v: number) => v * ratio,
+  };
+};

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 6 - 2
src/components/custom-share/index.tsx


+ 1 - 0
src/components/custom-share/shareUtils.ts

@@ -1,6 +1,7 @@
 import { getAgentShareInfo } from "@/service/agent"
 import { isSuccess } from "@/utils"
 
+
 export const getAvatarImageSrc = (avatarImg: string)=> {
     const mp4SuffixIndex = avatarImg.lastIndexOf('.mp4')
     if(mp4SuffixIndex > -1){

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 1
src/config/index.ts


+ 0 - 1
src/pages/agent-gen/components/step/StepStart.tsx

@@ -41,7 +41,6 @@ export default React.memo(function StepStart({ next, setTaskId }: IProps) {
       description: value,
     })
     Taro.hideLoading();
-    console.log(response,1111)
     if(isSuccess(response.status)){
       setTaskId(response.data.taskId)
       next();

+ 1 - 0
src/pages/agent/components/AgentSetting/components/AgentCard/index.module.less

@@ -7,6 +7,7 @@
   justify-content: center;
   width: 200px;
   height: 356px;
+  overflow: hidden;
   border-radius: 16px;
   background-color: white;
 }

+ 50 - 44
src/pages/agent/components/AgentSetting/components/AgentKnowledgeLib/index.tsx

@@ -1,5 +1,4 @@
 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 WemetaSwitch from "@/components/wemeta-switch";
@@ -8,13 +7,21 @@ import IconArrow from "@/components/icon/icon-arrow";
 
 import IconPageColor from "@/components/icon/icon-page-color";
 import Taro from "@tarojs/taro";
+import { useAgentStore } from "@/store/agentStore";
 
 export default function Index() {
-  
-  const [checked, setChecked] = useState(false);
-  const handleSwitchChange = (checked: boolean) => {
-    setChecked(checked);
-    // onSwitchChanged && onSwitchChanged(checked);
+  const { agent, editAgentCharacter, fetchAgent } = useAgentStore();
+  const agentCharacter = useAgentStore((state) => state.agentCharacter);
+  const handleSwitchChange = async (checked: boolean) => {
+    if (!agent?.agentId || !agentCharacter) {
+      return;
+    }
+
+    await editAgentCharacter(agent.agentId, {
+      ...agentCharacter,
+      enabledPersonalKb: checked,
+    });
+    fetchAgent(agent.agentId);
   };
 
   const IconArrowRight = () => {
@@ -25,46 +32,47 @@ export default function Index() {
     );
   };
 
-  const handleClick = ()=> {
+  const handleClick = () => {
     Taro.switchTab({
-      url: '/pages/knowledge/index'
-    })
-    
+      url: "/pages/knowledge/index",
+    });
+  };
+
+  if (!agent || !agent.isEnt) {
+    return <></>;
   }
 
   return (
     <CardList>
-            <CardListItem
-              className="pl-16 pr-8"
-              leftRenderer={IconPageColor}
-              rightRenderer={IconArrowRight}
-              onClick={handleClick}
-            >
-              <View className="text-14 py-18 font-medium leading-22">
-                知识库
+      <CardListItem
+        className="pl-16 pr-8"
+        leftRenderer={IconPageColor}
+        rightRenderer={IconArrowRight}
+        onClick={handleClick}
+      >
+        <View className="text-14 py-18 font-medium leading-22">知识库</View>
+      </CardListItem>
+      <View className="">
+        <View className="flex flex-col gap-12 px-16 pb-16">
+          <View className="flex rounded-8 p-16 gap-16 bg-gray-3">
+            <View className="flex-1">
+              <View className="text-14 font-medium leading-22 text-black pb-2">
+                个人知识
               </View>
-            </CardListItem>
-            <View className="">
-              <View className="flex flex-col gap-12 px-16 pb-16">
-                <View className="flex rounded-8 p-16 gap-16 bg-gray-3">
-                  <View className="flex-1">
-                    <View className="text-14 font-medium leading-22 text-black pb-2">
-                      个人知识
-                    </View>
-                    <View className="text-12 leading-20 text-gray-45">
-                      使用你上传的内容(如文档、链接等)作为智能体回答的知识基础。
-                    </View>
-                  </View>
+              <View className="text-12 leading-20 text-gray-45">
+                使用你上传的内容(如文档、链接等)作为智能体回答的知识基础。
+              </View>
+            </View>
 
-                  <View className="flex-center">
-                    <WemetaSwitch
-                      checked={checked}
-                      onChange={(checked) => handleSwitchChange(checked)}
-                    ></WemetaSwitch>
-                  </View>
-                </View>
+            <View className="flex-center">
+              <WemetaSwitch
+                checked={agent.enabledPersonalKb ?? true}
+                onChange={(checked) => handleSwitchChange(checked)}
+              ></WemetaSwitch>
+            </View>
+          </View>
 
-                <View className="flex rounded-8 p-16 bg-gray-3">
+          {/* <View className="flex rounded-8 p-16 bg-gray-3">
                   <View className="flex-1">
                     <View className="text-14 font-medium leading-22 text-black pb-2">
                       杭州茗视光眼科医院
@@ -80,11 +88,9 @@ export default function Index() {
                       onChange={(checked) => handleSwitchChange(checked)}
                     ></WemetaSwitch>
                   </View>
-                </View>
-              </View>
-            </View>
-          </CardList>
+                </View> */}
+        </View>
+      </View>
+    </CardList>
   );
 }
-
-

+ 3 - 20
src/pages/agent/components/AgentSetting/index.tsx

@@ -6,28 +6,11 @@ import AgentContactCard from './components/AgentContactCard'
 
 import React, { useEffect, useState } from "react";
 import { useAgentStore } from "@/store/agentStore";
-import { fetchMyAvatars, TAvatarItem } from "@/service/storage";
-import { isSuccess } from "@/utils";
+
 
 export default React.memo(function Index() {
   console.log('agent setting')
-
-  const [avatars, setAvatars] = useState<TAvatarItem[]>([])
-
-  const {agent, fetchAgents} = useAgentStore()
-  
-  // const getMyAvatars = async () => {
-  //   const response =  await fetchMyAvatars({pageSize: 20, pageIndex: 1})
-  //   if(isSuccess(response.status)){
-  //     console.log(response.data)
-  //     setAvatars(response.data.data)
-  //   }
-  // }
-
-  // useEffect(()=> {
-  //   getMyAvatars()
-  // }, [])
-  
+  const {fetchAgents} = useAgentStore()  
 
   useEffect(()=> {
     fetchAgents()
@@ -40,7 +23,7 @@ export default React.memo(function Index() {
         <AgentContactCard></AgentContactCard>
       </View>
       <AgentSettingList></AgentSettingList>
-      <View className="pt-20">
+      <View className="py-20">
         <AgentKnowledgeLib></AgentKnowledgeLib>
       </View>
     </View>

+ 7 - 3
src/pages/agent/index.tsx

@@ -7,7 +7,7 @@ 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 { useDidShow, useRouter } from "@tarojs/taro";
 import { useComponentStore } from "@/store/componentStore";
 import { useUserStore } from "@/store/userStore";
 
@@ -43,9 +43,13 @@ export default function Index() {
     },
   ];
 
-  useEffect(() => {
+  useDidShow(()=> {
     agentId && fetchAgentDetail(agentId);
-  }, [agentId]);
+  })
+
+  // useEffect(() => {
+  //   agentId && fetchAgentDetail(agentId);
+  // }, [agentId]);
 
   return (
     <PageCustom>

+ 0 - 5
src/pages/chat-history/index.config.ts

@@ -1,5 +0,0 @@
-export default definePageConfig({
-  navigationBarTitleText: '分析',
-  "usingComponents": {},
-  "navigationStyle": 'custom',
-})

+ 0 - 66
src/pages/chat-history/index.module.less

@@ -1,66 +0,0 @@
-.page{
-  padding: 20px 28px 20px;
-  width: 100%;
-  margin: 20px 28px;
-}
-.container{
-  padding: 36px 24px;
-  border-radius: 20px;
-  box-shadow: 0px 8px 16px 0px rgba(#6A685E, .05);
-  background-color: white;
-}
-.summary{
-  display: flex;
-  flex-direction: column;
-  border-bottom: 2px dashed #000;
-  padding-bottom: 36px;
-}
-.turnRow{
-  display: flex;
-  align-items: center;
-  gap: 2px;
-  padding: 36px 0 4px;
-}
-.turnNum{
-  font-size: 24px;
-  line-height: 32px;
-  color: #000;
-}
-.turnText{
-  font-size: 20px;
-  line-height: 28px;
-}
-.datetime{
-  flex: 1;
-  font-size: 12px;
-  line-height: 22px;
-  color: rgba(#000, .45);
-}
-.userName{
-  font-size: 12px;
-  line-height: 22px;
-  color: rgba(#000, .45);
-}
-.listItem{
-  padding: 20px 0;
-  width: 100%;
-  border-bottom: 1px dashed rgba(#000, .1);
-}
-.listItem:last-child{
-  border-bottom: 0;
-}
-.itemRow{
-  position: relative;
-  padding-left: 20px;
-  &::after{
-    content: '';
-    position: absolute;
-    left: 2px;
-    top: 50%;
-    margin-top: -3px;
-    width: 6px;
-    height: 6px;
-    border-radius: 10px;
-    background-color: var(--color-primary-dark);
-  }
-}

+ 0 - 64
src/pages/chat-history/index.tsx

@@ -1,64 +0,0 @@
-import { View, Image, Text } from "@tarojs/components";
-import Taro, { useDidShow } from "@tarojs/taro";
-import NavBarNormal from "@/components/nav-bar-normal/index";
-import { getChatRecords } from '@/service/stats'
-import { useState } from "react";
-import { TEntityChatSessionRecord } from '@/types/index'
-import IconPeople from '@/images/icon-people.png'
-import PageCustom from '@/components/page-custom/index'
-import { formatDateFull} from '@/utils/index'
-import style from './index.module.less'
-
-
-export default () => {
-  const $instance = Taro.getCurrentInstance();
-  const sessionId = $instance.router?.params?.sessionId;
-  const createAt = $instance.router?.params?.createAt;
-  const num = $instance.router?.params?.num;
-  const characterName = $instance.router?.params?.characterName;
-  const [list, setList] = useState<TEntityChatSessionRecord[]|[]>([])
-  const fetchData = async (sessionId: string)=> {
-    const res = await getChatRecords(sessionId)
-    if(res?.data){
-      setList(res.data)
-    }
-  }
-  useDidShow(()=> {
-    sessionId && fetchData(sessionId)
-  })
-  return (
-    <PageCustom>
-      <NavBarNormal>
-          <Text>聊天记录</Text>
-      </NavBarNormal>
-      
-      <View className={style.page}>
-        <View className={style.container}>
-          <View className={style.summary}>
-            <Image src={IconPeople} className="w-28 h-28 rounded-6"></Image>
-            <View className="flex black-light text-12">
-              <View className={style.turnRow}>
-                <View className={style.turnNum}>{num}</View>
-                <View className={style.turnText}>轮</View>
-              </View>
-            </View>
-            <View className="flex items-center mt-4">
-              <View className={style.datetime}>{createAt && formatDateFull(new Date(createAt))}</View>  
-              <View className={style.userName}>{characterName}</View>
-            </View>
-          </View>
-          
-          <View className="mt-16">
-            {list && list.map((item:TEntityChatSessionRecord) => {
-              return <View className={style.listItem}>
-                  <View className={style.itemRow}>
-                    <View className="text-gray-65 text-14 leading-28">{item.userMsg}</View>
-                  </View>
-                </View>
-            })}
-          </View>
-        </View>
-      </View>
-    </PageCustom>
-  );
-};

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

@@ -20,13 +20,13 @@ export default ({size='large'}:IProps) => {
         <View className="flex flex-col flex-1 gap-4">
           <View className="flex items-end gap-4">
             <View className="text-12 font-medium leading-12">{agent?.name}</View>
-            <View className="text-12 leading-12"><IconCertificateColor/></View>
+            {agent?.isEnt && <View className="text-12 leading-12"><IconCertificateColor/></View>}
           </View>
-          <View className="flex items-center gap-2">
+          {agent?.entId && <View className="flex items-center gap-2">
             <View className="text-gray-45 text-12 leading-12 truncate max-w-[180px]">
               {agent?.entName}
             </View>
-          </View>
+          </View>}
         </View>
     </>
     }
@@ -43,7 +43,7 @@ export default ({size='large'}:IProps) => {
             <View className="text-12 leading-20 truncate max-w-[188px]">
               {agent?.entName}
             </View>
-            <TagCertificated />
+            {agent?.isEnt && <TagCertificated />}
           </View>
         </View>
     </>

+ 0 - 5
src/pages/choose-contact/index.config.ts

@@ -1,5 +0,0 @@
-export default definePageConfig({
-  navigationBarTitleText: '选择展示的'+ process.env.TARO_APP_NAME_TEXT,
-  "usingComponents": {},
-  navigationStyle: 'custom',
-})

+ 0 - 3
src/pages/choose-contact/index.module.less

@@ -1,3 +0,0 @@
-.listHeight{
-  height: calc(100vh - 220px);
-}

+ 0 - 212
src/pages/choose-contact/index.tsx

@@ -1,212 +0,0 @@
-import { useEffect, useState } from "react";
-import { View, ScrollView } from "@tarojs/components";
-import Taro, { useRouter } from "@tarojs/taro";
-import style from './index.module.less'
-import ContactCard from "@/components/contact-card/index";
-import WemetaTabs from "@/components/wemeta-tabs/index";
-import WemetaRadio from "@/components/wemeta-radio/index";
-import NavBarNormal from '@/components/nav-bar-normal/index'
-import PageCustom from '@/components/page-custom'
-import { useCharacterStore } from "@/store/characterStore";
-import { usePageStore } from "@/store/pageStore";
-import { IContactModel, ICharacter } from "@/types/index";
-import { getContactList } from "@/service/contact";
-import { APP_NAME_TEXT } from '@/config'
-
-
-export default function Index() {
-  const router = useRouter();
-  const { profileId } = router.params;
-  const { fetchCharacterList } = useCharacterStore();
-  let {setTmpPicked, setPicked} = usePageStore();
-  // 未点击确定前按钮前临时选中的卡片
-  let tmpPicked = usePageStore((state)=> state.tmpPicked);
-  // 已选中的卡片
-  let picked = usePageStore((state)=> state.picked);
-  const characters = useCharacterStore((state) => state.characters);
-  
-  // 自己的卡片
-  const [myCardList, setMyCardList] = useState<ICharacter[]>([]);
-  // 联系人中的卡片
-  const [contactList, setContactList] = useState<IContactModel[]>([])
-  
-  const fetchContactList = async () => {
-    const res = await getContactList({ page: 1, pageSize: 50 });
-    if (res.code === 0 && res.data) {
-      // 将与临时选中的卡片选中状态同步到获取下来的卡片数据上
-      const list = res.data.map(item => {
-        return {
-          ...item,
-          checked: tmpPicked.findIndex(pickedItem=> {
-            return pickedItem.contactProfileId === item.contactProfileId 
-          }) > -1,
-        }
-      })
-      setContactList(list);
-    }
-  };
-
-  const handleCheck = (character: ICharacter,)=> {
-    const newList = myCardList.map((item)=> {
-      if(item.profileId === character.profileId){
-        return {
-          ...item,
-          checked: !item.checked
-        }  
-      }
-      return {
-        ...item,
-      }
-    })
-    setMyCardList(newList)
-    // 如果是取消选中,则临时选中列表中去掉
-    if(character.checked){
-      setTmpPicked(tmpPicked.filter(item=> item.contactProfileId !== character.profileId))
-      return
-    }
-    // 如果是选中新的,则添加到临时选中的数组中
-    const newContact = {
-      avatar: character.avatar,
-      badges: character.badges,
-      company: character.company,
-      contactProfileId: character.profileId,
-      createdAt: character.createdAt,
-      job: character.job,
-      name: character.name,
-      checked: true
-    }
-    setTmpPicked([...tmpPicked, newContact])
-  }
-
-  const handleContactCheck = (contact: IContactModel)=> {
-    const newList = contactList.map((item)=> {
-      if(item.contactProfileId === contact.contactProfileId){
-        return {
-          ...item,
-          checked: !item.checked
-        }  
-      }
-      return {
-        ...item,
-      }
-    })
-    setContactList(newList)
-    
-    if(contact.checked){
-      setTmpPicked(tmpPicked.filter(item=> item.contactProfileId !== contact.contactProfileId))
-      return
-    }
-    const newContact = {
-      ...contact,
-      checked: true
-    }
-    setTmpPicked([...tmpPicked, newContact])
-  }
-
-
-  const handleSave = () => {
-    setPicked([...tmpPicked])
-    Taro.navigateBack();
-  };
-
-  // 渲染自己的卡片列表
-  const renderMyCards = () => {
-    return (
-      <View>
-      <ScrollView
-      scroll-y
-      className={style.listHeight}
-      >
-        <View className="flex flex-col gap-8 p-20">
-          {myCardList.map((item) => {
-            return (
-              <ContactCard key={item.profileId} data={item} onClick={()=> handleCheck(item)} renderRight={()=> {
-                return <WemetaRadio checkbox checked={item.checked}></WemetaRadio>
-              }}></ContactCard>
-            );
-          })}
-        </View>
-      </ScrollView>
-        <View className="px-20" onClick={()=> handleSave()}>
-          <View className="button-rounded-big">确认添加</View>  
-        </View>
-      </View>
-    );
-  };
-
-  // 渲染联系人列表
-  const renderContactCards = () => {
-    return (
-      <View>
-        <ScrollView
-      scroll-y
-      className={style.listHeight}
-      >
-      <View className="flex flex-col gap-8 p-20">
-        {contactList.map((item) => {
-          return (
-            <ContactCard key={item.profileId} data={item} onClick={()=> handleContactCheck(item)} renderRight={()=> {
-              return <WemetaRadio checkbox checked={item.checked}></WemetaRadio>
-            }}></ContactCard>
-          );
-        })}
-      </View>
-      </ScrollView>
-        <View className="px-20" onClick={()=> handleSave()}>
-          <View className="button-rounded-big">确认添加</View>  
-        </View>
-      </View>
-    )
-  }
-  
-  const tabList = [
-    {
-      key: "1",
-      label: "我创建的",
-      children: renderMyCards(),
-    },
-    {
-      key: "2",
-      label: "我的联系人",
-      children: renderContactCards(),
-    },
-  ];
-
-  
-
-
-  const initPage =  () => {
-    setTmpPicked([...picked])
-    fetchCharacterList();
-    fetchContactList();
-  }
-  useEffect(()=> {
-    
-    setMyCardList(characters.map((item)=> {
-      return {
-        ...item,
-        checked: tmpPicked.findIndex(pickedItem=> pickedItem.contactProfileId === item.profileId) > -1,
-      }
-    }))
-  }, [characters])
-
-  useEffect(() => {
-    if (profileId) {
-      initPage()
-    }
-  }, []);
-
-  return (
-    <PageCustom>
-      <NavBarNormal>{`选择展示的${APP_NAME_TEXT}`}</NavBarNormal>
-      <View className="w-full">
-        <WemetaTabs
-          full
-          list={tabList}
-          current="1"
-          tabStyle="outline"
-        ></WemetaTabs>  
-      </View>
-    </PageCustom>
-  );
-}

+ 0 - 4
src/pages/contact/index.tsx

@@ -18,10 +18,6 @@ export default function Index() {
 
   const fetcher = async ([_url, nextId, page, pageSize, _keyword]) => {
     let keyword = _keyword
-    // if(_keyword !== undefined){
-    //   keyword = decodeURIComponent(_keyword)
-    //   console.log(keyword,1111)
-    // }
     const res = await getContactList({ startId: nextId, pageSize, keyword });
     return res.data;
   };

+ 0 - 5
src/pages/editor-pages/editor-company/index.config.ts

@@ -1,5 +0,0 @@
-export default definePageConfig({
-  navigationBarTitleText: '章节标题',
-  "usingComponents": {},
-  navigationStyle: 'custom'
-})

+ 0 - 2
src/pages/editor-pages/editor-company/index.module.less

@@ -1,2 +0,0 @@
-
-

+ 0 - 79
src/pages/editor-pages/editor-company/index.tsx

@@ -1,79 +0,0 @@
-import { useState } from "react";
-import { View } from "@tarojs/components";
-
-import PageCustom from "@/components/page-custom/index";
-import NavBarNormal from "@/components/nav-bar-normal/index";
-import editorStyle from "../editor.module.less";
-import WemetaRadioGroup from "@/components/wemeta-radio-group/index";
-import { useComponentStore } from '@/store/componentStore'
-import { useCharacterStore } from '@/store/characterStore'
-import WemetaTextarea from "@/components/wemeta-textarea/index";
-import Taro, {useRouter, useUnload} from "@tarojs/taro";
-export default function Index() {
-  const router = useRouter();
-  const { id } = router.params;
-  const deltaNum = id ? 1 : 2
-  let currentComponent = useComponentStore((state)=>  state.currentComponent);
-  const character = useCharacterStore((state)=> state.character);
-  const loading = useComponentStore((state)=> state.loading);
-  const { saveComponent } = useComponentStore();
-  const [value, setValue] = useState(currentComponent?.data?.text ?? '');
-  
-  const handleSave = async () => {
-    if(loading){
-      return
-    }
-    if(value.length <= 0){
-      return;
-    }
-    // const c = {
-    //   data: {
-    //     text: value,
-    //     layout: radioValue,
-    //   },
-    //   enabled: currentComponent?.enabled ?? true,
-    //   id: currentComponent?.id,
-    //   name: currentComponent?.name ?? "姓名",
-    //   index: currentComponent?.index,
-    //   characterProfileId: currentComponent?.characterProfileId ?? character?.profileId,
-    //   type: "title",
-    // };
-
-    
-    // await saveComponent(c)
-  };
-
-  const onChange = (e: any) => {
-    setValue(e);
-  };
-  
-
-  
-
-  const handleNavBack = async () => {
-    await handleSave()
-  }
-  
-  
-
-  return (
-    <PageCustom>
-      <NavBarNormal backText="企业"></NavBarNormal>
-      <View className="flex flex-col items-center w-full">
-        <View className={editorStyle.container}>
-          <View
-            className={`${editorStyle.textInputContainer} ${editorStyle.underline}`}
-          >
-            <WemetaTextarea
-              value={value}
-              onBlur={(value: string) => onChange(value)}
-              onInput={(value: string) => onChange(value)}
-              placeholder="填写企业名称"
-              autoFocus
-            />
-          </View>
-        </View>
-      </View>
-    </PageCustom>
-  );
-}

+ 0 - 5
src/pages/editor-pages/editor-position/index.config.ts

@@ -1,5 +0,0 @@
-export default definePageConfig({
-  navigationBarTitleText: '章节标题',
-  "usingComponents": {},
-  navigationStyle: 'custom'
-})

+ 0 - 2
src/pages/editor-pages/editor-position/index.module.less

@@ -1,2 +0,0 @@
-
-

+ 0 - 79
src/pages/editor-pages/editor-position/index.tsx

@@ -1,79 +0,0 @@
-import { useState } from "react";
-import { View } from "@tarojs/components";
-
-import PageCustom from "@/components/page-custom/index";
-import NavBarNormal from "@/components/nav-bar-normal/index";
-import editorStyle from "../editor.module.less";
-import WemetaRadioGroup from "@/components/wemeta-radio-group/index";
-import { useComponentStore } from '@/store/componentStore'
-import { useCharacterStore } from '@/store/characterStore'
-import WemetaTextarea from "@/components/wemeta-textarea/index";
-import Taro, {useRouter, useUnload} from "@tarojs/taro";
-export default function Index() {
-  const router = useRouter();
-  const { id } = router.params;
-  const deltaNum = id ? 1 : 2
-  let currentComponent = useComponentStore((state)=>  state.currentComponent);
-  const character = useCharacterStore((state)=> state.character);
-  const loading = useComponentStore((state)=> state.loading);
-  const { saveComponent } = useComponentStore();
-  const [value, setValue] = useState(currentComponent?.data?.text ?? '');
-  
-  const handleSave = async () => {
-    if(loading){
-      return
-    }
-    if(value.length <= 0){
-      return;
-    }
-    // const c = {
-    //   data: {
-    //     text: value,
-    //     layout: radioValue,
-    //   },
-    //   enabled: currentComponent?.enabled ?? true,
-    //   id: currentComponent?.id,
-    //   name: currentComponent?.name ?? "姓名",
-    //   index: currentComponent?.index,
-    //   characterProfileId: currentComponent?.characterProfileId ?? character?.profileId,
-    //   type: "title",
-    // };
-
-    
-    // await saveComponent(c)
-  };
-
-  const onChange = (e: any) => {
-    setValue(e);
-  };
-  
-
-  
-
-  const handleNavBack = async () => {
-    await handleSave()
-  }
-  
-  
-
-  return (
-    <PageCustom>
-      <NavBarNormal backText="职位"></NavBarNormal>
-      <View className="flex flex-col items-center w-full">
-        <View className={editorStyle.container}>
-          <View
-            className={`${editorStyle.textInputContainer} ${editorStyle.underline}`}
-          >
-            <WemetaTextarea
-              value={value}
-              onBlur={(value: string) => onChange(value)}
-              onInput={(value: string) => onChange(value)}
-              placeholder="填写职位名称"
-              autoFocus
-            />
-          </View>
-        </View>
-      </View>
-    </PageCustom>
-  );
-}

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

@@ -1,7 +1,7 @@
 .navButtons{
   display: flex;
   align-items: center;
-  padding: 4px 13px 4px 19px;
+  padding: 4px 14px 4px 14px;
   border-radius: 25px;
   border: 1px solid rgba(151,151,151, 0.2);
   background-color: rgba(255, 255, 255, 0.6);

+ 61 - 30
src/pages/profile/index.tsx

@@ -2,39 +2,81 @@ import PageCustom from "@/components/page-custom/index";
 import { View, Image } from "@tarojs/components";
 import { useEffect, useState } from "react";
 import ComponentList from "@/components/component-list";
-import { TAgentDetail } from "@/types/agent";
+
 import NavBarNormal from "@/components/nav-bar-normal/index";
-import { getAgent, postVisitorLog } from "@/service/agent";
-import Taro, { useRouter } from "@tarojs/taro";
-import { getLoginId, isSuccess } from "@/utils";
+import Taro, { getCurrentPages, useRouter } from "@tarojs/taro";
+import { isSuccess } from "@/utils";
 
 import IconArrowLeft from "@/components/icon/icon-arrow-left";
 import IconHomeOutline from "@/components/icon/IconHomeOutline";
 import SummaryBar from "@/components/AgentPage/components/SummaryBar";
 import { useAgentStore } from "@/store/agentStore";
 import style from "./index.module.less";
+import { sceneUnzip } from "@/service/wechat";
+import { postLog } from "./profile";
 
-export default function Index() {
+export default function Profile() {
   const { agent, fetchAgent } = useAgentStore();
-  const router = useRouter();
-  const { agentId, shareKey } = router.params;
+  const params = useRouter().params;
 
-  if (!agentId) {
-    return <View>loading...</View>;
-  }
+  // 解码
+  const decodeSceneValue = async (sceneValue: string) => {
+    const response = await sceneUnzip(sceneValue);
+    if (isSuccess(response.status)) {
+      try {
+        const originalScene = JSON.parse(response.data.originalScene) as {
+          shareKey?: string;
+          agentId?: string;
+        };
+        if (originalScene.agentId) {
+          console.log(originalScene,111)
+          fetchAgent(originalScene.agentId);
+          postLog(originalScene.agentId, originalScene.shareKey ?? "");
+        }
+      } catch (e) {
+        Taro.showToast({
+          title: "没有对应的知能体",
+          icon: "error",
+        });
+      }
+    }
+  };
+  console.log(params.scene, 1111);
+  // 通过小程序码识别打开的页面
+  useEffect(()=> {
+    const scene = decodeURIComponent(params.scene ?? "");
+    if (scene.length <= 32 && scene.length > 0) {
+      // 有值,且小于 32 位,说明需要解码
+      // 判断是否需要解压 shareKey
+      decodeSceneValue(scene);
+    }
+  }, [])
+
+  // 正常分享出来的页面
+  useEffect(() => {
+    if (params.agentId) {
+      fetchAgent(params.agentId);
+      postLog(params.agentId, params.shareKey);
+    }
+  }, [params.agentId]);
 
   const renderNavBarLeft = () => {
+    const pages = getCurrentPages();
     return (
       <View className={style.navButtons}>
-        <View
-          className="flex-center"
-          onClick={() => {
-            Taro.navigateBack();
-          }}
-        >
-          <IconArrowLeft></IconArrowLeft>
-        </View>
-        <View className={style.navGapLine}></View>
+        {pages.length > 2 && (
+          <>
+            <View
+              className="flex-center"
+              onClick={() => {
+                Taro.navigateBack();
+              }}
+            >
+              <IconArrowLeft></IconArrowLeft>
+            </View>
+            <View className={style.navGapLine}></View>
+          </>
+        )}
         <View
           className="flex-center"
           onClick={() => {
@@ -49,17 +91,6 @@ export default function Index() {
     );
   };
 
-  useEffect(() => {
-    fetchAgent(agentId);
-  }, [agentId]);
-
-  useEffect(() => {
-    if (agentId) {
-      const loginId = getLoginId();
-      postVisitorLog({ agentId, loginId, shareKey: shareKey ?? '' });
-    }
-  }, [agentId]);
-
   return (
     <PageCustom>
       <View className="w-full">

+ 6 - 0
src/pages/profile/profile.ts

@@ -0,0 +1,6 @@
+import { postVisitorLog } from "@/service/agent";
+import { getLoginId, isSuccess } from "@/utils";
+export const postLog = (agentId: string, shareKey?: string) => {
+  const loginId = getLoginId();
+  postVisitorLog({ agentId: agentId, loginId, shareKey: shareKey ?? '' });
+}

+ 1 - 13
src/pages/test/index.tsx

@@ -1,19 +1,7 @@
-// import ChatAI from "@/components/chat-ai/index";
-// import ComponentList from "@/components/component-list";
+
 import NavBarNormal from "@/components/nav-bar-normal/index";
 import { View } from "@tarojs/components";
 import PageCustom from "@/components/page-custom/index";
-// import IconEditOutline from "@/images/icon-edit-outline.png";
-// import { useAppStore } from "@/store/appStore";
-// import { useCharacterStore, useCurrentCharacter, useCharacterStyle } from "@/store/characterStore";
-// import { useComponentStore } from "@/store/componentStore";
-// import { uploadImage } from "@/utils/http";
-
-// import CustomShareComponent from "@/components/custom-share/CustomShareComponent";
-// import { Button, Image, Input, View, Video } from "@tarojs/components";
-// import Taro, { useDidShow, useRouter, useUnload } from "@tarojs/taro";
-// import { useRef, useState } from "react";
-// import style from "./index.module.less";
 
 import IconVoiceColor from "@/components/icon/icon-voice-color";
 import TabBarButtons from "@/components/wemeta-tabs/TabBarButtons";

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

@@ -5,10 +5,9 @@ import { IVoicePlayerBar } from "@/components/voice-player-bar/index";
 import WemetaRadio from "@/components/wemeta-radio/index";
 import { CloneVoiceStatus } from "@/consts/enum";
 import IconWave from "@/images/icon-wave-20.png";
-import { voiceCloneConfirm } from "@/service/character";
 import { useAppStore } from "@/store/appStore";
 import { ICharacter } from "@/types";
-import { formatDateFull, getCloneVoiceIdentifier } from "@/utils/index";
+import { formatDateFull } from "@/utils/index";
 import { Image, View } from "@tarojs/components";
 import { useEffect, useRef, useState } from "react";
 import Popup from "@/components/popup/popup";

+ 4 - 2
src/service/agent.ts

@@ -67,8 +67,10 @@ export const deleteAgent = (agentId: string) => {
 
 
 // 访问某个智能体,允许不登录状态下访问
-export const getAgent = (agentId: string) =>  {
-  return request.get<TAgentDetail>(`${bluebookAiAgent}api/v1/agent/${agentId}`)
+export const getAgent = (agentId: string, shareKey?: string) =>  {
+  return request.get<TAgentDetail>(`${bluebookAiAgent}api/v1/agent/${agentId}`, {
+    params: {shareKey}
+  })
 }
 
 // 上报访客日志--间隔 N 秒调用一次

+ 0 - 287
src/service/character.ts

@@ -1,287 +0,0 @@
-import { BASE_URL } from "@/config/index";
-import type { ICharacter, TEntityVoiceCloneRecord } from "@/types/index";
-import { useAudioPlayer } from "@/utils/audio";
-import { getHeaders, service } from "@/utils/http";
-import Taro from "@tarojs/taro";
-
-import { ModelUserProfile, TModelGenQrCodeRequest } from "@/types/index";
-import { getChatSession } from "@/store/chat";
-import { TextDecoder } from "text-encoding-shim";
-import JsonChunkParser from "@/utils/jsonChunkParser";
-
-// FIXME: react hook warning, not top level
-const { playChunk, pushChunk2Quene, setFistChunk, stopPlayChunk } =
-  useAudioPlayer();
-
-export const batchGet = (profileIds: string[], config?: any) => {
-  return service.post<{ profileIds: string[] }, ICharacter[]>(
-    `/v1/character/batchGet`,
-    { profileIds },
-    config
-  );
-};
-export const getVoiceCloneHistory = (profileId: string) => {
-  return service.get<TEntityVoiceCloneRecord[]>(`/v1/audio/voiceClone`);
-};
-export const voiceCloneConfirm = (voiceName: string) => {
-  return service.post<any>(`/v1/audio/${voiceName}/confirm`);
-};
-export const listCharacter = () => {
-  return service.get<ICharacter[]>(`/v1/character`);
-};
-export const getCharacterById = (profileId: string) => {
-  return service.get<ICharacter>(`/v1/character/${profileId}`);
-};
-export const deleteCharacterById = (profileId: string) => {
-  return service.delete<null>(`/v1/character/${profileId}`);
-};
-export const getProfileById = (profileId: string) => {
-  return service.get<ModelUserProfile>(`/v1/character/${profileId}/profile`);
-};
-
-export const saveCharacter = (data: ICharacter) => {
-  return service.post<ICharacter, ICharacter>("/v1/character", data);
-};
-export type TCloneVoice = {
-  profileId: string;
-  key?: string;
-  value: string;
-};
-export const cloneVoice = (data: TCloneVoice) => {
-  return service.post<{ value: string; key?: string }, string>(
-    `/v1/audio/voiceClone`,
-    {
-      value: data.value,
-      key: data.key,
-    }
-  );
-};
-export const greeting = (profileId: string, configs?: any) => {
-  return service.post<unknown, { audio: string; session: string }>(
-    `/v1/character/${profileId}/greeting`,
-    {},
-    configs
-  );
-};
-
-const chatRequest = (
-  profileId: string,
-  session: string,
-  arrayBuffer: ArrayBuffer | string
-) => {
-  const fileContent = arrayBuffer;
-  const data = {
-    value: fileContent,
-    key: process.env.TARO_ENV == "h5" ? "wav" : "mp3",
-  };
-  let isFirstChunk = true;
-  if (process.env.TARO_ENV == "h5") {
-    fetch(`${BASE_URL}v1/character/${profileId}/chat?session=${session}`, {
-      headers: {
-        ...getHeaders(),
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify(data),
-      method: "post",
-    })
-      .then((_data) => {
-        return _data.body?.getReader();
-      })
-      .then(async (reader) => {
-        console.log("[ reader ] >", reader);
-        if (!reader) {
-          return;
-        }
-
-        // const buffers: ArrayBuffer[] = [];
-        while (true) {
-          const { done, value } = await reader.read();
-          // console.log("[ done ] >", done);
-          // console.log("[ value ] >", value);
-          if (done) break;
-          // buffers.push(value.buffer);
-          if (isFirstChunk) {
-            setFistChunk(value.buffer);
-            isFirstChunk = false;
-          } else {
-            pushChunk2Quene(value.buffer);
-          }
-          playChunk();
-        }
-        // 测试音频数据是否正确
-        // console.log("buffers", buffers.length);
-        // const blob = new Blob(buffers, { type: "audio/wav" });
-        // const audioUrl = URL.createObjectURL(blob);
-        // console.log("audioUrl", audioUrl);
-        // const a = document.createElement("a");
-        // a.href = audioUrl;
-        // a.download = "audio.wav";
-        // a.click();
-      });
-  } else {
-    const reqTask = Taro.request({
-      url: `${BASE_URL}v1/character/${profileId}/chat?session=${session}`,
-      data: data,
-      enableChunked: true,
-      method: "POST",
-      header: {
-        ...getHeaders(),
-      },
-      responseType: "arraybuffer",
-      success: function (res) {
-        console.log("服务端响应 >>", res);
-        // 如果没有识别或发生错误,则停止播放(恢复默认状态)
-        if (res.header["Content-Type"]?.indexOf("application/json") > -1) {
-          stopPlayChunk();
-        }
-      },
-    });
-    // reqTask.
-    reqTask.onChunkReceived((chunk) => {
-      // console.log(chunk)
-      if (isFirstChunk) {
-        isFirstChunk = false;
-        setFistChunk(chunk.data, reqTask);
-      } else {
-        pushChunk2Quene(chunk.data);
-      }
-      playChunk();
-    });
-    // todo: 需要返回 reqTask 用于停止发出请求
-    // reqTask.abort();
-  }
-};
-
-function arrayBufferToHex(buffer: ArrayBuffer) {
-  return Array.from(new Uint8Array(buffer))
-    .map((b) => b.toString(16).padStart(2, "0"))
-    .join("");
-}
-// 暂时将流式播放的逻辑放在此处,后期考虑移到具体文件内
-export const chat = (
-  profileId: string,
-  session: string,
-  content: string | ArrayBuffer
-) => {
-  if (content instanceof ArrayBuffer) {
-    // console.log("[ 测试 ] >", arrayBufferToHex(content));
-    chatRequest(profileId, session, arrayBufferToHex(content));
-    return;
-  }
-  const fs = Taro.getFileSystemManager();
-
-  fs.readFile({
-    filePath: content,
-    encoding: "hex", // 以二进制方式读取文件
-    success: (res) => {
-      const fileContent = res.data;
-      console.log(
-        "%c [ fileContent ]: ",
-        "color: #bf2c9f; background: pink; font-size: 13px;",
-        fileContent
-      );
-      chatRequest(profileId, session, fileContent);
-    },
-    fail: (err) => {
-      console.error("读取文件失败", err);
-    },
-  });
-};
-
-export const share = (profileId: string, platform: string) => {
-  return service.get<{
-    referralCode?: string;
-    url?: string;
-  }>(`/v1/character/${profileId}/share`, {
-    params: {
-      platform,
-    },
-  });
-};
-
-// 获取克隆声音状态
-export const getVoiceCloneStatus = (profileId: string, voiceName: string) => {
-  return service.get<TEntityVoiceCloneRecord>(
-    `/v1/character/${profileId}/voiceClone/${voiceName}`
-  );
-};
-// 获取微信小程序二维码
-export const genCharacterQrcode = (
-  profileId: string,
-  params: TModelGenQrCodeRequest
-) => {
-  return service.post<any, string>(`/v1/character/${profileId}/qrcode`, params);
-};
-
-export type TTextChatParams = {
-  profileId: string;
-  params: {
-    message?: string;
-    model?: string;
-  };
-  onStart: () => void;
-  onReceived: (m: { content: string; reasoningContent: string }) => void;
-  onFinished: () => void;
-  onError: () => void;
-};
-
-export const textChat = ({
-  profileId,
-  params,
-  onStart,
-  onReceived,
-  onFinished,
-  onError,
-}: TTextChatParams) => {
-  onStart();
-  const session = getChatSession();
-  // todo: 需要加上错误处理,当错误时清掉 onStart 中创建的 气泡框
-  if (!session) {
-    return;
-  }
-  let reqTask: Taro.RequestTask<any>;
-  const jsonParser = new JsonChunkParser();
-  jsonParser.onParseComplete((m) => {
-    console.log("okok", m);
-    onFinished();
-  });
-  const onChunkReceived = (chunk: any) => {
-    // console.log(chunk);
-    const uint8Array = new Uint8Array(chunk.data);
-    var string = new TextDecoder("utf-8").decode(uint8Array);
-    // console.log(string);
-    jsonParser.parseChunk(string, (m) => {
-      // console.log(m);
-      onReceived(m);
-    });
-  };
-  try {
-    reqTask = Taro.request({
-      url: `${BASE_URL}v1/character/${profileId}/textChat?session=${session}`,
-      data: params,
-      enableChunked: true,
-      method: "POST",
-      header: {
-        ...getHeaders(),
-      },
-      responseType: "arraybuffer",
-      success: function (res) {
-        console.log("服务端响应 >>", res);
-        // 如果没有识别或发生错误,则停止播放(恢复默认状态)
-        if (res.header["Content-Type"]?.indexOf("application/json") > -1) {
-        }
-      },
-    });
-
-    // reqTask.
-    reqTask.onChunkReceived(onChunkReceived);
-  } catch (e) {
-    onError();
-  }
-
-  const stopChunk = () => {
-    reqTask.offChunkReceived(onChunkReceived);
-  };
-
-  return stopChunk;
-};

+ 0 - 12
src/service/stats.ts

@@ -1,12 +0,0 @@
-import service from '@/xiaolanbenlib/module/axios'
-import { TWeeklyChatStatistics, TEntityChatSession, IPageParams, TEntityChatSessionRecord } from '@/types/index'
-
-export const getWeeklyStats = () => {
-  return service.get<TWeeklyChatStatistics>('/v1/stats/weekly')
-}
-export const getChatHistories = (data: IPageParams) => {
-  return service.get<TEntityChatSession[]>('/v1/stats/chat/histories', {params: data})
-}
-export const getChatRecords = (sessionId: string) => {
-  return service.get<TEntityChatSessionRecord[]>(`/v1/stats/chat/${sessionId}/records`)
-}

+ 53 - 0
src/service/wechat.ts

@@ -0,0 +1,53 @@
+// 我的音色库&形象库
+import {
+  bluebookAiAgent,
+} from '@/xiaolanbenlib/api/index'
+import request from '@/xiaolanbenlib/module/axios.js'
+
+
+
+
+// 获取scene原始参数--无需校验权限{'originalScene':'xxx'}
+export const sceneUnzip = (shortScene: string) => {
+  return request.get<{originalScene: string}>(`${bluebookAiAgent}api/v1/wechat/xcx/scene/unzip`, {
+    params: {shortScene}
+  })
+}
+// 获取分享二维码时的scene参数{'shortScene':'xxxx'}
+export const sceneZip = (originalScene: string) => {
+  return request.get<{shortScene: string}>(`${bluebookAiAgent}api/v1/wechat/xcx/scene/zip`, {
+    params: {originalScene}
+  })
+}
+
+// 获取小程序分享二维码{'imgUrl':'http:xxx'}
+/**
+ * 
+auto_color (boolean, optional): 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false ,
+check_path (boolean, optional): 默认是true,检查page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错);为 false 时允许小程序未发布或者 page 不存在, 但page 有数量上限(60000个)请勿滥用。 ,
+env_version (string, optional): 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。 ,
+is_hyaline (boolean, optional): 默认是false,是否需要透明底色,为 true 时,生成透明底色的小程序 ,
+line_color (object, optional): 默认是{"r":0,"g":0,"b":0} 。auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":xxx,"g":xxx,"b":xxx} 十进制表示 ,
+page (string, optional): 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 ,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置 ,
+scene (string, optional): 必须 如果该参数太长,请使用压缩url 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) ,
+width (integer, optional): 默认430,二维码的宽度,单位 px,最小 280px,最大 1280px
+ * @returns 
+ */
+export const genWechatQrcode = (data: {
+  auto_color?: boolean,
+  check_path?: boolean,
+  env_version?: 'release'|'trial'|'develop',
+  is_hyaline?: boolean,
+  line_color?: {r:number, g:number, b: number},
+  page?: string,
+  scene: string,
+  width ?: number
+}, imageType: 'image'|'base64' = 'image') => {
+  return request.post<{
+    imgBase64: string|null
+    imgUrl: string|null
+    contentType: string|null //"image/jpeg" "image/png"
+  }>(`${bluebookAiAgent}api/v1/wechat/xcx/share/qrimg`, data, {
+    params: {imageType: imageType}
+  })
+}

+ 4 - 3
src/store/agentStore.ts

@@ -67,12 +67,12 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
 
     return [];
   },
-  fetchAgent: async (agentId: string) => {
+  fetchAgent: async (agentId: string, shareKey?:string) => {
     const { agents } = get()
     // 如果自己的智能体列表中有 对应的 agentId,则请求自己的 agent, 否则请求无需登录的 getAgent 接口
     const isSelf = !!agents.find((item)=> item.agentId === agentId)
     const req = isSelf ? _getMyAgent : _getAgent; 
-    const response = await req(agentId);
+    const response = await req(agentId, shareKey);
     const result = isSuccess(response.status)
     if (result && response.data) {
       const agent = response.data;
@@ -131,11 +131,12 @@ export const useAgentStore = create<AgentStoreState>((set, get) => ({
     }
     return null;
   },
+  // 编辑声音,人设,开场白,问题引导,知识库
   editAgentCharacter: async (agentId: string, data: TEditAgentCharacter) => {
-    // const filteredObj = pickNonEmpty(data);
     const response = await _editAgentCharacter(agentId, data);
     console.log(response.data);
     const result = isSuccess(response.status)
+    //@ts-ignore
     set((state) => {
       return {
         agent: {

+ 0 - 178
src/store/characterStore.ts

@@ -1,178 +0,0 @@
-import { create } from 'zustand'
-import {
-  getCharacterById as _getCharacterById,
-  getProfileById as _getProfileById,
-  listCharacter, saveCharacter,
-  cloneVoice as _cloneVoice,
-  // greeting as _greeting,
-  deleteCharacterById as _deleteCharacterById,
-  getVoiceCloneHistory,
-} from '@/service/character'
-import { ICharacter, TEntityComponent, ModelUserProfile, TEntityVoiceCloneRecord } from '@/types/index'
-
-type TCreateCharacterParams = Omit<ICharacter, 'profileId'> & { profileId?: string };
-// 混入自定义样式进 character
-const mixinCustomStylesToCharacter = (character: ICharacter) => {
-  const customStyled = character?.bgColor ? `
-    --color-bg-primary: ${character.bgColor};
-    --color-primary: ${character.bgColor};
-    ` : `
-      --color-bg-primary: ;
-      --color-primary: ;
-    `
-  const customBgImg = character?.bgImg ?? ''
-  character = { ...character, customStyled, customBgImg }
-  return character
-}
-
-export interface CharacterStoreState {
-  character: ICharacter | null
-  characters: ICharacter[]
-  voiceList: TEntityVoiceCloneRecord[]
-  components: TEntityComponent[]
-  fetchVoiceCloneHistory: (profileId: string) => Promise<TEntityVoiceCloneRecord[]>
-  fetchCharacterList: () => Promise<ICharacter[] | null>
-  fetchCharacter: (profileId: string) => Promise<void>
-  saveCharacter: (c: TCreateCharacterParams) => Promise<{
-    code: number;
-    data: ICharacter;
-    msg: string;
-  } | null>
-  getProfileById: (profileId: string) => Promise<{
-    code: number;
-    data: ModelUserProfile;
-    msg: string;
-  }>
-  deleteCharacterById: (profileId: string) => Promise<null>
-  getCharacterById: (profileId: string) => Promise<ICharacter | null>
-  setCurrentCharacter: (character: ICharacter | null) => void
-  cloneVoice: (fileLink: string, key?: string) => Promise<{ code: number; data: string; msg: string; } | undefined>
-  // greeting: (profileId:string, configs: any) => Promise<{ audio: string, session: number } | null>
-}
-
-export const useCharacterStore = create<CharacterStoreState>((set, get) => ({
-  character: null, // 当前角色信息
-  characters: [],
-  voiceList: [], // 克隆列表
-  components: [], // 用户组件列表
-  fetchVoiceCloneHistory: async (profileId: string) => {
-    const response = await getVoiceCloneHistory(profileId)
-    if (response.code === 0) {
-      set({ voiceList: response.data })
-      return response.data
-    }
-    return []
-  },
-  fetchCharacterList: async () => {
-    const response = await listCharacter()
-    console.log(response?.data)
-    if (response.code === 0) {
-      const characters = response.data.map((item) => {
-        if (item.profileID) {
-          return {
-            ...item,
-            profileId: item.profileID
-          }
-        }
-        const character = mixinCustomStylesToCharacter(item)
-        return character
-      })
-      set({ characters: characters })
-      return characters;
-    }
-    return null
-  },
-  fetchCharacter: async (profileId: string) => {
-    get().getCharacterById(profileId)
-  },
-  // 保存角色信息, 需要修改什么字段就传什么字段
-  saveCharacter: async (c:TCreateCharacterParams) => {
-    const response = await saveCharacter(c as ICharacter)
-    console.log(response)
-    if (response.code !== 0 || !response.data) {
-      return null
-    }
-    const character = mixinCustomStylesToCharacter(response.data)
-    get().setCurrentCharacter(character)
-    return response
-  },
-  addCharacter: async (c: ICharacter) => {
-    const character = mixinCustomStylesToCharacter(c)
-    set((state) => {
-      return {
-        characters: [...state.characters, character]
-      }
-    })
-  },
-  getProfileById: async (profileId: string) => {
-    const res = await _getProfileById(profileId)
-    if (res.code === 0 && res.data) {
-      const character = mixinCustomStylesToCharacter(res.data.character)
-      set({ character })
-      return res
-    }
-    return res;
-  },
-  getCharacterById: async (profileId: string) => {
-    const res = await _getCharacterById(profileId)
-    if (res.code === 0 && res.data) {
-      const character = mixinCustomStylesToCharacter(res.data)
-      set({ character })
-      return character
-    }
-    return null;
-
-  },
-  deleteCharacterById: async (profileId: string) => {
-    const res = await _deleteCharacterById(profileId)
-    if (res.code === 0) {
-      get().fetchCharacterList()
-    }
-    return res.data
-  },
-  setCurrentCharacter: (character: ICharacter | null) => {
-    // console.log('set current character:', character)
-    set({ character })
-  },
-  cloneVoice: async (fileLink: string, key?: string) => {
-    const profileId = get().character?.profileId;
-    if (!profileId) {
-      return
-    }
-    return await _cloneVoice({
-      profileId,
-      value: fileLink,
-      key,
-    })
-  },
-  // greeting: async (profileId, configs: any) => {
-  //   if (!profileId) {
-  //     return null
-  //   }
-  //   const res = await _greeting(profileId, configs)
-  //   if (res.code === 0) {
-  //     return res.data
-  //   }
-  //   return null
-  // }
-}))
-
-export const useCurrentCharacter = () => {
-  return useCharacterStore((state) => state.character);
-}
-
-export const useCharacterStyle = () => {
-  const character = useCharacterStore((state) => state.character);
-  const customStyled = character?.bgColor ? `
-    --color-bg-primary: ${character.bgColor};
-    --color-primary: ${character.bgColor};
-    ` : `
-      --color-bg-primary: ;
-      --color-primary: ;
-    `
-  // 没有自定义颜色时,也需要写 --var 清除一下
-  return {
-    customStyled,
-    customBgImg: character?.bgImg ?? ''
-  }
-}

+ 0 - 66
src/utils/auth.ts

@@ -1,72 +1,6 @@
 import Taro from "@tarojs/taro";
-import axios from './http'
 import { getToken, setToken } from '@/utils/index'
 
-// import { authBind } from "@/service/auth";
-// import { EBindKind } from "@/consts/enum";
-
-// let isLogining = false;
-
-
-const authLoginH5 = async (resolve) => {
-	const BrowserID = await require("browser-id");
-	const fingerprint = BrowserID()
-	console.log("figerprint", fingerprint)
-	//发起网络请求
-	const result = await axios.get<unknown, { code: number, data: string }>('/v1/auth/browser/oauthLogin', { params: { code: fingerprint, referralCode } })
-	if (result?.code === 0) {
-		setToken(result.data)
-		resolve(true)
-		return
-	}
-	resolve(false)
-	return;
-}
-
-export const authLogin = (): Promise<boolean> => {
-	const launchOptions = Taro.getLaunchOptionsSync()
-	// 如果有 referralCode 参数,则说明是通过分享的方式进入小程序,则需要获取 referralCode 参数
-	const referralCode = launchOptions.query?.referralCode
-	return new Promise(async (resolve, reject) => {
-		const token = getToken()
-		if (token) {
-			resolve(true)
-			return;
-		}
-		if (isLogining) {
-			return 
-		}
-		isLogining = true;
-		if (process.env.TARO_ENV == "h5") {
-			await authLoginH5(resolve)
-			isLogining = false;
-			return;
-		}
-
-		Taro.login({
-			complete(){
-				isLogining = false;	
-			},
-			async success(res) {
-				console.log(res);
-				if (res.code) {
-					//发起网络请求
-					const result = await axios.get<unknown, { code: number, data: string }>('/v1/auth/wechat/oauthLogin', { params: { code: res.code, ref: referralCode } })
-					if (result?.code === 0) {
-						setToken(result.data)
-						resolve(true)
-					}
-				} else {
-					console.log('登录失败!' + res.errMsg)
-					reject(false)
-				}
-			}, fail(res) {
-				console.log('登录失败!' + res.errMsg)
-				reject(false)
-			}
-		})
-	})
-}
 
 // 用户未授权
 export const showAuthModal = (content: string) => {

+ 1 - 1
src/utils/index.ts

@@ -5,7 +5,7 @@ import {
   ENABLE_UPGRADE_VIP,
 } from "@/config/index";
 import {LOGIN_ID_STORAGE_KEY } from '@/xiaolanbenlib/constant'
-import { share } from "@/service/character";
+
 import Taro, { FileSystemManager } from "@tarojs/taro";
 import { useRef, useCallback } from "react";
 

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů