Skip to content

Commit 480872d

Browse files
author
User
committed
更新前端展示
1 parent 0989505 commit 480872d

14 files changed

Lines changed: 575 additions & 438 deletions

README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,19 +1285,37 @@ GET http://localhost:8000/sessions/{session_id}/summary
12851285

12861286
### 首页界面
12871287

1288-
![首页界面](image/首页界面.png)
1288+
<p align="center">
1289+
<img src="image/首页界面.png" alt="首页界面" width="800"/>
1290+
</p>
12891291

12901292
现代化的聊天界面设计,包含:
1291-
- 情感标签可视化
1292-
- 建议按钮快速回复
1293-
- 流畅的动画效果
1294-
- 响应式设计,支持移动端
1293+
- 🎭 **情感标签可视化** - 实时显示AI识别的情感状态
1294+
- 💬 **建议按钮快速回复** - 智能推荐回复选项
1295+
- ⌨️ **打字机效果** - 根据情绪动态调整打字速度和光标颜色
1296+
- 🎨 **流畅的动画效果** - Framer Motion 驱动的交互动画
1297+
- 📱 **响应式设计** - 完美支持移动端访问
1298+
- 🔄 **会话管理** - 支持多会话切换和历史记录
12951299

12961300
### AI形象定制
12971301

1298-
![AI形象定制](image/AI形象定制.png)
1302+
<p align="center">
1303+
<img src="image/AI形象定制.png" alt="AI形象定制" width="800"/>
1304+
</p>
12991305

1300-
个性化AI形象定制功能,让AI陪伴更加生动有趣。
1306+
个性化AI形象定制功能,支持:
1307+
- 🤖 **AI性格设置** - 选择温柔、活泼、专业等不同性格风格
1308+
- 💬 **对话风格** - 调整回复长度、语气和表达方式
1309+
-**响应速度** - 自定义打字机效果速度
1310+
- 🎨 **主题定制** - 个性化界面主题和配色
1311+
- 📝 **偏好记忆** - 自动保存用户偏好设置
1312+
1313+
### 侧边栏功能
1314+
1315+
- 📜 **会话历史** - 查看和管理历史对话
1316+
-**新建会话** - 一键开启新对话
1317+
- ⚙️ **设置入口** - 快速访问个性化设置
1318+
- 📊 **情感趋势** - 查看情感变化统计
13011319

13021320
## 🔮 未来规划
13031321

frontend/src/components/ChatContainer.js

Lines changed: 121 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import { AnimatePresence } from 'framer-motion';
3-
import { Heart, User, Bot, Loader2, Paperclip, Send, Link, ExternalLink, X, MessageSquarePlus } from 'lucide-react';
3+
import { User, Bot, Loader2, Paperclip, Send, Link, ExternalLink, X, Sparkles, Mic, PenLine, Image, Music, Languages, Presentation, MoreHorizontal } from 'lucide-react';
44
import {
55
ChatContainer as ChatContainerStyled,
6-
Header,
7-
Title,
8-
Subtitle,
96
MessagesContainer,
107
MessageBubble,
118
Avatar,
@@ -19,9 +16,15 @@ import {
1916
SuggestionChip,
2017
WelcomeMessage,
2118
LoadingIndicator,
22-
InputContainer,
23-
InputRow,
19+
InputContainer
20+
} from '../styles';
21+
import {
22+
InputWrapper,
23+
InputBox,
2424
MessageInput,
25+
InputActions,
26+
LeftActions,
27+
RightActions,
2528
AttachmentButton,
2629
SendButton,
2730
FileInput,
@@ -31,13 +34,28 @@ import {
3134
RemoveAttachmentButton,
3235
URLPreview,
3336
URLText,
34-
URLButton
35-
} from '../styles';
37+
URLButton,
38+
FeatureButton,
39+
QuickActions,
40+
QuickActionButton
41+
} from '../styles/input';
3642
import { emotionLabels } from '../constants/emotions';
3743
import { formatTimestamp, formatFileSize } from '../utils/formatters';
3844
import TypewriterComponent from './TypewriterText';
3945
import { getFileIcon } from '../utils/fileUtils';
4046

47+
// 获取问候语
48+
const getGreeting = () => {
49+
const hour = new Date().getHours();
50+
if (hour < 6) return '夜深了';
51+
if (hour < 9) return '早上好';
52+
if (hour < 12) return '上午好';
53+
if (hour < 14) return '中午好';
54+
if (hour < 18) return '下午好';
55+
if (hour < 22) return '晚上好';
56+
return '夜深了';
57+
};
58+
4159
const ChatContainer = ({
4260
messages,
4361
isLoading,
@@ -59,49 +77,52 @@ const ChatContainer = ({
5977
onSuggestionClick,
6078
onOpenFeedbackModal
6179
}) => {
80+
const [deepThinkActive, setDeepThinkActive] = useState(false);
81+
82+
const handleKeyDown = (e) => {
83+
if (e.key === 'Enter' && !e.shiftKey) {
84+
e.preventDefault();
85+
onSendMessage();
86+
}
87+
if (onTabNavigation) {
88+
onTabNavigation(e);
89+
}
90+
};
91+
6292
return (
6393
<ChatContainerStyled
64-
initial={{ opacity: 0, x: 20 }}
65-
animate={{ opacity: 1, x: 0 }}
66-
transition={{ duration: 0.5 }}
94+
initial={{ opacity: 0 }}
95+
animate={{ opacity: 1 }}
96+
transition={{ duration: 0.3 }}
6797
>
68-
<Header>
69-
<Title>
70-
<Heart size={24} />
71-
情感聊天机器人
72-
</Title>
73-
<Subtitle>温暖陪伴,理解倾听</Subtitle>
74-
</Header>
75-
7698
<MessagesContainer>
7799
<AnimatePresence initial={false}>
78100
{messages.length === 0 ? (
79101
<WelcomeMessage
80102
key="welcome"
81-
initial={{ opacity: 0 }}
82-
animate={{ opacity: 1 }}
103+
initial={{ opacity: 0, y: 20 }}
104+
animate={{ opacity: 1, y: 0 }}
83105
exit={{ opacity: 0 }}
84-
transition={{ delay: 0.5 }}
106+
transition={{ delay: 0.2 }}
85107
>
86-
<h3>👋 你好!我是你的情感支持伙伴</h3>
108+
<h3>{getGreeting()},小草</h3>
87109
<p>
88-
我在这里倾听你的心声,理解你的感受。<br/>
89-
无论是开心、难过、焦虑还是困惑,我都愿意陪伴你。<br/>
90-
请随意分享你的想法和感受吧!
110+
我是你的情感支持伙伴,随时倾听你的心声。<br/>
111+
无论开心、难过还是困惑,都可以和我聊聊。
91112
</p>
92113
</WelcomeMessage>
93114
) : (
94115
messages.map((message) => (
95116
<MessageBubble
96117
key={message.id}
97118
isUser={message.role === 'user'}
98-
initial={{ opacity: 0, y: 20 }}
119+
initial={{ opacity: 0, y: 15 }}
99120
animate={{ opacity: 1, y: 0 }}
100-
exit={{ opacity: 0, y: -20 }}
101-
transition={{ duration: 0.3 }}
121+
exit={{ opacity: 0 }}
122+
transition={{ duration: 0.2 }}
102123
>
103124
<Avatar isUser={message.role === 'user'}>
104-
{message.role === 'user' ? <User size={20} /> : <Bot size={20} />}
125+
{message.role === 'user' ? <User size={18} /> : <Bot size={18} />}
105126
</Avatar>
106127
<MessageWrapper>
107128
<MessageContent
@@ -111,9 +132,9 @@ const ChatContainer = ({
111132
{message.role === 'assistant' && !message.isHistory ? (
112133
<TypewriterComponent
113134
text={message.content}
114-
speed={message.emotion === 'sad' ? 40 : message.emotion === 'angry' ? 20 : message.emotion === 'happy' ? 25 : 30}
135+
speed={30}
115136
showCursor={true}
116-
cursorColor={message.emotion === 'sad' ? '#74b9ff' : message.emotion === 'angry' ? '#ff7675' : message.emotion === 'happy' ? '#00b894' : '#333'}
137+
cursorColor="#6366f1"
117138
isUser={false}
118139
/>
119140
) : (
@@ -132,10 +153,9 @@ const ChatContainer = ({
132153
<FeedbackButtons>
133154
<FeedbackButton
134155
onClick={() => onOpenFeedbackModal(message)}
135-
whileHover={{ scale: 1.05 }}
136-
whileTap={{ scale: 0.95 }}
156+
whileHover={{ scale: 1.02 }}
157+
whileTap={{ scale: 0.98 }}
137158
>
138-
<MessageSquarePlus size={14} />
139159
反馈
140160
</FeedbackButton>
141161
</FeedbackButtons>
@@ -150,9 +170,9 @@ const ChatContainer = ({
150170
<LoadingIndicator
151171
initial={{ opacity: 0, y: 10 }}
152172
animate={{ opacity: 1, y: 0 }}
153-
exit={{ opacity: 0, y: -10 }}
173+
exit={{ opacity: 0 }}
154174
>
155-
<Loader2 size={18} className="spinner" />
175+
<Loader2 size={16} className="spinner" />
156176
<span>正在思考中</span>
157177
<span className="dots">
158178
<span>.</span>
@@ -168,10 +188,10 @@ const ChatContainer = ({
168188
{suggestions.map((suggestion, index) => (
169189
<SuggestionChip
170190
key={index}
171-
initial={{ opacity: 0, scale: 0.8 }}
191+
initial={{ opacity: 0, scale: 0.9 }}
172192
animate={{ opacity: 1, scale: 1 }}
173-
exit={{ opacity: 0, scale: 0.8 }}
174-
transition={{ delay: index * 0.1 }}
193+
exit={{ opacity: 0, scale: 0.9 }}
194+
transition={{ delay: index * 0.05 }}
175195
onClick={() => onSuggestionClick(suggestion)}
176196
>
177197
{suggestion}
@@ -192,7 +212,7 @@ const ChatContainer = ({
192212
animate={{ opacity: 1, y: 0 }}
193213
exit={{ opacity: 0, y: -10 }}
194214
>
195-
<Link size={16} />
215+
<Link size={14} />
196216
<URLText>{detectedURLs[0]}</URLText>
197217
<URLButton onClick={() => window.open(detectedURLs[0], '_blank')}>
198218
<ExternalLink size={14} />
@@ -207,15 +227,15 @@ const ChatContainer = ({
207227
{attachments.map((attachment) => (
208228
<AttachmentItem
209229
key={attachment.id}
210-
initial={{ opacity: 0, scale: 0.8 }}
230+
initial={{ opacity: 0, scale: 0.9 }}
211231
animate={{ opacity: 1, scale: 1 }}
212-
exit={{ opacity: 0, scale: 0.8 }}
232+
exit={{ opacity: 0, scale: 0.9 }}
213233
>
214234
<AttachmentIcon>
215235
{getFileIcon(attachment.type)}
216236
</AttachmentIcon>
217237
<span>{attachment.name}</span>
218-
<span>({formatFileSize(attachment.size)})</span>
238+
<span style={{ color: '#999' }}>({formatFileSize(attachment.size)})</span>
219239
<RemoveAttachmentButton
220240
onClick={() => onRemoveAttachment(attachment.id)}
221241
>
@@ -227,45 +247,62 @@ const ChatContainer = ({
227247
</AttachmentsPreview>
228248
)}
229249

230-
<InputRow>
231-
<MessageInput
232-
ref={inputRef}
233-
type="text"
234-
value={inputValue}
235-
onChange={onInputChange}
236-
onKeyPress={onKeyPress}
237-
onKeyDown={onTabNavigation}
238-
placeholder="分享你的想法和感受..."
239-
disabled={isLoading}
240-
aria-label="消息输入框"
241-
aria-describedby="input-hint"
242-
/>
243-
<AttachmentButton
244-
ref={attachmentButtonRef}
245-
onClick={() => fileInputRef.current?.click()}
246-
disabled={isLoading}
247-
onKeyDown={onTabNavigation}
248-
whileHover={{ scale: 1.05 }}
249-
whileTap={{ scale: 0.95 }}
250-
aria-label="添加附件"
251-
title="添加附件 (图片、PDF、文档)"
252-
>
253-
<Paperclip size={20} />
254-
</AttachmentButton>
255-
<SendButton
256-
ref={sendButtonRef}
257-
onClick={onSendMessage}
258-
disabled={(!inputValue.trim() && attachments.length === 0) || isLoading}
259-
onKeyDown={onTabNavigation}
260-
whileHover={{ scale: 1.05 }}
261-
whileTap={{ scale: 0.95 }}
262-
aria-label="发送消息"
263-
aria-disabled={(!inputValue.trim() && attachments.length === 0) || isLoading}
264-
title="发送消息 (Enter)"
265-
>
266-
<Send size={20} />
267-
</SendButton>
268-
</InputRow>
250+
<InputWrapper>
251+
<InputBox>
252+
<MessageInput
253+
ref={inputRef}
254+
value={inputValue}
255+
onChange={onInputChange}
256+
onKeyDown={handleKeyDown}
257+
placeholder="发消息或输入 / 选择技能"
258+
disabled={isLoading}
259+
rows={1}
260+
/>
261+
<InputActions>
262+
<LeftActions>
263+
<AttachmentButton
264+
ref={attachmentButtonRef}
265+
onClick={() => fileInputRef.current?.click()}
266+
disabled={isLoading}
267+
whileHover={{ scale: 1.05 }}
268+
whileTap={{ scale: 0.95 }}
269+
title="添加附件"
270+
>
271+
<Paperclip size={18} />
272+
</AttachmentButton>
273+
<FeatureButton
274+
active={deepThinkActive}
275+
onClick={() => setDeepThinkActive(!deepThinkActive)}
276+
whileHover={{ scale: 1.02 }}
277+
whileTap={{ scale: 0.98 }}
278+
>
279+
<Sparkles size={14} />
280+
深度思考
281+
</FeatureButton>
282+
</LeftActions>
283+
<RightActions>
284+
<AttachmentButton
285+
whileHover={{ scale: 1.05 }}
286+
whileTap={{ scale: 0.95 }}
287+
title="语音输入"
288+
>
289+
<Mic size={18} />
290+
</AttachmentButton>
291+
<SendButton
292+
ref={sendButtonRef}
293+
onClick={onSendMessage}
294+
disabled={(!inputValue.trim() && attachments.length === 0) || isLoading}
295+
whileHover={{ scale: 1.05 }}
296+
whileTap={{ scale: 0.95 }}
297+
title="发送消息"
298+
>
299+
<Send size={16} />
300+
</SendButton>
301+
</RightActions>
302+
</InputActions>
303+
</InputBox>
304+
305+
</InputWrapper>
269306

270307
<FileInput
271308
ref={fileInputRef}

frontend/src/components/FeedbackModal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { motion, AnimatePresence } from 'framer-motion';
2+
import { AnimatePresence } from 'framer-motion';
33
import { X } from 'lucide-react';
44
import {
55
ModalOverlay,

frontend/src/components/HistoryManagementModal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useEffect, useCallback } from 'react';
22
import { motion, AnimatePresence } from 'framer-motion';
3-
import { X, Search, Trash2, RotateCcw } from 'lucide-react';
3+
import { X, Search, Trash2 } from 'lucide-react';
44
import ChatAPI from '../services/ChatAPI';
55
import { formatRelativeTime } from '../utils/formatters';
66
import {

0 commit comments

Comments
 (0)