فهرست منبع

修改一些小问题

masoft 2 ماه پیش
والد
کامیت
eba7e583d6

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
web/public/sw.js


+ 27 - 1
web/src/api/client.ts

@@ -9,6 +9,7 @@ import {
     UserLoginParams,
     UserLoginResult,
     UserPasswordParams,
+    UserInfoParams,
     UserInfoResult,
     UserBalanceResult,
     ChatSubmitParams,
@@ -16,7 +17,9 @@ import {
     ChatMessageParams,
     ChatMessageResult,
     ChatSessionParams,
-    ChatSessionResult
+    ChatSessionResult,
+    ChatSessionDeleteParams,
+    ChatSessionRenameParams
 } from '@/utils/clientsApis';
 import {Result} from '@/utils/result';
 
@@ -61,6 +64,14 @@ export const userPassword = (params: UserPasswordParams) => {
 };
 
 /**
+ * 前台用户修改个人信息
+ */
+export const updateUserInfo = (params: UserInfoParams) => {
+    const fetchService = useFetch();
+    return fetchService.post('/gpts/user/update', { body: params });
+};
+
+/**
  * 查看用户信息
  */
 export const getUserInfo = (): Promise<Result<UserInfoResult>> => {
@@ -100,3 +111,18 @@ export const getChatSession = (params: ChatSessionParams) : Promise<Result<PageM
     return fetchService.post('/gpts/chat/session', { body: params });
 };
 
+/**
+ * 聊天会话删除
+ */
+export const deleteChatSession = (params: ChatSessionDeleteParams): Promise<Result<null>> => {
+    const fetchService = useFetch();
+    return fetchService.post('/gpts/chat/session/delete', { body: params });
+};
+
+/**
+ * 聊天会话重命名
+ */
+export const renameChatSession = (params: ChatSessionRenameParams): Promise<Result<null>> => {
+    const fetchService = useFetch();
+    return fetchService.post('/gpts/chat/session/rename', { body: params });
+};

+ 162 - 51
web/src/app/dialogue/page.tsx

@@ -1,9 +1,9 @@
 "use client";
-import { getApiUrl } from "@/utils/common";
+import { getApiUrl, isMobile } from "@/utils/common";
 import { getUserSession } from "@/utils/user";
 import { useState, useEffect } from "react";
 import type { PopconfirmProps } from "antd";
-import { theme, Popconfirm } from "antd";
+import { theme, Popconfirm, Button, Card, Result } from "antd";
 import { ThemeProvider, css, cx } from "antd-style";
 import { useTheme } from "next-themes";
 import { ProChat, ProChatInstance } from "@ant-design/pro-chat";
@@ -16,12 +16,15 @@ import {
   RiDeleteBinLine,
   RiCloseFill,
   RiArrowDropRightLine,
+  RiDraftLine,
 } from "react-icons/ri";
 import {
   getChatSession,
   getChatMessage,
   getEmployeeDetail,
   getUserBalance,
+  deleteChatSession,
+  renameChatSession,
 } from "@/api/client";
 import { ChatSessionResult, EmployeeSearchResult } from "@/utils/clientsApis";
 
@@ -42,7 +45,7 @@ import {
   Storage_getConversationId,
 } from "@/utils/chat";
 import { useGlobalContext } from "@/providers/GlobalProvider";
-import VipPage from "@/app/vip/page";
+import VipBoxPage from "@/app/vip-box/page";
 
 export default function Dialogue() {
   const themeBig = useTheme();
@@ -57,12 +60,14 @@ export default function Dialogue() {
 
   const [chatAiModelList, setChatAiModelList] = useState<ChatAiModel[]>([]);
   const [chatSessionLastId, setChatSessionLastId] = useState<string>("");
+  const [chatSessionRenameId, setChatSessionRenameId] = useState<string>("");
   const [chatSessionList, setChatSessionList] = useState<ChatSessionResult[]>(
     []
   );
   const [showVip, setShowVip] = useState(false);
   const [showLeftBox, setShowLeftBox] = useState(false);
   const [balance, setBalance] = useState<number>(0);
+  const [rename, setRename] = useState<string>("");
 
   //历史记录和智能体列表 显示隐藏
   const handlShowLeftLetter = () => {
@@ -133,21 +138,22 @@ export default function Dialogue() {
   //新对话
   const newChat = () => {
     var newConversationId = "guid_0000_" + new Date().getTime();
-    setChatSessionList((chatSessionList) => [
-      ...[
-        {
-          id: newConversationId,
-          name: "新对话",
-          createdAt: new Date().getTime(),
-          inputs: {},
-        },
-      ],
-      ...chatSessionList,
-    ]);
-    Storage_setListType(0);
+    // setChatSessionList((chatSessionList) => [
+    //   ...[
+    //     {
+    //       id: newConversationId,
+    //       name: "新对话",
+    //       createdAt: new Date().getTime(),
+    //       inputs: {},
+    //     },
+    //   ],
+    //   ...chatSessionList,
+    // ]);
+    Storage_setListType(1);
     Storage_setConversationId(newConversationId);
     setHistoryOrChatList(0);
     setShowComponent(false);
+    setHistoryOrChatList(1);
     setIniChatMessage([]);
     setTimeout(() => {
       setShowComponent(true);
@@ -181,7 +187,7 @@ export default function Dialogue() {
   //加载助手对应的历史会话
   const loadChatSession = (agentId: number, last_id: string) => {
     setTimeout(() => {
-      setShowComponent(false);
+      //setShowComponent(false);
       getChatSession({ agentId: agentId, last_id: last_id, limit: 100 }).then(
         (data) => {
           if (data.code === 0 && data.data.data !== null) {
@@ -196,7 +202,7 @@ export default function Dialogue() {
           } else {
             setChatSessionList([]);
           }
-          setShowComponent(true);
+          //setShowComponent(true);
         }
       );
     });
@@ -221,6 +227,46 @@ export default function Dialogue() {
       }
     });
   };
+  //删除聊天会话
+  const confirmDeletChatSession = (id: string) => {
+    deleteChatSession({
+      conversationId: id,
+      agentId: Storage_getAgentId(),
+    }).then((res) => {
+      if (res.code == 0) {
+        if (id == Storage_getConversationId()) {
+          newChat();
+        }
+        setChatSessionList(chatSessionList.filter((v) => v.id !== id));
+      }
+    });
+  };
+  //重命名聊天会话
+  const renameChatSessionUi = (id: string, name: string) => {
+    renameChatSession({
+      conversationId: id,
+      agentId: Storage_getAgentId(),
+      name: name,
+    }).then((res) => {
+      if (res.code == 0) {
+        setChatSessionList(
+          chatSessionList.map((v) => (v.id === id ? { ...v, name: name } : v))
+        );
+        setChatSessionRenameId("");
+        setRename("");
+      }
+    });
+  };
+  //开启重命名输入框
+  const editChatSessionRenameId = (id: string, name: string) => {
+    if (chatSessionRenameId === id) {
+      setChatSessionRenameId("");
+      setRename("");
+    } else {
+      setChatSessionRenameId(id);
+      setRename(name);
+    }
+  };
 
   useEffect(() => {
     changeMenuIndex(1);
@@ -272,7 +318,7 @@ export default function Dialogue() {
     loadChatSession(agentId, chatSessionLastId);
 
     getBalance();
-  }, [loginShow, chatSessionLastId]);
+  }, [loginShow]);
 
   //样式覆盖
   const BarkCustomClassName = cx(
@@ -373,6 +419,15 @@ export default function Dialogue() {
     setShowVip(false);
   };
 
+  const NeedBuyVip = () => {
+    return (
+      <>
+        当前智能体需要会员才能使用,去开通:
+        <a onClick={() => setShowVip(true)}>会员套餐</a>
+      </>
+    );
+  };
+
   return (
     <>
       <div className="flex justify-between items-center bg-[slate-200] dark:bg-[#000] h-full">
@@ -440,19 +495,64 @@ export default function Dialogue() {
                         <div
                           className="w-full mt-3 cursor-pointer"
                           key={item.id}
-                          onClick={() => changeChatSession(item.id)}
                         >
                           <div
-                            className={`flex rounded border ${
+                            className={`flex rounded border group ${
                               Storage_getConversationId() == item.id &&
                               Storage_getListType() === historyOrChatList
                                 ? "dark:border-[#0061ff] bg-blue-50 dark:bg-gray-800 text-[#0061ff]"
                                 : "border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400"
                             } p-3 sm:flex-row flex-col`}
                           >
-                            <div className="flex-grow text-ellipsis line-clamp-2">
-                              <h2 className="pb-2">{item.name}</h2>
-                              <p className="text-sm text-gray-400">
+                            <div className="flex-grow text-ellipsis line-clamp-2 relative">
+                              <Popconfirm
+                                title="删除提醒"
+                                description="确定删除当前历史会话吗?"
+                                onConfirm={() =>
+                                  confirmDeletChatSession(item.id)
+                                }
+                                okText="确定"
+                                cancelText="取消"
+                              >
+                                <RiDeleteBinLine className="absolute top-0.5 right-0.5 cursor-pointer group-hover:block hidden" />
+                              </Popconfirm>
+                              <RiDraftLine
+                                className="absolute top-0.5 right-6 cursor-pointer group-hover:block hidden"
+                                onClick={() =>
+                                  editChatSessionRenameId(item.id, item.name)
+                                }
+                              />
+
+                              {chatSessionRenameId && (
+                                <p>
+                                  <input
+                                    value={rename}
+                                    onChange={(e) => setRename(e.target.value)}
+                                    onKeyDown={(e) => {
+                                      if (e.key === "Enter") {
+                                        renameChatSessionUi(item.id, rename);
+                                      }
+                                      if (e.key === "Escape") {
+                                        setChatSessionRenameId("");
+                                        setRename("");
+                                      }
+                                    }}
+                                    className="h-8 bg-gray-50 dark:bg-[#202123] bg-opacity-50 rounded border border-gray-300 dark:border-slate-700 text-base outline-none text-gray-700 py-1 leading-8 transition-colors duration-200 ease-in-out"
+                                  />
+                                </p>
+                              )}
+                              {!chatSessionRenameId && (
+                                <h2
+                                  className="pb-2"
+                                  onClick={() => changeChatSession(item.id)}
+                                >
+                                  {item.name}
+                                </h2>
+                              )}
+                              <p
+                                className="text-sm text-gray-400"
+                                onClick={() => changeChatSession(item.id)}
+                              >
                                 {new Date(item.createdAt).toLocaleString()}
                               </p>
                             </div>
@@ -481,8 +581,7 @@ export default function Dialogue() {
                         <div className="w-full mt-3" key={item.id}>
                           <div
                             className={`flex rounded border group ${
-                              Storage_getAgentId() == item.id &&
-                              Storage_getListType() === historyOrChatList
+                              Storage_getAgentId() == item.id
                                 ? "dark:border-[#0061ff] bg-blue-50 dark:bg-gray-800 text-[#0061ff]"
                                 : "border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400"
                             }  p-3 sm:flex-row flex-col`}
@@ -584,19 +683,32 @@ export default function Dialogue() {
                 //helloMessage ={helloMessage}
                 actions={{
                   render: (defaultDoms) => {
-                    if (showLeftLetter) {
-                      return defaultDoms;
+                    if (isMobile()) {
+                      return [
+                        <a
+                          key="handlShowLeftBox"
+                          className="text-gray-400 hover:text-blue-600"
+                          onClick={() => setShowLeftBox(true)}
+                        >
+                          <RiBookReadLine className="text-2xl" />
+                        </a>,
+                        ...defaultDoms,
+                      ];
+                    } else {
+                      if (showLeftLetter) {
+                        return defaultDoms;
+                      }
+                      return [
+                        <a
+                          key="handlShowLeftLetter"
+                          className="text-gray-400 hover:text-blue-600"
+                          onClick={handlShowLeftLetter}
+                        >
+                          <RiBookReadLine className="text-2xl" />
+                        </a>,
+                        ...defaultDoms,
+                      ];
                     }
-                    return [
-                      <a
-                        key="handlShowLeftLetter"
-                        className="text-gray-400 hover:text-blue-600"
-                        onClick={handlShowLeftLetter}
-                      >
-                        <RiBookReadLine className="text-2xl" />
-                      </a>,
-                      ...defaultDoms,
-                    ];
                   },
                   flexConfig: {
                     gap: 24,
@@ -604,6 +716,13 @@ export default function Dialogue() {
                     justify: "space-start",
                   },
                 }}
+                chatItemRenderConfig={{
+                  contentRender: (item) => {
+                    if (item?.originData?.role === "need_pay") {
+                      return <NeedBuyVip />;
+                    }
+                  },
+                }}
                 request={async (messages) => {
                   const response = await fetch(
                     getApiUrl() + "/gpts/chat/submit",
@@ -662,19 +781,20 @@ export default function Dialogue() {
                                   if (parsed.finish) {
                                     setConversationId(parsed.conversation_id);
                                     getBalance();
+                                    loadChatSession(Storage_getAgentId(), "");
                                   }
                                   if (parsed.need_login) {
-                                    changeLoginShow(true);
                                     controller.enqueue(
                                       encoder.encode("请登录后使用")
                                     );
+                                    setTimeout(() => {changeLoginShow(true);}, 200);
                                   } else if (parsed.need_pay) {
                                     controller.enqueue(
                                       encoder.encode(
-                                        "当前智能体需要会员才能使用,去开通:[会员套餐](/vip)"
+                                        "当前智能体需要会员才能使用"
                                       )
                                     );
-                                    setShowVip(true);
+                                    setTimeout(() => {setShowVip(true);}, 200);
                                   }
                                 }
                               }
@@ -777,15 +897,6 @@ export default function Dialogue() {
         )}
       </div>
 
-      <div
-        className="absolute -left-5 top-1/2 transform -translate-y-1/2 rounded-full bg-[#ecf1f9] p-1 shadow-lg  md:hidden block dark:bg-blue-950"
-        onClick={() => {
-          setShowLeftBox(true);
-        }}
-      >
-        <RiArrowDropRightLine className="text-3xl text-[#0061ff] ml-3" />
-      </div>
-
       {showLeftBox && (
         <div className="pay-box">
           <div className="pay-mask"></div>
@@ -985,13 +1096,13 @@ export default function Dialogue() {
       {showVip && (
         <div className="pay-box">
           <div className="pay-mask"></div>
-          <div className="pay-div pt-12 md:p-7 bg-white dark:bg-gray-900 text-base rounded w-full md:container h-screen">
+          <div className="pay-div pt-12 md:p-7 bg-white dark:bg-gray-900 text-base rounded w-full md:h-5/6 md:container h-screen">
             <RiCloseFill
               className="absolute right-2.5 top-2.5 w-8 h-8 cursor-pointer transform duration-500 ease-in-out hover:scale-125 text-gray-500"
               onClick={closeVipBox}
             ></RiCloseFill>
             <div className="h-full overflow-y-auto">
-              <VipPage></VipPage>
+              <VipBoxPage></VipBoxPage>
             </div>
           </div>
         </div>

+ 1 - 1
web/src/app/page.tsx

@@ -202,7 +202,7 @@ export default function Home() {
             <div className="flex flex-wrap -m-4 text-sm">
               {employeeList.map((item) => (
                 <div
-                  className="p-4 lg:w-1/2 xl:w-1/3 transition transform hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:transform-none grow"
+                  className="p-4 w-full lg:w-1/2 xl:w-1/3 transition transform hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:transform-none grow-0 "
                   key={item.id}
                 >
                   <a

+ 21 - 8
web/src/app/user-center/page.tsx

@@ -2,7 +2,7 @@
 import { useRef, useState, useEffect } from "react";
 import { message, Tabs } from "antd";
 import { css, cx } from "antd-style";
-import { getUserInfo, userPassword, getUserBalance } from "@/api/client";
+import { getUserInfo,updateUserInfo, userPassword, getUserBalance } from "@/api/client";
 import { useGlobalContext } from "@/providers/GlobalProvider";
 import { useTheme } from "next-themes";
 import {
@@ -14,7 +14,9 @@ import {
 
 const UserCenter = () => {
   const themeBig = useTheme();
-  const { changeMenuIndex } = useGlobalContext();
+  const { changeMenuIndex,uploadUserInfoState, changeUploadUserInfoState } = useGlobalContext();
+  const [userName, setUserName] = useState<string>("");
+  const [nickName_static, setNickName_static] = useState<string>("");
   const [nickName, setNickName] = useState<string>("");
   const [phone, setPhone] = useState<string>("");
   const [email, setEmail] = useState<string>("");
@@ -33,10 +35,19 @@ const UserCenter = () => {
   const handleSaveUserInfo = (e: React.FormEvent) => {
     e.preventDefault();
     if (nickName) {
-      if (email) {
-        message.success("修改成功!");
+      if (phone) {
+        if (email) {
+          updateUserInfo({nickname:nickName, mobile: phone, email: email }).then(
+            (data) => {
+              message.success("用户信息更新成功!");
+              changeUploadUserInfoState(!uploadUserInfoState);
+            }
+          );
+        } else {
+          inputRef_email.current?.focus();
+        }
       } else {
-        inputRef_email.current?.focus();
+        inputRef_phone.current?.focus();
       }
     } else {
       inputRef_nickName.current?.focus();
@@ -78,6 +89,8 @@ const UserCenter = () => {
     changeMenuIndex(0);
     getUserInfo().then((data) => {
       if (data.code == 0) {
+        setUserName(data.data.username);
+        setNickName_static(data.data.nickname);
         setNickName(data.data.nickname);
         setPhone(data.data.mobile);
         setEmail(data.data.email);
@@ -88,7 +101,7 @@ const UserCenter = () => {
         setBalance(data.data.balance);
       }
     });
-  }, []);
+  }, [uploadUserInfoState]);
 
   return (
     <>
@@ -109,9 +122,9 @@ const UserCenter = () => {
               src="/images/avatar.png"
               alt="avatar"
             />
-            <div className="mt-4 text-xl">{nickName}</div>
+            <div className="mt-4 text-xl">{nickName_static}</div>
             <div className="mt-3 text-gray-400">
-              {email ? email : "extemp@default.com"}
+              {userName}
             </div>
             <div className="mt-3 text-gray-600 text-left">
               我是一台基于深度学习和自然语言处理技术的 AI

+ 179 - 0
web/src/app/vip-box/page.tsx

@@ -0,0 +1,179 @@
+"use client";
+import { useState, useEffect } from "react";
+import { useGlobalContext } from "@/providers/GlobalProvider";
+import { RiCloseFill } from 'react-icons/ri';
+
+interface Package {
+  id: number;
+  name: string;
+  description: string;
+  price: string;
+  image: string;
+  days: number;
+  basePoints: number;
+  seniorPoints: number;
+}
+
+const packages: Package[] = [
+  {
+    id: 1,
+    name: "入门体验会员",
+    description:
+      "套餐包含500积分通用AI模型(AI3.5Turbo等模型)、100积分增强AI模型(AI4o大模型)、30积分高级绘画额度",
+    price: "19.99",
+    image:
+      "http://ai3666.oss-cn-beijing.aliyuncs.com/ai/2024-11-14/%C3%A7%C2%A8%C2%BF%C3%A5%C2%AE%C2%9A%C3%A8%C2%AE%C2%BE%C3%A8%C2%AE%C2%A1-1.jpg",
+    days: 30,
+    basePoints: 100,
+    seniorPoints: 100,
+  },
+  {
+    id: 2,
+    name: "季度高级会员",
+    description:
+      "套餐包含800积分通用AI模型(AI3.5Turbo等模型)、1000积分增强AI模型(AI4o大模型)、300积分高级绘画额度",
+    price: "99.00",
+    image:
+      "http://ai3666.oss-cn-beijing.aliyuncs.com/ai/2024-11-14/%C3%A7%C2%A8%C2%BF%C3%A5%C2%AE%C2%9A%C3%A8%C2%AE%C2%BE%C3%A8%C2%AE%C2%A1-2.jpg",
+    days: 120,
+    basePoints: 800,
+    seniorPoints: 1000,
+  },
+  {
+    id: 3,
+    name: "年度畅享会员",
+    description:
+      "套餐包含3000积分通用AI模型(AI3.5Turbo等模型)、3000积分增强AI模型(AI4o大模型)、300积分高级绘画额度",
+    price: "365.00",
+    image:
+      "http://ai3666.oss-cn-beijing.aliyuncs.com/ai/2024-11-14/%C3%A7%C2%A8%C2%BF%C3%A5%C2%AE%C2%9A%C3%A8%C2%AE%C2%BE%C3%A8%C2%AE%C2%A1-3.jpg",
+    days: 365,
+    basePoints: 3000,
+    seniorPoints: 3000,
+  },
+];
+
+export default function VipBoxPage() {
+  const { changeMenuIndex } = useGlobalContext();
+  const [showBuyBox, setShowBuyBox] = useState(false);
+
+  const closeBuyBox = () => {
+    setShowBuyBox(false);
+  }
+
+  useEffect(() => {
+    
+  }, []);
+
+  return (
+    <>
+      <section className="text-gray-600 body-font mt-6 md:mt-0">
+        <div className="w-full md:container md:px-5 md:py-24 mx-auto">
+          <div className="flex flex-col text-center w-full">
+            <h1 className="sm:text-4xl text-3xl font-medium title-font mb-2 text-gray-900 dark:text-white">
+              会员套餐
+            </h1>
+            <p className="lg:w-2/3 mx-auto leading-relaxed text-base text-gray-500">
+              尽情探索,欢迎光临我们的在线商店、感谢您选择我们、让我们一同开启愉悦的购物之旅!
+            </p>
+          </div>
+
+          <div className="px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16">
+            <div className="grid grid-cols-1 gap-2 md:grid-cols-2 md:gap-4  xl:grid-cols-3 xl:gap-8">
+              {packages.map((pkg) => (
+                <div
+                  className="rounded-2xl border border-gray-200 shadow-sm dark:border-gray-500"
+                  key={pkg.id}
+                >
+                  <div className="p-6 sm:px-8">
+                    <img
+                      className="lg:h-48 md:h-36 w-full object-cover object-center rounded-2xl"
+                      src={pkg.image}
+                      alt={pkg.name}
+                    />
+                    <h2 className="mt-2 text-lg font-medium text-gray-900 dark:text-white">
+                      {pkg.name}
+                    </h2>
+                    <p className="mt-2 text-gray-700 dark:text-gray-500">
+                      {pkg.description}
+                    </p>
+                    <p className="mt-2 sm:mt-4">
+                      <strong className="text-3xl font-bold text-gray-900 sm:text-4xl  dark:text-gray-300">
+                        {pkg.days}
+                      </strong>
+                      <span className="text-sm font-medium text-gray-700 dark:text-gray-500 ml-1">
+                        天
+                      </span>
+                    </p>
+                    <button className="mt-4 block w-full rounded px-12 py-3 text-center text-sm font-medium text-white global-bg-color focus:outline-none focus:ring sm:mt-6 transition ease-in-out hover:-translate-y-1" onClick={() => setShowBuyBox(true)}>
+                      ¥{pkg.price}
+                    </button>
+                  </div>
+
+                  <div className="px-6 pb-6 sm:px-8 sm:pb-8">
+                    <ul className="space-y-2 text-gray-700 dark:text-gray-500">
+                      <li className="flex justify-between">
+                        <span>基础模型额度</span>
+                        <span>{pkg.basePoints} 积分 </span>
+                      </li>
+                      <li className="flex justify-between">
+                        <span>高级模型额度</span>
+                        <span>{pkg.seniorPoints} 积分 </span>
+                      </li>
+                    </ul>
+                  </div>
+                </div>
+              ))}
+            </div>
+          </div>
+        </div>
+      </section>
+
+      {showBuyBox && (
+        <div className="pay-box">
+          <div className="pay-mask"></div>
+          <div className="pay-div p-7 bg-white dark:bg-gray-900 text-base rounded w-11/12 lg:w-full max-w-screen-lg">
+            <RiCloseFill className="absolute right-2.5 top-2.5 w-8 h-8 cursor-pointer transform duration-500 ease-in-out hover:scale-125 text-gray-500" onClick={closeBuyBox}></RiCloseFill>
+            <h2 className="text-xl global-txt-color">会员套餐支付</h2>
+            <div className="py-10 grid grid-cols-1 md:grid-cols-2 md:gap-8">
+              <div className="">
+                <div className="flex">
+                  <div className="w-20 text-nowrap text-left h-6 leading-8 shrink-0">
+                    需要支付:
+                  </div>
+                  <div className="h-6 text-red-700 text-2xl">¥19.90</div>
+                </div>
+                <div className="mt-4 flex ">
+                  <div className="w-20 text-nowrap text-left shrink-0">套餐名称:</div>
+                  <div className="text-left">入门体验会员</div>
+                </div>
+                <div className="mt-4 flex">
+                  <div className="w-20 text-nowrap text-left shrink-0">套餐描述:</div>
+                  <div className="text-left w-5/6">
+                    套餐包含500积分通用AI模型(AI3.5Turbo等模型)、100积分增强AI模型(AI4o大模型)、30积分高级绘画额度
+                  </div>
+                </div>
+              </div>
+              <div className="text-center py-4 md:py-0 mt-5 md:mt-0 border-t md:border-t-0">
+                <div>
+                  请在 <span className="text-red-700">00:03:34</span>{" "}
+                  时间内完成支付!
+                </div>
+                <div className="w-full pt-3">
+                  <div className="relative w-72 mx-auto p-3 border rounded">
+                    <img
+                      src="/temp/wxpay.png"
+                      className="w-12 bg-white p-1 div-center"
+                    />
+                    <img src="/temp/qrcode.png" />
+                  </div>
+                </div>
+                <div className="mt-2">打开微信扫码支付</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      )}
+    </>
+  );
+}

+ 2 - 2
web/src/components/Header/index.tsx

@@ -8,7 +8,7 @@ import { getUserInfo } from "@/api/client";
 
 export default function Header({ name }: { name: string }) {
   const router = useRouter();
-  const { loginShow, changeLoginShow } = useGlobalContext();
+  const { loginShow, changeLoginShow,uploadUserInfoState } = useGlobalContext();
   const [isLogin, setIsLogin] = useState(false);
   const [nickName, setNickName] = useState("");
 
@@ -25,7 +25,7 @@ export default function Header({ name }: { name: string }) {
         }
       });
     }
-  }, [loginShow]);
+  }, [loginShow,uploadUserInfoState]);
 
   return (
     <header className="sticky w-full flex gap-4 justify-between items-center top-0 shadow dark:shadow-none backdrop-blur dark:bg-transparent transition-all py-2 px-1 z-50">

+ 7 - 1
web/src/providers/GlobalProvider.tsx

@@ -16,6 +16,7 @@ interface GlobalProviderProps {
 export const GlobalProvider: React.FC<GlobalProviderProps> = ({ children }) => {
   const [menuIndex, setMenuIndex] = useState<number>(0);
   const [loginShow, setLoginShow] = useState<boolean>(false);
+  const [uploadUserInfoState, setUploadUserInfoState] = useState<boolean>(false);
 
   const changeMenuIndex = (index: number) => {
     setMenuIndex(index);
@@ -23,6 +24,9 @@ export const GlobalProvider: React.FC<GlobalProviderProps> = ({ children }) => {
   const changeLoginShow = (show: boolean) => {
     setLoginShow(show);
   };
+  const changeUploadUserInfoState = (value: boolean) => {
+    setUploadUserInfoState(value);
+  };
   
   useEffect(() => {
   }, []);
@@ -33,7 +37,9 @@ export const GlobalProvider: React.FC<GlobalProviderProps> = ({ children }) => {
         menuIndex,
         changeMenuIndex,
         loginShow,
-        changeLoginShow
+        changeLoginShow,
+        uploadUserInfoState,
+        changeUploadUserInfoState
       }}
     >
       {children}

+ 41 - 0
web/src/utils/clientsApis.ts

@@ -157,6 +157,21 @@ export interface UserPasswordParams {
 }
 
 /**
+ * 用户修改个人信息请求参数
+ * 
+ * @interface UserInfoParams
+ * @property {string} nickname - 昵称
+ * @property {string} mobile - 手机号码
+ * @property {string} email -邮箱
+ */
+export interface UserInfoParams {
+    nickname: string;
+    mobile: string;
+    email: string;
+}
+
+
+/**
  * 获取用户信息响应结果
  * 
  * @interface UserInfoResult
@@ -290,3 +305,29 @@ export interface ChatSessionResult {
     createdAt: number;
     inputs: any;
 }
+
+/**
+ * 聊天会话删除请求参数
+ * 
+ * @interface ChatSessionDeleteParams
+ * @property {string} conversationId - 会话ID
+ * @property {number} agentId - 智能体ID
+ */
+export interface ChatSessionDeleteParams {
+    conversationId: string;
+    agentId: number;
+}
+
+/**
+ * 聊天会话重命名请求参数
+ * 
+ * @interface ChatSessionRenameParams
+ * @property {string} conversationId - 会话ID
+ * @property {number} agentId - 智能体ID
+ * @property {string} name - 名称
+ */
+export interface ChatSessionRenameParams {
+    conversationId: string;
+    agentId: number;
+    name: string;
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است