feat:dify聊天页面接入消息反馈、复制功能

This commit is contained in:
PingChuan
2025-12-10 21:57:43 +08:00
parent ba517d7b9c
commit 38c57f7acc
3 changed files with 116 additions and 5 deletions
+53 -1
View File
@@ -1,4 +1,5 @@
import { Button, Card, Spin } from 'antd';
import { LikeOutlined, LikeFilled, DislikeOutlined, DislikeFilled, CopyOutlined } from '@ant-design/icons';
import { Button, Card, Spin, Tooltip } from 'antd';
import { useState } from 'react';
import type { ChatItem, Feedbacktype } from '~/api/dify-chat';
import '../../styles/components/chat-with-llm/chat-message.css';
@@ -26,6 +27,20 @@ export default function ChatMessage({
const [feedback, setFeedback] = useState<'like' | 'dislike' | null>(
message.feedback?.rating || null
);
const [copied, setCopied] = useState(false);
/**
* 处理复制
*/
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(content);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (err) {
console.error('复制失败:', err);
}
};
const { id, content, isAnswer, agent_thoughts, message_files, isOpeningStatement, suggestedQuestions, more, retriever_resources } = message;
const isAgentMode = !!agent_thoughts && agent_thoughts.length > 0;
@@ -168,6 +183,13 @@ export default function ChatMessage({
);
}
// 判断是否可以显示反馈按钮(AI回答、非占位符、非正在响应)
const canShowFeedback = isAnswer &&
!id.startsWith('placeholder-') &&
!id.startsWith('opening-') &&
!id.startsWith('response-') &&
!isResponding;
return (
<div className="chat-message">
<div className={`flex ${isAnswer ? 'justify-start' : 'justify-end'} mb-2`}>
@@ -184,6 +206,36 @@ export default function ChatMessage({
)}
</div>
</div>
{/* 反馈按钮 - 仅在AI回答且非占位符时显示 */}
{canShowFeedback && (
<div className="message-feedback">
<Tooltip title={copied ? '已复制' : '复制'}>
<Button
size="small"
type="text"
icon={<CopyOutlined />}
onClick={handleCopy}
className={copied ? 'message-copy-btn copied' : 'message-copy-btn'}
/>
</Tooltip>
<div className="feedback-actions-right">
<Button
size="small"
type="text"
icon={feedback === 'like' ? <LikeFilled /> : <LikeOutlined />}
onClick={() => handleFeedback('like')}
className={feedback === 'like' ? 'feedback-active-like' : ''}
/>
<Button
size="small"
type="text"
icon={feedback === 'dislike' ? <DislikeFilled /> : <DislikeOutlined />}
onClick={() => handleFeedback('dislike')}
className={feedback === 'dislike' ? 'feedback-active-dislike' : ''}
/>
</div>
</div>
)}
</Card>
</div>
</div>