|
@@ -4,47 +4,30 @@ import {
|
|
Prompts,
|
|
Prompts,
|
|
Sender,
|
|
Sender,
|
|
Suggestion,
|
|
Suggestion,
|
|
- ThoughtChain,
|
|
|
|
XProvider,
|
|
XProvider,
|
|
useXAgent,
|
|
useXAgent,
|
|
useXChat,
|
|
useXChat,
|
|
Welcome,
|
|
Welcome,
|
|
|
|
+ Attachments,
|
|
|
|
+ AttachmentsProps,
|
|
} from "@ant-design/x";
|
|
} 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 React from "react";
|
|
-
|
|
|
|
import {
|
|
import {
|
|
BulbOutlined,
|
|
BulbOutlined,
|
|
SmileOutlined,
|
|
SmileOutlined,
|
|
UserOutlined,
|
|
UserOutlined,
|
|
- CoffeeOutlined,
|
|
|
|
- FireOutlined,
|
|
|
|
EditOutlined,
|
|
EditOutlined,
|
|
DeleteOutlined,
|
|
DeleteOutlined,
|
|
MessageOutlined,
|
|
MessageOutlined,
|
|
PlusOutlined,
|
|
PlusOutlined,
|
|
|
|
+ CloudUploadOutlined,
|
|
|
|
+ LinkOutlined,
|
|
} from "@ant-design/icons";
|
|
} 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"> = {
|
|
const roles: GetProp<typeof Bubble.List, "roles"> = {
|
|
assient: {
|
|
assient: {
|
|
@@ -59,12 +42,14 @@ const roles: GetProp<typeof Bubble.List, "roles"> = {
|
|
avatar: { icon: <UserOutlined />, style: { background: "#87d068" } },
|
|
avatar: { icon: <UserOutlined />, style: { background: "#87d068" } },
|
|
},
|
|
},
|
|
};
|
|
};
|
|
-
|
|
|
|
-export default () => {
|
|
|
|
|
|
+type AssistantProps = {
|
|
|
|
+ agent?: AgentItem;
|
|
|
|
+};
|
|
|
|
+export default (props: AssistantProps) => {
|
|
const [value, setValue] = React.useState("");
|
|
const [value, setValue] = React.useState("");
|
|
const { message } = App.useApp();
|
|
const { message } = App.useApp();
|
|
|
|
|
|
- const [agent] = useXAgent<{role: string, content: string}>({
|
|
|
|
|
|
+ const [agent] = useXAgent<{ role: string; content: string }>({
|
|
baseURL: "http://localhost:3000/ai/chat",
|
|
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) => {
|
|
const submitMessage = (message: string) => {
|
|
- onRequest({role: "user", content: message});
|
|
|
|
|
|
+ // onRequest({ role: "user", content: message });
|
|
};
|
|
};
|
|
|
|
|
|
const handlePromptItem = (item: any) => {
|
|
const handlePromptItem = (item: any) => {
|
|
- onRequest({role: "user", content: item.data.description});
|
|
|
|
|
|
+ // onRequest({ role: "user", content: item.data.description });
|
|
};
|
|
};
|
|
- console.log(messages)
|
|
|
|
|
|
+
|
|
return (
|
|
return (
|
|
<>
|
|
<>
|
|
<Card
|
|
<Card
|
|
@@ -107,8 +131,12 @@ export default () => {
|
|
},
|
|
},
|
|
}}
|
|
}}
|
|
title={
|
|
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>
|
|
</span>
|
|
}
|
|
}
|
|
>
|
|
>
|
|
@@ -116,7 +144,13 @@ export default () => {
|
|
<Flex style={{ height: "100%" }} gap={12}>
|
|
<Flex style={{ height: "100%" }} gap={12}>
|
|
<div className="w-200px">
|
|
<div className="w-200px">
|
|
<div className="w-full px-12px">
|
|
<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>
|
|
</div>
|
|
<Conversations
|
|
<Conversations
|
|
style={{ width: 200 }}
|
|
style={{ width: 200 }}
|
|
@@ -136,15 +170,24 @@ export default () => {
|
|
<div className="flex-1">
|
|
<div className="flex-1">
|
|
{!messages.length ? (
|
|
{!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
|
|
<Prompts
|
|
- title="✨ 你可以这样问我:"
|
|
|
|
- items={promptsItems}
|
|
|
|
|
|
+ title={
|
|
|
|
+ props.agent?.promptsItems ? "✨ 你可以这样问我:" : ""
|
|
|
|
+ }
|
|
|
|
+ items={props.agent?.promptsItems || []}
|
|
wrap
|
|
wrap
|
|
onItemClick={handlePromptItem}
|
|
onItemClick={handlePromptItem}
|
|
/>
|
|
/>
|
|
@@ -155,13 +198,13 @@ export default () => {
|
|
roles={roles}
|
|
roles={roles}
|
|
items={
|
|
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>
|
|
</div>
|
|
@@ -170,12 +213,12 @@ export default () => {
|
|
{
|
|
{
|
|
key: "1",
|
|
key: "1",
|
|
icon: <BulbOutlined style={{ color: "#FFD700" }} />,
|
|
icon: <BulbOutlined style={{ color: "#FFD700" }} />,
|
|
- label: "Ignite Your Creativity",
|
|
|
|
|
|
+ label: "一句话",
|
|
},
|
|
},
|
|
{
|
|
{
|
|
key: "2",
|
|
key: "2",
|
|
icon: <SmileOutlined style={{ color: "#52C41A" }} />,
|
|
icon: <SmileOutlined style={{ color: "#52C41A" }} />,
|
|
- label: "Tell me a Joke",
|
|
|
|
|
|
+ label: "自动生成",
|
|
},
|
|
},
|
|
]}
|
|
]}
|
|
onItemClick={handlePromptItem}
|
|
onItemClick={handlePromptItem}
|
|
@@ -188,7 +231,22 @@ export default () => {
|
|
{({ onTrigger, onKeyDown }) => {
|
|
{({ onTrigger, onKeyDown }) => {
|
|
return (
|
|
return (
|
|
<Sender
|
|
<Sender
|
|
|
|
+ ref={senderRef}
|
|
|
|
+ header={senderHeader}
|
|
|
|
+ prefix={
|
|
|
|
+ <Button
|
|
|
|
+ type="text"
|
|
|
|
+ icon={<LinkOutlined />}
|
|
|
|
+ onClick={() => {
|
|
|
|
+ setOpenAttachment(!openAttachment);
|
|
|
|
+ }}
|
|
|
|
+ />
|
|
|
|
+ }
|
|
value={value}
|
|
value={value}
|
|
|
|
+ onPasteFile={(file) => {
|
|
|
|
+ attachmentsRef.current?.upload(file);
|
|
|
|
+ setOpenAttachment(true);
|
|
|
|
+ }}
|
|
onChange={(nextVal) => {
|
|
onChange={(nextVal) => {
|
|
if (nextVal === "/") {
|
|
if (nextVal === "/") {
|
|
onTrigger();
|
|
onTrigger();
|
|
@@ -198,7 +256,7 @@ export default () => {
|
|
setValue(nextVal);
|
|
setValue(nextVal);
|
|
}}
|
|
}}
|
|
onKeyDown={onKeyDown}
|
|
onKeyDown={onKeyDown}
|
|
- placeholder='输入/获取快捷提示'
|
|
|
|
|
|
+ placeholder="输入/获取快捷提示"
|
|
onSubmit={submitMessage}
|
|
onSubmit={submitMessage}
|
|
/>
|
|
/>
|
|
);
|
|
);
|