From 4d421ddfed1b725eabbed81eab113b4e440517c1 Mon Sep 17 00:00:00 2001
From: jialh <1972868360@qq.com>
Date: 星期二, 10 六月 2025 14:49:14 +0800
Subject: [PATCH] 备份
---
src/components/AiProChat/AiProChat.tsx | 270 ++++++++++++++++++++++++------------------------------
1 files changed, 120 insertions(+), 150 deletions(-)
diff --git a/src/components/AiProChat/AiProChat.tsx b/src/components/AiProChat/AiProChat.tsx
index 66caa01..f0c156f 100644
--- a/src/components/AiProChat/AiProChat.tsx
+++ b/src/components/AiProChat/AiProChat.tsx
@@ -15,17 +15,8 @@
import remarkBreaks from "remark-breaks";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
-import rehypeHighlight from "rehype-highlight";
-import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
-import { ghcolors } from "react-syntax-highlighter/dist/esm/styles/prism";
import logo from "/favicon.png";
import "./markdown-styles.css";
-
-const codeStyle: Record<string, React.CSSProperties> = {
- ...(Object.fromEntries(
- Object.entries(ghcolors).filter(([key]) => typeof key === "string")
- ) as Record<string, React.CSSProperties>),
-};
const loadMermaid = () => {
if (typeof window !== "undefined" && !(window as any).mermaid) {
@@ -63,10 +54,10 @@
botAvatar?: string;
request: (messages: ChatMessage[]) => Promise<Response>;
clearMessage?: () => void;
- botId?: string; // 鏂板 botId 鍙傛暟
+ botId?: string;
botTypeId?: number;
- onFileUploaded?: (fileId: string) => void; // 鏂板鏂囦欢涓婁紶鍥炶皟
- onFileRemoved?: (removedFileId?: string) => void; // 鏂板鏂囦欢鍒犻櫎鍥炶皟
+ onFileUploaded?: (fileId: string) => void;
+ onFileRemoved?: (removedFileId?: string) => void;
};
export const AiProChat = ({
@@ -79,10 +70,10 @@
botAvatar = `${logo}`,
request,
clearMessage,
- botId, // 鏂板
+ botId,
botTypeId,
- onFileUploaded, // 鏂板
- onFileRemoved, // 鏂板
+ onFileUploaded,
+ onFileRemoved,
}: AiProChatProps) => {
const isControlled =
parentChats !== undefined && parentOnChatsChange !== undefined;
@@ -110,38 +101,34 @@
}
}, [chats]);
-
const handleRemoveFile = (name: string) => {
- const fileToRemove = fileList.find(f => f.name === name);
+ const fileToRemove = fileList.find((f) => f.name === name);
console.log("handleRemoveFile", fileToRemove);
-
+
if (!fileToRemove) return;
-
- const newUploadedFiles = uploadedFiles.filter(f => f !== name);
- const newFileList = fileList.filter(f => f.name !== name);
-
+
+ const newUploadedFiles = uploadedFiles.filter((f) => f !== name);
+ const newFileList = fileList.filter((f) => f.name !== name);
+
setUploadedFiles(newUploadedFiles);
setFileList(newFileList);
-
- // 纭繚浼犻�掔殑鏄枃浠剁殑 url (鍗虫枃浠禝D)
+
if (fileToRemove.url) {
onFileRemoved?.(fileToRemove.url);
}
};
-
const handleUpload = async (file: File) => {
if (botTypeId === 2 && uploadedFiles.length >= 1) {
messageApi.warning("鍙兘涓婁紶涓�涓枃浠讹紝璇峰垹闄ゅ凡涓婁紶鏂囦欢");
return false;
}
- // 澶氭枃浠舵ā寮忔鏌ワ紙鍋囪闄愬埗鏈�澶�5涓枃浠讹級
if (botTypeId === 3 && uploadedFiles.length >= 5) {
messageApi.warning("鏈�澶氬彧鑳戒笂浼�5涓枃浠�");
return false;
}
- setFileList(prev => [
+ setFileList((prev) => [
...prev,
{
uid: file.name,
@@ -149,7 +136,7 @@
status: "uploading",
},
]);
-
+
const formData = new FormData();
const tokenKey = `${import.meta.env.VITE_APP_TOKEN_KEY}`;
formData.append("file", file);
@@ -167,9 +154,9 @@
const result = await res.json();
const fileData = JSON.parse(result.data.trim());
- setFileList(prev =>
- prev.map(f =>
- f.name === file.name
+ setFileList((prev) =>
+ prev.map((f) =>
+ f.name === file.name
? { ...f, uid: fileData.name, status: "done", url: fileData.id }
: f
)
@@ -177,17 +164,12 @@
setUploadedFiles((prev) => [...prev, fileData.name]);
messageApi.success(`${fileData.name} 涓婁紶鎴愬姛`);
- // 璋冪敤鍥炶皟鍑芥暟浼犻�掓枃浠禝D
onFileUploaded?.(fileData.id);
return fileData;
} catch (error) {
- setFileList(prev =>
- prev.map(f =>
- f.name === file.name
- ? { ...f, status: "error" }
- : f
- )
+ setFileList((prev) =>
+ prev.map((f) => (f.name === file.name ? { ...f, status: "error" } : f))
);
messageApi.error((error as Error).message || "涓婁紶澶辫触");
throw error;
@@ -368,122 +350,113 @@
}
};
- const renderMessages = () => {
- if (!chats?.length) {
- return (
- <Welcome
- variant="borderless"
- icon={
+ // 淇敼 renderMessages 鍑芥暟涓殑 ReactMarkdown 閮ㄥ垎
+const renderMessages = () => {
+ if (!chats?.length) {
+ return (
+ <Welcome
+ variant="borderless"
+ icon={
+ <img
+ src={botAvatar}
+ style={{ width: 32, height: 32, borderRadius: "50%" }}
+ alt="AI Avatar"
+ />
+ }
+ description={helloMessage}
+ styles={{ icon: { width: 40, height: 40 } }}
+ />
+ );
+ }
+ return (
+ <Bubble.List
+ autoScroll={true}
+ items={chats.map((chat, index) => ({
+ key: chat.id + Math.random().toString(),
+ typing: { suffix: <>馃挆</> },
+ header: <Space>{new Date(chat.created).toLocaleString()}</Space>,
+ loading: chat.loading,
+ loadingRender: () => (
+ <Space>
+ <Spin size="small" />
+ AI姝e湪鎬濊�冧腑...
+ </Space>
+ ),
+ footer: (
+ <Space>
+ {chat.role === "assistant" && (
+ <Button
+ color="default"
+ variant="text"
+ size="small"
+ icon={<SyncOutlined />}
+ onClick={() => handleRegenerate(index)}
+ />
+ )}
+ <Button
+ color="default"
+ variant="text"
+ size="small"
+ icon={<CopyOutlined />}
+ onClick={async () => {
+ try {
+ await navigator.clipboard.writeText(chat.content);
+ message.success("澶嶅埗鎴愬姛");
+ } catch (error) {
+ message.error("澶嶅埗澶辫触");
+ }
+ }}
+ />
+ </Space>
+ ),
+ role: chat.role === "user" ? "local" : "ai",
+ content: (
+ <div className="markdown-body">
+ {chat.role === "assistant" ? (
+ <ReactMarkdown
+ remarkPlugins={[remarkGfm, remarkBreaks]}
+ rehypePlugins={[rehypeRaw, rehypeSanitize]}
+ components={{
+ code({ node, className, children, ...props }) {
+ const match = /language-(\w+)/.exec(className || "");
+ return match ? (
+ <pre className={className} {...props as React.HTMLAttributes<HTMLPreElement>}>
+ <code>{children}</code>
+ </pre>
+ ) : (
+ <code className={className} {...props as React.HTMLAttributes<HTMLElement>}>
+ {children}
+ </code>
+ );
+ },
+ }}
+ >
+ {chat.content}
+ </ReactMarkdown>
+ ) : (
+ chat.content
+ )}
+ </div>
+ ),
+ avatar:
+ chat.role === "assistant" ? (
<img
src={botAvatar}
style={{ width: 32, height: 32, borderRadius: "50%" }}
alt="AI Avatar"
/>
- }
- description={helloMessage}
- styles={{ icon: { width: 40, height: 40 } }}
- />
- );
- }
- return (
- <Bubble.List
- autoScroll={true}
- items={chats.map((chat, index) => ({
- key: chat.id + Math.random().toString(),
- typing: { suffix: <>馃挆</> },
- header: <Space>{new Date(chat.created).toLocaleString()}</Space>,
- loading: chat.loading,
- loadingRender: () => (
- <Space>
- <Spin size="small" />
- AI姝e湪鎬濊�冧腑...
- </Space>
+ ) : (
+ {
+ icon: <UserOutlined />,
+ style: { color: "#fff", backgroundColor: "#87d068" },
+ }
),
- footer: (
- <Space>
- {chat.role === "assistant" && (
- <Button
- color="default"
- variant="text"
- size="small"
- icon={<SyncOutlined />}
- onClick={() => handleRegenerate(index)}
- />
- )}
- <Button
- color="default"
- variant="text"
- size="small"
- icon={<CopyOutlined />}
- onClick={async () => {
- try {
- await navigator.clipboard.writeText(chat.content);
- message.success("澶嶅埗鎴愬姛");
- } catch (error) {
- message.error("澶嶅埗澶辫触");
- }
- }}
- />
- </Space>
- ),
- role: chat.role === "user" ? "local" : "ai",
- content: (
- <div className="markdown-body">
- {chat.role === "assistant" ? (
- <ReactMarkdown
- remarkPlugins={[remarkGfm, remarkBreaks]}
- rehypePlugins={[rehypeRaw, rehypeSanitize, rehypeHighlight]}
- components={{
- code({ node, className, children, ...props }) {
- const match = /language-(\w+)/.exec(className || "");
- const isInline = !!(
- node?.position?.start &&
- node.position.end &&
- node.position.start.line === node.position.end.line
- );
+ }))}
+ roles={{ ai: { placement: "start" }, local: { placement: "end" } }}
+ />
+ );
+};
- return !isInline ? (
- <SyntaxHighlighter
- language={match?.[1] || "text"}
- style={codeStyle as { [key: string]: React.CSSProperties }}
- PreTag="div"
- {...props}
- >
- {String(children).replace(/\n$/, "")}
- </SyntaxHighlighter>
- ) : (
- <code className={className} {...props}>
- {children}
- </code>
- );
- },
- }}
- >
- {chat.content}
- </ReactMarkdown>
- ) : (
- chat.content
- )}
- </div>
- ),
- avatar:
- chat.role === "assistant" ? (
- <img
- src={botAvatar}
- style={{ width: 32, height: 32, borderRadius: "50%" }}
- alt="AI Avatar"
- />
- ) : (
- {
- icon: <UserOutlined />,
- style: { color: "#fff", backgroundColor: "#87d068" },
- }
- ),
- }))}
- roles={{ ai: { placement: "start" }, local: { placement: "end" } }}
- />
- );
- };
return (
<div
@@ -552,15 +525,12 @@
>
{name}
</span>
- {/* 娣诲姞鍒犻櫎鎸夐挳 */}
<Button
type="text"
size="small"
icon={<DeleteOutlined />}
onClick={() => {
handleRemoveFile(name);
- // setUploadedFiles(uploadedFiles.filter((f) => f !== name));
- // setFileList(fileList.filter((f) => f.name !== name));
}}
/>
</div>
--
Gitblit v1.8.0