|
@@ -55,6 +55,7 @@ const ChatComponent: React.FC<ChatComponentProps> = ({ messageList, onClose }) =
|
|
|
boxShadow: "0 1px 2px rgba(0,0,0,0.1)",
|
|
boxShadow: "0 1px 2px rgba(0,0,0,0.1)",
|
|
|
maxWidth: "70%",
|
|
maxWidth: "70%",
|
|
|
wordWrap: "break-word",
|
|
wordWrap: "break-word",
|
|
|
|
|
+ position: "relative", // 为伪元素定位做准备
|
|
|
} as React.CSSProperties;
|
|
} as React.CSSProperties;
|
|
|
|
|
|
|
|
const contentStyle = {
|
|
const contentStyle = {
|
|
@@ -62,6 +63,7 @@ const ChatComponent: React.FC<ChatComponentProps> = ({ messageList, onClose }) =
|
|
|
lineHeight: "1.5",
|
|
lineHeight: "1.5",
|
|
|
fontSize: "14px",
|
|
fontSize: "14px",
|
|
|
textAlign: "left",
|
|
textAlign: "left",
|
|
|
|
|
+ paddingTop: "5px",
|
|
|
} as React.CSSProperties;
|
|
} as React.CSSProperties;
|
|
|
|
|
|
|
|
const attachmentContainerStyle = {
|
|
const attachmentContainerStyle = {
|
|
@@ -126,48 +128,75 @@ const ChatComponent: React.FC<ChatComponentProps> = ({ messageList, onClose }) =
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
{messageList.map((msg) => (
|
|
{messageList.map((msg) => (
|
|
|
- <div
|
|
|
|
|
- key={msg.id}
|
|
|
|
|
- style={{
|
|
|
|
|
- ...baseMessageStyle,
|
|
|
|
|
- justifyContent: msg.sender === "other"? "flex-start" : "flex-end",
|
|
|
|
|
- display: "flex",
|
|
|
|
|
- flexDirection: "column",
|
|
|
|
|
- alignItems: msg.sender === "other"? "flex-start" : "flex-end",
|
|
|
|
|
- paddingLeft: "40px",
|
|
|
|
|
- }}
|
|
|
|
|
- >
|
|
|
|
|
- {/* 根据发送方显示对应的名称和图标 */}
|
|
|
|
|
- {msg.sender === "other" && (
|
|
|
|
|
- <div style={senderInfoStyle}>
|
|
|
|
|
- <img
|
|
|
|
|
- src="/partner.png"
|
|
|
|
|
- alt="AAA株式会社图标"
|
|
|
|
|
- style={iconStyle}
|
|
|
|
|
- />
|
|
|
|
|
- <span style={senderNameStyle}>AAA株式会社</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- )}
|
|
|
|
|
- {msg.sender === "me" && (
|
|
|
|
|
- <div style={senderInfoStyle}>
|
|
|
|
|
- <span style={senderNameStyle}>羽田ベース</span>
|
|
|
|
|
- <img
|
|
|
|
|
- src="/base.png"
|
|
|
|
|
- alt="羽田ベース图标"
|
|
|
|
|
- style={{...iconStyle, marginLeft: "4px", marginRight: "0" }}
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- )}
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ key={msg.id}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ ...baseMessageStyle,
|
|
|
|
|
+ justifyContent: msg.sender === "other"? "flex-start" : "flex-end",
|
|
|
|
|
+ display: "flex",
|
|
|
|
|
+ flexDirection: "column",
|
|
|
|
|
+ alignItems: msg.sender === "other"? "flex-start" : "flex-end",
|
|
|
|
|
+ paddingLeft: "40px",
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {msg.sender === "other" && (
|
|
|
|
|
+ <div style={senderInfoStyle}>
|
|
|
|
|
+ <img
|
|
|
|
|
+ src="/partner.png"
|
|
|
|
|
+ alt="AAA株式会社图标"
|
|
|
|
|
+ style={iconStyle}
|
|
|
|
|
+ />
|
|
|
|
|
+ <span style={senderNameStyle}>AAA株式会社</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {msg.sender === "me" && (
|
|
|
|
|
+ <div style={senderInfoStyle}>
|
|
|
|
|
+ <span style={senderNameStyle}>羽田ベース</span>
|
|
|
|
|
+ <img
|
|
|
|
|
+ src="/base.png"
|
|
|
|
|
+ alt="羽田ベース图标"
|
|
|
|
|
+ style={{...iconStyle, marginLeft: "4px", marginRight: "0" }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
|
|
|
- {/*聊天内容气泡:内容非空时才显示 */}
|
|
|
|
|
- {msg.content.trim()!== "" && (
|
|
|
|
|
|
|
+ {msg.content.trim()!== "" && (
|
|
|
<div
|
|
<div
|
|
|
style={{
|
|
style={{
|
|
|
- ...bubbleStyle,
|
|
|
|
|
|
|
+ ...bubbleStyle,
|
|
|
backgroundColor: msg.sender === "other"? "#d9d9d9" : "#deebf7",
|
|
backgroundColor: msg.sender === "other"? "#d9d9d9" : "#deebf7",
|
|
|
marginBottom: "4px",
|
|
marginBottom: "4px",
|
|
|
|
|
+ marginTop: "15px",
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
|
|
+ {msg.sender === "other" && (
|
|
|
|
|
+ <div
|
|
|
|
|
+ style={{
|
|
|
|
|
+ content: '""',
|
|
|
|
|
+ position: "absolute",
|
|
|
|
|
+ left: "12px",
|
|
|
|
|
+ top: "-23px",
|
|
|
|
|
+ borderTop: "20px solid transparent",
|
|
|
|
|
+ borderBottom: "20px solid transparent",
|
|
|
|
|
+ borderLeft: "15px solid #d9d9d9",
|
|
|
|
|
+ transform: "translateY(20%)",
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
|
|
+ {msg.sender === "me" && (
|
|
|
|
|
+ <div
|
|
|
|
|
+ style={{
|
|
|
|
|
+ content: '""',
|
|
|
|
|
+ position: "absolute",
|
|
|
|
|
+ right: "12px",
|
|
|
|
|
+ top: "-23px",
|
|
|
|
|
+ borderTop: "20px solid transparent",
|
|
|
|
|
+ borderBottom: "20px solid transparent",
|
|
|
|
|
+ borderRight: "15px solid #deebf7",
|
|
|
|
|
+ transform: "translateY(20%)",
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
<div style={contentStyle}>
|
|
<div style={contentStyle}>
|
|
|
{msg.content.split("\n").map((line, index) => (
|
|
{msg.content.split("\n").map((line, index) => (
|
|
|
<React.Fragment key={index}>
|
|
<React.Fragment key={index}>
|
|
@@ -178,7 +207,6 @@ const ChatComponent: React.FC<ChatComponentProps> = ({ messageList, onClose }) =
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
|
-
|
|
|
|
|
{/* 附件区域 */}
|
|
{/* 附件区域 */}
|
|
|
{msg.attachment && (
|
|
{msg.attachment && (
|
|
|
<div style={attachmentContainerStyle}>
|
|
<div style={attachmentContainerStyle}>
|
|
@@ -194,11 +222,10 @@ const ChatComponent: React.FC<ChatComponentProps> = ({ messageList, onClose }) =
|
|
|
</a>
|
|
</a>
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
|
-
|
|
|
|
|
{/* 时间戳 */}
|
|
{/* 时间戳 */}
|
|
|
<div
|
|
<div
|
|
|
style={{
|
|
style={{
|
|
|
- ...timestampStyle,
|
|
|
|
|
|
|
+ ...timestampStyle,
|
|
|
marginLeft: msg.sender === "other"? "10px" : "0",
|
|
marginLeft: msg.sender === "other"? "10px" : "0",
|
|
|
marginRight: msg.sender === "me"? "10px" : "0",
|
|
marginRight: msg.sender === "me"? "10px" : "0",
|
|
|
textAlign: msg.sender === "other"? "left" : "right",
|
|
textAlign: msg.sender === "other"? "left" : "right",
|
|
@@ -208,7 +235,6 @@ const ChatComponent: React.FC<ChatComponentProps> = ({ messageList, onClose }) =
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
))}
|
|
))}
|
|
|
-
|
|
|
|
|
{/* 用于自动滚动的参考点 */}
|
|
{/* 用于自动滚动的参考点 */}
|
|
|
<div ref={messagesEndRef} />
|
|
<div ref={messagesEndRef} />
|
|
|
</div>
|
|
</div>
|
|
@@ -249,12 +275,12 @@ const InputArea: React.FC<{ onSendMessage: (content: string, file: File | null)
|
|
|
<div
|
|
<div
|
|
|
style={{
|
|
style={{
|
|
|
width: "100%",
|
|
width: "100%",
|
|
|
- maxWidth: "600px",
|
|
|
|
|
- margin: "0 auto",
|
|
|
|
|
|
|
+ margin: "0",
|
|
|
padding: "16px",
|
|
padding: "16px",
|
|
|
display: "flex",
|
|
display: "flex",
|
|
|
flexDirection: "column",
|
|
flexDirection: "column",
|
|
|
gap: "8px",
|
|
gap: "8px",
|
|
|
|
|
+ boxSizing: "border-box",
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
<textarea
|
|
<textarea
|
|
@@ -269,6 +295,7 @@ const InputArea: React.FC<{ onSendMessage: (content: string, file: File | null)
|
|
|
borderRadius: "4px",
|
|
borderRadius: "4px",
|
|
|
border: "1px solid #ccc",
|
|
border: "1px solid #ccc",
|
|
|
resize: "none",
|
|
resize: "none",
|
|
|
|
|
+ boxSizing: "border-box",
|
|
|
}}
|
|
}}
|
|
|
/>
|
|
/>
|
|
|
{selectedFile && (
|
|
{selectedFile && (
|
|
@@ -376,6 +403,7 @@ const initialMessages: ChatMessage[] = [
|
|
|
},
|
|
},
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
|
|
+
|
|
|
const Chat: React.FC<ChatProps> = ({ onClose }) => {
|
|
const Chat: React.FC<ChatProps> = ({ onClose }) => {
|
|
|
const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);
|
|
const [messages, setMessages] = useState<ChatMessage[]>(initialMessages);
|
|
|
|
|
|
|
@@ -385,15 +413,15 @@ const Chat: React.FC<ChatProps> = ({ onClose }) => {
|
|
|
sender: "me",
|
|
sender: "me",
|
|
|
content,
|
|
content,
|
|
|
timestamp: new Date()
|
|
timestamp: new Date()
|
|
|
- .toLocaleString("ja-JP", {
|
|
|
|
|
|
|
+ .toLocaleString("ja-JP", {
|
|
|
year: "numeric",
|
|
year: "numeric",
|
|
|
month: "long",
|
|
month: "long",
|
|
|
day: "numeric",
|
|
day: "numeric",
|
|
|
hour: "2-digit",
|
|
hour: "2-digit",
|
|
|
minute: "2-digit",
|
|
minute: "2-digit",
|
|
|
})
|
|
})
|
|
|
- .replace(/[年月]/g, "-")
|
|
|
|
|
- .replace("日", ""),
|
|
|
|
|
|
|
+ .replace(/[年月]/g, "-")
|
|
|
|
|
+ .replace("日", ""),
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
if (file) {
|
|
if (file) {
|
|
@@ -407,8 +435,19 @@ const Chat: React.FC<ChatProps> = ({ onClose }) => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
- <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
|
|
|
|
- <div className="chat-messages-container">
|
|
|
|
|
|
|
+ <div style={{
|
|
|
|
|
+ height: '100%',
|
|
|
|
|
+ display: 'flex',
|
|
|
|
|
+ flexDirection: 'column',
|
|
|
|
|
+ margin: 0,
|
|
|
|
|
+ padding: 0
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <div className="chat-messages-container" style={{
|
|
|
|
|
+ padding: '16px',
|
|
|
|
|
+ boxSizing: 'border-box',
|
|
|
|
|
+ flex: 1,
|
|
|
|
|
+ overflow: 'auto'
|
|
|
|
|
+ }}>
|
|
|
<ChatComponent messageList={messages} onClose={onClose} />
|
|
<ChatComponent messageList={messages} onClose={onClose} />
|
|
|
</div>
|
|
</div>
|
|
|
<InputArea onSendMessage={handleSendMessage} />
|
|
<InputArea onSendMessage={handleSendMessage} />
|
|
@@ -417,4 +456,3 @@ const Chat: React.FC<ChatProps> = ({ onClose }) => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export default Chat;
|
|
export default Chat;
|
|
|
-
|
|
|