Browse Source

style: 修改ai助手样式

liaojiaxing 1 month ago
parent
commit
0f029ad1a9

BIN
src/assets/icon-ai-1.png


BIN
src/assets/icon-ai-2.png


BIN
src/assets/icon-ai-3.png


BIN
src/assets/icon-ai-4.png


BIN
src/assets/icon-ai-5.png


BIN
src/assets/icon-ai-6.png


+ 110 - 52
src/pages/ai/Assistant.tsx

@@ -4,47 +4,30 @@ import {
   Prompts,
   Sender,
   Suggestion,
-  ThoughtChain,
   XProvider,
   useXAgent,
   useXChat,
   Welcome,
+  Attachments,
+  AttachmentsProps,
 } from "@ant-design/x";
 
-import { Card, Divider, Flex, Radio, Typography, App, Button } from "antd";
+import { Card, Divider, Flex, App, Button } from "antd";
 import React from "react";
-
 import {
   BulbOutlined,
   SmileOutlined,
   UserOutlined,
-  CoffeeOutlined,
-  FireOutlined,
   EditOutlined,
   DeleteOutlined,
   MessageOutlined,
   PlusOutlined,
+  CloudUploadOutlined,
+  LinkOutlined,
 } from "@ant-design/icons";
-import type { GetProp } from "antd";
-import type { PromptsProps, ConversationsProps } from "@ant-design/x";
-
-const promptsItems: PromptsProps["items"] = [
-  {
-    key: "1",
-    icon: <CoffeeOutlined style={{ color: "#964B00" }} />,
-    description: "怎么创建我的应用?",
-  },
-  {
-    key: "2",
-    icon: <SmileOutlined style={{ color: "#FAAD14" }} />,
-    description: "页面设计器如何使用?",
-  },
-  {
-    key: "3",
-    icon: <FireOutlined style={{ color: "#FF4D4F" }} />,
-    description: "如何生成页面SQL?",
-  },
-];
+import type { GetProp, GetRef } from "antd";
+import type { ConversationsProps } from "@ant-design/x";
+import type { AgentItem } from "./data";
 
 const roles: GetProp<typeof Bubble.List, "roles"> = {
   assient: {
@@ -59,12 +42,14 @@ const roles: GetProp<typeof Bubble.List, "roles"> = {
     avatar: { icon: <UserOutlined />, style: { background: "#87d068" } },
   },
 };
-
-export default () => {
+type AssistantProps = {
+  agent?: AgentItem;
+};
+export default (props: AssistantProps) => {
   const [value, setValue] = React.useState("");
   const { message } = App.useApp();
 
-  const [agent] = useXAgent<{role: string, content: string}>({
+  const [agent] = useXAgent<{ role: string; content: string }>({
     baseURL: "http://localhost:3000/ai/chat",
   });
 
@@ -89,14 +74,53 @@ export default () => {
     },
   });
 
+  const [openAttachment, setOpenAttachment] = React.useState(false);
+  const attachmentsRef = React.useRef<GetRef<typeof Attachments>>(null);
+  const senderRef = React.useRef<GetRef<typeof Sender>>(null);
+  const [attachmentItems, setAttachmentItems] = React.useState<GetProp<AttachmentsProps, 'items'>>([]);
+
+  const senderHeader = (
+    <Sender.Header
+      title="附件"
+      styles={{
+        content: {
+          padding: 0,
+        },
+      }}
+      open={openAttachment}
+      onOpenChange={setOpenAttachment}
+      forceRender
+    >
+      <Attachments
+        ref={attachmentsRef}
+        // Mock not real upload file
+        beforeUpload={() => false}
+        items={attachmentItems}
+        onChange={({ fileList }) => setAttachmentItems(fileList)}
+        placeholder={(type) =>
+          type === "drop"
+            ? {
+                title: "拖拽文件到这里",
+              }
+            : {
+                icon: <CloudUploadOutlined />,
+                title: "文件列表",
+                description: "点击或者拖拽文件到这里上传",
+              }
+        }
+        getDropContainer={() => senderRef.current?.nativeElement}
+      />
+    </Sender.Header>
+  );
+
   const submitMessage = (message: string) => {
-    onRequest({role: "user", content: message});
+    // onRequest({ role: "user", content: message });
   };
 
   const handlePromptItem = (item: any) => {
-    onRequest({role: "user", content: item.data.description});
+    // onRequest({ role: "user", content: item.data.description });
   };
-  console.log(messages)
+
   return (
     <>
       <Card
@@ -107,8 +131,12 @@ export default () => {
           },
         }}
         title={
-          <span>
-            <em-emoji id="*️⃣"></em-emoji>综合助手
+          <span className="flex items-center">
+            <img
+              className="w-20px h-20px rounded-8px"
+              src={props.agent?.icon}
+            />
+            <span className="ml-4px">{props.agent?.name}</span>
           </span>
         }
       >
@@ -116,7 +144,13 @@ export default () => {
           <Flex style={{ height: "100%" }} gap={12}>
             <div className="w-200px">
               <div className="w-full px-12px">
-                <Button type="primary" className="w-full" icon={<PlusOutlined/>}>新对话</Button>
+                <Button
+                  type="primary"
+                  className="w-full"
+                  icon={<PlusOutlined />}
+                >
+                  新对话
+                </Button>
               </div>
               <Conversations
                 style={{ width: 200 }}
@@ -136,15 +170,24 @@ export default () => {
               <div className="flex-1">
                 {!messages.length ? (
                   <>
-                    <Welcome
-                      icon="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp"
-                      title="你好!我是易码工坊AI助手"
-                      description="关于易码工坊的所有问题,你都可以向我咨询~"
-                      className="mt-20 mb-10"
-                    />
+                    <div className="mt-20 mb-10">
+                      <Welcome
+                        icon={
+                          <img
+                            src={props.agent?.icon}
+                            className="rounded-8px"
+                          />
+                        }
+                        title={`你好!我是易码工坊${props.agent?.name || "AI"}助手`}
+                        description={props.agent?.description}
+                      />
+                    </div>
+
                     <Prompts
-                      title="✨ 你可以这样问我:"
-                      items={promptsItems}
+                      title={
+                        props.agent?.promptsItems ? "✨ 你可以这样问我:" : ""
+                      }
+                      items={props.agent?.promptsItems || []}
                       wrap
                       onItemClick={handlePromptItem}
                     />
@@ -155,13 +198,13 @@ export default () => {
                     roles={roles}
                     items={
                       []
-                    //   messages.map(({ id, message, status }) => ({
-                    //   key: id,
-                    //   loading: status === "loading",
-                    //   role: status === "user" ? "local" : "ai",
-                    //   content: message,
-                    // }))
-                  }
+                      //   messages.map(({ id, message, status }) => ({
+                      //   key: id,
+                      //   loading: status === "loading",
+                      //   role: status === "user" ? "local" : "ai",
+                      //   content: message,
+                      // }))
+                    }
                   />
                 )}
               </div>
@@ -170,12 +213,12 @@ export default () => {
                   {
                     key: "1",
                     icon: <BulbOutlined style={{ color: "#FFD700" }} />,
-                    label: "Ignite Your Creativity",
+                    label: "一句话",
                   },
                   {
                     key: "2",
                     icon: <SmileOutlined style={{ color: "#52C41A" }} />,
-                    label: "Tell me a Joke",
+                    label: "自动生成",
                   },
                 ]}
                 onItemClick={handlePromptItem}
@@ -188,7 +231,22 @@ export default () => {
                 {({ onTrigger, onKeyDown }) => {
                   return (
                     <Sender
+                      ref={senderRef}
+                      header={senderHeader}
+                      prefix={
+                        <Button
+                          type="text"
+                          icon={<LinkOutlined />}
+                          onClick={() => {
+                            setOpenAttachment(!openAttachment);
+                          }}
+                        />
+                      }
                       value={value}
+                      onPasteFile={(file) => {
+                        attachmentsRef.current?.upload(file);
+                        setOpenAttachment(true);
+                      }}
                       onChange={(nextVal) => {
                         if (nextVal === "/") {
                           onTrigger();
@@ -198,7 +256,7 @@ export default () => {
                         setValue(nextVal);
                       }}
                       onKeyDown={onKeyDown}
-                      placeholder='输入/获取快捷提示'
+                      placeholder="输入/获取快捷提示"
                       onSubmit={submitMessage}
                     />
                   );

+ 133 - 0
src/pages/ai/data.tsx

@@ -0,0 +1,133 @@
+import { SmileOutlined, CoffeeOutlined, FireOutlined } from "@ant-design/icons";
+import type { PromptsProps } from "@ant-design/x";
+
+import icon1 from "@/assets/icon-ai-1.png";
+import icon2 from "@/assets/icon-ai-2.png";
+import icon3 from "@/assets/icon-ai-3.png";
+import icon4 from "@/assets/icon-ai-4.png";
+import icon5 from "@/assets/icon-ai-5.png";
+import icon6 from "@/assets/icon-ai-6.png";
+
+export type AgentItem = {
+  key: string;
+  name: string;
+  icon: string;
+  description?: string;
+  promptsItems?: PromptsProps["items"]
+}
+
+export const assistantList: AgentItem[] = [
+  {
+    key: "1",
+    name: "综合问答",
+    icon: icon1,
+    description: "基于LLM的智能助手,可以进行各种使用查询、知识问答等~",
+    promptsItems: [
+      {
+        key: "1",
+        icon: <CoffeeOutlined style={{ color: "#964B00" }} />,
+        description: "怎么创建我的应用?",
+      },
+      {
+        key: "2",
+        icon: <SmileOutlined style={{ color: "#FAAD14" }} />,
+        description: "页面设计器如何使用?",
+      },
+      {
+        key: "3",
+        icon: <FireOutlined style={{ color: "#FF4D4F" }} />,
+        description: "如何生成页面SQL?",
+      },
+    ],
+  },
+  {
+    key: "2",
+    name: "系统设计",
+    icon: icon2,
+    description: "可以进行各种系统方面的图形创建、使用说明,如: 流程图、系统架构图等等",
+    promptsItems: [
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何创建流程图?",
+      },
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何设置画布样式?",
+      },
+    ]
+  },
+  {
+    key: "3",
+    name: "数据模型",
+    icon: icon3,
+    description: "关于数据模型的一些问题~",
+    promptsItems: [
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何创建表格?",
+      },
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何使用在系统中使用数据模型?",
+      },
+    ]
+  },
+  {
+    key: "4",
+    name: "页面设计",
+    icon: icon4,
+    description: "表单设计器方面的使用方法~",
+    promptsItems: [
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何使用表单设计器?",
+      },
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何在表单设计器中添加弹窗?",
+      },
+    ]
+  },
+  {
+    key: "5",
+    name: "流程设计",
+    icon: icon5,
+    description: "不同流程的创建和使用",
+    promptsItems: [
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何在系统中使用流程图?",
+      },
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "流程异常如何处理?",
+      },
+    ]
+  },
+  {
+    key: "6",
+    name: "文档管理",
+    icon: icon6,
+    description: "文档管理方面的一些问题",
+    promptsItems: [
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何上传文档?",
+      },
+      {
+        key: "1",
+        icon: <SmileOutlined style={{ color: "#52C41A" }} />,
+        description: "如何将文档保存为模板?",
+      },
+    ]
+  },
+];

+ 4 - 35
src/pages/ai/index.tsx

@@ -4,42 +4,11 @@ import data from "@emoji-mart/data";
 import { init } from "emoji-mart";
 import styles from "./index.less";
 import logo from "@/assets/shalu-new1.png";
+import { assistantList } from "./data";
 
 init({ data });
 
 export default () => {
-  const assistantList = [
-    {
-      key: "1",
-      name: "综合助手",
-      icon: "iconfont icon-tuijian mr-1",
-    },
-    {
-      key: "2",
-      name: "系统设计",
-      icon: "iconfont icon-tuijian mr-1",
-    },
-    {
-      key: "3",
-      name: "数据模型",
-      icon: "iconfont icon-tuijian mr-1",
-    },
-    {
-      key: "4",
-      name: "页面设计",
-      icon: "iconfont icon-tuijian mr-1",
-    },
-    {
-      key: "5",
-      name: "流程设计",
-      icon: "iconfont icon-tuijian mr-1",
-    },
-    {
-      key: "6",
-      name: "文档管理",
-      icon: "iconfont icon-tuijian mr-1",
-    },
-  ];
 
   const [active, setActive] = useState("1");
   return (
@@ -53,7 +22,7 @@ export default () => {
             助手类型
           </p>
           <div
-            className="mt-3 space-y-1 overflow-y-auto overflow-x-hidden"
+            className="mt-3 space-y-2 overflow-y-auto overflow-x-hidden"
             style={{ height: "calc(-140px + 100vh)" }}
           >
             {assistantList.map((item, index) => (
@@ -69,7 +38,7 @@ export default () => {
                     className="flex items-center justify-center relative rounded-lg grow-0 shrink-0 overflow-hidden w-6 h-6 text-base"
                     style={{ background: "rgb(213, 245, 246)" }}
                   >
-                    <em-emoji id="*️⃣"></em-emoji>
+                    <img className="w-full h-full" src={item.icon}/>
                   </span>
                   <div
                     className="overflow-hidden text-ellipsis whitespace-nowrap"
@@ -91,7 +60,7 @@ export default () => {
       <div className="grow w-0">
         <div className="h-full py-2 pl-0 pr-2 sm:p-2">
           <div className="h-full flex bg-white rounded-2xl shadow-md overflow-hidden false">
-            <Assistant />
+            <Assistant key={active} agent={assistantList.find(item => item.key === active)}/>
           </div>
         </div>
       </div>