|
@@ -2,9 +2,14 @@ import { useCallback, useState } from "react";
|
|
|
import { Message } from "./AiChat";
|
|
import { Message } from "./AiChat";
|
|
|
import Marked from "../general/Marked";
|
|
import Marked from "../general/Marked";
|
|
|
import TextArea from "antd/lib/input/TextArea";
|
|
import TextArea from "antd/lib/input/TextArea";
|
|
|
-import { Button, Space } from "antd";
|
|
|
|
|
|
|
+import { Button, message, Space, Tooltip } from "antd";
|
|
|
|
|
|
|
|
-import { CheckOutlined, CloseOutlined } from "@ant-design/icons";
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ CheckOutlined,
|
|
|
|
|
+ CloseOutlined,
|
|
|
|
|
+ CopyOutlined,
|
|
|
|
|
+ EditOutlined,
|
|
|
|
|
+} from "@ant-design/icons";
|
|
|
|
|
|
|
|
interface IWidget {
|
|
interface IWidget {
|
|
|
msg?: Message;
|
|
msg?: Message;
|
|
@@ -13,11 +18,10 @@ interface IWidget {
|
|
|
|
|
|
|
|
const MsgUser = ({ msg, onChange }: IWidget) => {
|
|
const MsgUser = ({ msg, onChange }: IWidget) => {
|
|
|
const [editing, setEditing] = useState(false);
|
|
const [editing, setEditing] = useState(false);
|
|
|
- const [content, setContent] = useState("");
|
|
|
|
|
|
|
+ const [content, setContent] = useState(msg?.content ?? "");
|
|
|
|
|
|
|
|
const confirmEdit = useCallback((): void => {
|
|
const confirmEdit = useCallback((): void => {
|
|
|
onChange && onChange(content);
|
|
onChange && onChange(content);
|
|
|
- setContent("");
|
|
|
|
|
}, [content, onChange]);
|
|
}, [content, onChange]);
|
|
|
|
|
|
|
|
const cancelEdit = useCallback((): void => {
|
|
const cancelEdit = useCallback((): void => {
|
|
@@ -36,49 +40,106 @@ const MsgUser = ({ msg, onChange }: IWidget) => {
|
|
|
[cancelEdit, confirmEdit]
|
|
[cancelEdit, confirmEdit]
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- return editing ? (
|
|
|
|
|
- <div>
|
|
|
|
|
- <TextArea
|
|
|
|
|
- value={content}
|
|
|
|
|
- onChange={(e) => setContent(e.target.value)}
|
|
|
|
|
- onKeyPress={handleEditKeyPress}
|
|
|
|
|
- autoSize={{ minRows: 2, maxRows: 8 }}
|
|
|
|
|
- style={{ marginBottom: "8px" }}
|
|
|
|
|
- />
|
|
|
|
|
- <Space size="small">
|
|
|
|
|
- <Button
|
|
|
|
|
- size="small"
|
|
|
|
|
- type="primary"
|
|
|
|
|
- icon={<CheckOutlined />}
|
|
|
|
|
- onClick={confirmEdit}
|
|
|
|
|
- >
|
|
|
|
|
- 确认
|
|
|
|
|
- </Button>
|
|
|
|
|
- <Button size="small" icon={<CloseOutlined />} onClick={cancelEdit}>
|
|
|
|
|
- 取消
|
|
|
|
|
- </Button>
|
|
|
|
|
- </Space>
|
|
|
|
|
- </div>
|
|
|
|
|
- ) : (
|
|
|
|
|
- <div>
|
|
|
|
|
- <div
|
|
|
|
|
- style={{
|
|
|
|
|
- fontSize: "14px",
|
|
|
|
|
- lineHeight: "1.5",
|
|
|
|
|
- whiteSpace: "pre-wrap",
|
|
|
|
|
- wordBreak: "break-word",
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- <Marked text={msg?.content} />
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div
|
|
|
|
|
+ style={{
|
|
|
|
|
+ display: "flex",
|
|
|
|
|
+ justifyContent: "flex-end",
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
<div
|
|
<div
|
|
|
style={{
|
|
style={{
|
|
|
- fontSize: "12px",
|
|
|
|
|
- opacity: 0.6,
|
|
|
|
|
- marginTop: "8px",
|
|
|
|
|
|
|
+ maxWidth: "70%",
|
|
|
|
|
+ backgroundColor: "rgba(0.7,0.7,0.7,0.1)",
|
|
|
|
|
+ color: "black",
|
|
|
|
|
+ borderRadius: "8px",
|
|
|
|
|
+ padding: "16px",
|
|
|
|
|
+ border: "none",
|
|
|
|
|
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.03)",
|
|
|
|
|
+ textAlign: "left",
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
- {msg?.timestamp}
|
|
|
|
|
|
|
+ {editing ? (
|
|
|
|
|
+ <div style={{ width: "100%" }}>
|
|
|
|
|
+ <TextArea
|
|
|
|
|
+ value={content}
|
|
|
|
|
+ onChange={(e) => setContent(e.target.value)}
|
|
|
|
|
+ onKeyPress={handleEditKeyPress}
|
|
|
|
|
+ autoSize={{ minRows: 2, maxRows: 8 }}
|
|
|
|
|
+ style={{ marginBottom: "8px", width: "100%" }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Space size="small">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ icon={<CheckOutlined />}
|
|
|
|
|
+ onClick={() => confirmEdit()}
|
|
|
|
|
+ >
|
|
|
|
|
+ 确认
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ icon={<CloseOutlined />}
|
|
|
|
|
+ onClick={cancelEdit}
|
|
|
|
|
+ >
|
|
|
|
|
+ 取消
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Space>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: "14px",
|
|
|
|
|
+ lineHeight: "1.5",
|
|
|
|
|
+ whiteSpace: "pre-wrap",
|
|
|
|
|
+ wordBreak: "break-word",
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Marked text={msg?.content} />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: "12px",
|
|
|
|
|
+ opacity: 0.6,
|
|
|
|
|
+ marginTop: "8px",
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {msg?.timestamp}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Space size="small">
|
|
|
|
|
+ <Tooltip title="复制">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ icon={<CopyOutlined />}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ msg &&
|
|
|
|
|
+ navigator.clipboard
|
|
|
|
|
+ .writeText(msg.content)
|
|
|
|
|
+ .then((value) => message.success("已复制到剪贴板"))
|
|
|
|
|
+ .catch((reason: any) => {
|
|
|
|
|
+ console.error("复制失败:", reason);
|
|
|
|
|
+ message.error("复制失败");
|
|
|
|
|
+ });
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ <Tooltip title="复制">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ icon={<EditOutlined />}
|
|
|
|
|
+ onClick={() => {
|
|
|
|
|
+ msg && setEditing(true);
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ </Space>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|