|
@@ -7,17 +7,28 @@ import {
|
|
|
Spin,
|
|
|
Dropdown,
|
|
|
Button,
|
|
|
+ Alert,
|
|
|
+ Drawer,
|
|
|
+ List,
|
|
|
} from "antd";
|
|
|
import type { DraggableData, DraggableEvent } from "react-draggable";
|
|
|
import Draggable from "react-draggable";
|
|
|
import { Sender, Welcome, Prompts, Bubble } from "@ant-design/x";
|
|
|
import { PromptsProps } from "@ant-design/x";
|
|
|
import aiLogo from "@/assets/icon-ai-3.png";
|
|
|
-import { CoffeeOutlined, SmileOutlined, UserOutlined } from "@ant-design/icons";
|
|
|
+import {
|
|
|
+ CoffeeOutlined,
|
|
|
+ FireOutlined,
|
|
|
+ HistoryOutlined,
|
|
|
+ PlusOutlined,
|
|
|
+ SmileOutlined,
|
|
|
+ UserOutlined,
|
|
|
+} from "@ant-design/icons";
|
|
|
import { useChat } from "@/hooks/useChat";
|
|
|
import type { GetProp } from "antd/lib";
|
|
|
import MarkdownViewer from "@/components/ai/MarkdownViewer";
|
|
|
-import AITable from "./AITable";
|
|
|
+// import AITable from "./AITable";
|
|
|
+import { useModel } from "umi";
|
|
|
|
|
|
type AICteatorProps = {
|
|
|
trigger: JSX.Element;
|
|
@@ -33,6 +44,7 @@ type AICteatorProps = {
|
|
|
|
|
|
export default (props: AICteatorProps) => {
|
|
|
const [open, setOpen] = useState(false);
|
|
|
+ const [openHistory, setOpenHistory] = useState(false);
|
|
|
const [disabled, setDisabled] = useState(true);
|
|
|
const [bounds, setBounds] = useState({
|
|
|
left: 0,
|
|
@@ -47,6 +59,9 @@ export default (props: AICteatorProps) => {
|
|
|
);
|
|
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
+ const { onCreateByAi } = useModel("erModel");
|
|
|
+
|
|
|
+ // 提示词
|
|
|
const items: PromptsProps["items"] = [
|
|
|
{
|
|
|
key: "6",
|
|
@@ -57,15 +72,17 @@ export default (props: AICteatorProps) => {
|
|
|
{
|
|
|
key: "7",
|
|
|
icon: <SmileOutlined style={{ color: "#FAAD14" }} />,
|
|
|
- description: "创建一个订单表",
|
|
|
+ description: "帮我创建一个订单表",
|
|
|
+ disabled: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: "8",
|
|
|
+ icon: <FireOutlined style={{ color: "#FAAD14" }} />,
|
|
|
+ description: "客户管理系统需要的表",
|
|
|
disabled: false,
|
|
|
},
|
|
|
];
|
|
|
|
|
|
- const handleTry = () => {
|
|
|
- onSubmit(messages[messages.length - 2].content as string);
|
|
|
- };
|
|
|
-
|
|
|
// bubbles角色配置
|
|
|
const roles: GetProp<typeof Bubble.List, "roles"> = {
|
|
|
assistant: {
|
|
@@ -80,18 +97,29 @@ export default (props: AICteatorProps) => {
|
|
|
messageRender: (content) => {
|
|
|
return typeof content === "string" ? (
|
|
|
<Typography className={content?.includes("```") ? "w-full" : ""}>
|
|
|
- {/* <MarkdownViewer content={content} /> */}
|
|
|
- {content?.includes("<generate>") ? (
|
|
|
- <AITable
|
|
|
- content={content}
|
|
|
- onChange={props.onChange}
|
|
|
- onTry={handleTry}
|
|
|
- ></AITable>
|
|
|
- ) : (
|
|
|
- <MarkdownViewer
|
|
|
- content={content.replace("<chat>", "").replace("</chat>", "")}
|
|
|
- />
|
|
|
- )}
|
|
|
+ <MarkdownViewer
|
|
|
+ content={content}
|
|
|
+ codeFooter={(language, code) => {
|
|
|
+ const handleAdd = () => {
|
|
|
+ try {
|
|
|
+ const data = JSON.parse(code);
|
|
|
+ onCreateByAi(data);
|
|
|
+ message.success("添加成功");
|
|
|
+ } catch (error) {
|
|
|
+ message.error("解析失败");
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return (
|
|
|
+ <Button
|
|
|
+ type="text"
|
|
|
+ icon={<PlusOutlined />}
|
|
|
+ onClick={handleAdd}
|
|
|
+ >
|
|
|
+ 添加到画布
|
|
|
+ </Button>
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ />
|
|
|
</Typography>
|
|
|
) : (
|
|
|
content
|
|
@@ -112,45 +140,53 @@ export default (props: AICteatorProps) => {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
- const { loading, onRequest, cancel, messages, setMessages, addConversation } =
|
|
|
- useChat({
|
|
|
- app_name: "data_model",
|
|
|
- onSuccess: (msg) => {
|
|
|
- setMessages((messages) => {
|
|
|
- const arr = [...messages];
|
|
|
- const query = arr[messages.length - 2].content as string;
|
|
|
- arr[messages.length - 1].status = "done";
|
|
|
- arr[messages.length - 1].content += `</${assistantType}>`;
|
|
|
- return arr;
|
|
|
- });
|
|
|
- },
|
|
|
- onUpdate: (msg) => {
|
|
|
- setMessages((messages) => {
|
|
|
- const arr = [...messages];
|
|
|
- arr[messages.length - 1].content += msg.answer;
|
|
|
- arr[messages.length - 1].id = msg.message_id;
|
|
|
- arr[messages.length - 1].loading = false;
|
|
|
- arr[messages.length - 1].status = "loading";
|
|
|
- return arr;
|
|
|
- });
|
|
|
- setTimeout(() => {
|
|
|
- const scrollHeight = scrollRef.current?.scrollHeight;
|
|
|
- scrollRef.current?.scrollTo(0, scrollHeight || 0);
|
|
|
- }, 200);
|
|
|
- },
|
|
|
- onError: (error) => {
|
|
|
- message.error(error.message);
|
|
|
- setMessages((messages) => {
|
|
|
- const arr = [...messages];
|
|
|
- arr[messages.length - 1].content = (
|
|
|
- <Typography.Text type="danger">{error.message}</Typography.Text>
|
|
|
- );
|
|
|
- arr[messages.length - 1].status = "error";
|
|
|
- arr[messages.length - 1].loading = false;
|
|
|
- return arr;
|
|
|
- });
|
|
|
- },
|
|
|
- });
|
|
|
+ const {
|
|
|
+ loading,
|
|
|
+ onRequest,
|
|
|
+ cancel,
|
|
|
+ messages,
|
|
|
+ setMessages,
|
|
|
+ addConversation,
|
|
|
+ conversationList,
|
|
|
+ changeConversation,
|
|
|
+ loadingMessages
|
|
|
+ } = useChat({
|
|
|
+ app_name: "data_model",
|
|
|
+ onSuccess: (msg) => {
|
|
|
+ setMessages((messages) => {
|
|
|
+ const arr = [...messages];
|
|
|
+ // const query = arr[messages.length - 2].content as string;
|
|
|
+ arr[messages.length - 1].status = "done";
|
|
|
+ return arr;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ onUpdate: (msg) => {
|
|
|
+ setMessages((messages) => {
|
|
|
+ const arr = [...messages];
|
|
|
+ arr[messages.length - 1].content += msg.answer;
|
|
|
+ arr[messages.length - 1].id = msg.message_id;
|
|
|
+ arr[messages.length - 1].loading = false;
|
|
|
+ arr[messages.length - 1].status = "loading";
|
|
|
+ return arr;
|
|
|
+ });
|
|
|
+ setTimeout(() => {
|
|
|
+ const scrollHeight = scrollRef.current?.scrollHeight;
|
|
|
+ scrollRef.current?.scrollTo(0, scrollHeight || 0);
|
|
|
+ }, 200);
|
|
|
+ },
|
|
|
+ onError: (error) => {
|
|
|
+ message.error(error.message);
|
|
|
+ setMessages((messages) => {
|
|
|
+ const arr = [...messages];
|
|
|
+ arr[messages.length - 1].content = (
|
|
|
+ <Typography.Text type="danger">{error.message}</Typography.Text>
|
|
|
+ );
|
|
|
+ arr[messages.length - 1].status = "error";
|
|
|
+ arr[messages.length - 1].loading = false;
|
|
|
+ return arr;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
|
|
|
const triggerDom = React.cloneElement(props.trigger, {
|
|
|
...props.trigger.props,
|
|
@@ -186,7 +222,7 @@ export default (props: AICteatorProps) => {
|
|
|
},
|
|
|
{
|
|
|
id: Date.now() + "1",
|
|
|
- content: `<${assistantType}>`,
|
|
|
+ content: "",
|
|
|
status: "loading",
|
|
|
role: "assistant",
|
|
|
loading: true,
|
|
@@ -195,7 +231,7 @@ export default (props: AICteatorProps) => {
|
|
|
|
|
|
const query =
|
|
|
assistantType === "generate"
|
|
|
- ? `#角色:你是一个数据模型助手,根据需求部分的描述用生成数据模型工具为用户生成数据模型的json数据,不需要返回其他内容。
|
|
|
+ ? `#角色:你是一个数据模型助手,根据需求部分的描述用生成数据模型工具为用户生成数据模型的json数据。
|
|
|
#需求:${value.trim()}`
|
|
|
: value.trim();
|
|
|
onRequest(query, value.trim());
|
|
@@ -210,11 +246,19 @@ export default (props: AICteatorProps) => {
|
|
|
cancel();
|
|
|
};
|
|
|
|
|
|
+ // 点击提示词
|
|
|
const handlePromptClick = (item: any) => {
|
|
|
const msg = item.data.description || item.data.label;
|
|
|
onSubmit(msg);
|
|
|
};
|
|
|
|
|
|
+ // 点击历史记录
|
|
|
+ const handleOpenHistory = (item: any) => {
|
|
|
+ setOpenHistory(false);
|
|
|
+ changeConversation(item.sessionId);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取样式
|
|
|
const getStyle: React.CSSProperties = useMemo(
|
|
|
() =>
|
|
|
props.position
|
|
@@ -287,54 +331,90 @@ export default (props: AICteatorProps) => {
|
|
|
|
|
|
<Prompts
|
|
|
className="mb-10"
|
|
|
+ title="为您推荐:"
|
|
|
items={items}
|
|
|
vertical
|
|
|
onItemClick={handlePromptClick}
|
|
|
/>
|
|
|
-
|
|
|
- <Bubble.List autoScroll roles={roles} items={messages} />
|
|
|
+ <Spin spinning={loadingMessages}>
|
|
|
+ <Bubble.List autoScroll roles={roles} items={messages} />
|
|
|
+ </Spin>
|
|
|
</div>
|
|
|
- <Sender
|
|
|
- placeholder={
|
|
|
- assistantType === "generate"
|
|
|
- ? "如:创建一个用户表"
|
|
|
- : "请输入咨询问题"
|
|
|
- }
|
|
|
- prefix={
|
|
|
- <Dropdown
|
|
|
- menu={{
|
|
|
- items: [
|
|
|
- {
|
|
|
- key: "1",
|
|
|
- label: "生成实体表",
|
|
|
- onClick: () => {
|
|
|
- setAssistantType("generate");
|
|
|
- addConversation();
|
|
|
+ <div>
|
|
|
+ <div className="flex justify-end">
|
|
|
+ <Button
|
|
|
+ type="text"
|
|
|
+ icon={<PlusOutlined />}
|
|
|
+ onClick={() => addConversation}
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ type="text"
|
|
|
+ icon={<HistoryOutlined />}
|
|
|
+ onClick={() => setOpenHistory(true)}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <Sender
|
|
|
+ placeholder={
|
|
|
+ assistantType === "generate"
|
|
|
+ ? "如:创建一个用户表"
|
|
|
+ : "请输入咨询问题"
|
|
|
+ }
|
|
|
+ prefix={
|
|
|
+ <Dropdown
|
|
|
+ menu={{
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ key: "1",
|
|
|
+ label: "生成实体表",
|
|
|
+ onClick: () => {
|
|
|
+ setAssistantType("generate");
|
|
|
+ addConversation();
|
|
|
+ },
|
|
|
},
|
|
|
- },
|
|
|
- {
|
|
|
- key: "2",
|
|
|
- label: "咨询聊天",
|
|
|
- onClick: () => {
|
|
|
- setAssistantType("chat");
|
|
|
- addConversation();
|
|
|
+ {
|
|
|
+ key: "2",
|
|
|
+ label: "咨询聊天",
|
|
|
+ onClick: () => {
|
|
|
+ setAssistantType("chat");
|
|
|
+ addConversation();
|
|
|
+ },
|
|
|
},
|
|
|
- },
|
|
|
- ],
|
|
|
- }}
|
|
|
+ ],
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Button type="text" className="w-80px">
|
|
|
+ {assistantType === "generate" ? "生成实体表" : "咨询聊天"}
|
|
|
+ </Button>
|
|
|
+ </Dropdown>
|
|
|
+ }
|
|
|
+ loading={loading}
|
|
|
+ value={input}
|
|
|
+ onChange={setInput}
|
|
|
+ onSubmit={onSubmit}
|
|
|
+ onCancel={onStop}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Drawer
|
|
|
+ title="历史记录"
|
|
|
+ open={openHistory}
|
|
|
+ onClose={() => setOpenHistory(false)}
|
|
|
+ placement="right"
|
|
|
+ getContainer={false}
|
|
|
+ >
|
|
|
+ <List
|
|
|
+ dataSource={conversationList}
|
|
|
+ renderItem={(item) => (
|
|
|
+ <List.Item
|
|
|
+ className="px-12px hover:bg-gray-50 cursor-pointer"
|
|
|
+ key={item.id}
|
|
|
+ onClick={() => handleOpenHistory(item)}
|
|
|
>
|
|
|
- <Button type="text" className="w-80px">
|
|
|
- {assistantType === "generate" ? "生成实体表" : "咨询聊天"}
|
|
|
- </Button>
|
|
|
- </Dropdown>
|
|
|
- }
|
|
|
- loading={loading}
|
|
|
- value={input}
|
|
|
- onChange={setInput}
|
|
|
- onSubmit={onSubmit}
|
|
|
- onCancel={onStop}
|
|
|
+ {item.label}
|
|
|
+ </List.Item>
|
|
|
+ )}
|
|
|
/>
|
|
|
- </div>
|
|
|
+ </Drawer>
|
|
|
</Modal>
|
|
|
</>
|
|
|
);
|