style(frontend): redesign with Miuix HyperOS design language

- Color system: Miuix dark tokens (primary #277AF7, bg #242424, surface #000)
- Components: rounded-full buttons, squircle cards (18px), glass header
- Messages: blue user bubbles, dark AI bubbles with typing animation
- Admin dashboard: stat cards with real-time service status
- Login: centered logo with gradient shadow, HyperOS input fields
- Smooth transitions and scale-on-press interactions
This commit is contained in:
Aska committed 2026-08-12 16:41:34 +08:00
1 parent 17ef73bcbe
commit bea29d3b73
9 files changed
+312 -99

No files matched your search

@@ -1,16 +1,8 @@
import type { Message } from '../../types/chat'
export default function MessageList({ messages }: { messages: Message[] }) {
if (messages.length === 0) {
return (
<div className="flex items-center justify-center h-full text-gray-500 text-sm">
开始新对话吧~
</div>
)
}
return (
<div className="space-y-4 max-w-3xl mx-auto">
<div className="space-y-3">
{messages.map((msg) => (
<MessageBubble key={msg.id} message={msg} />
))}
@@ -21,22 +13,56 @@ export default function MessageList({ messages }: { messages: Message[] }) {
function MessageBubble({ message }: { message: Message }) {
const isUser = message.role === 'user'
const isAction = message.role === 'action'
const isSystem = message.role === 'system'
const isEmpty = message.role === 'assistant' && !message.content
if (isAction) {
return <div className="text-center text-gray-500 text-sm italic py-1">{message.content}</div>
return (
<div className="flex justify-center py-1">
<span className="text-xs text-[#4788FF] bg-[#2B3B54]/80 px-3 py-1 rounded-full">
{message.content}
</span>
</div>
)
}
if (isSystem) {
return (
<div className="flex justify-center py-1">
<span className="text-xs text-[#ffdad6] bg-[#2E0603]/80 px-3 py-1 rounded-full">{message.content}</span>
</div>
)
}
return (
<div className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[70%] rounded-2xl px-4 py-2.5 text-sm leading-relaxed ${
{/* Avatar for AI */}
{!isUser && (
<div className="w-8 h-8 rounded-xl bg-[#277AF7] flex items-center justify-center shrink-0 mr-2 mt-1">
<span className="text-xs font-bold text-white">C</span>
</div>
)}
<div className={`max-w-[75%] px-4 py-2.5 text-sm leading-relaxed ${
isUser
? 'bg-purple-600 text-white rounded-br-md'
: message.role === 'system'
? 'bg-red-900/50 text-red-300 mx-auto text-xs'
: 'bg-gray-800 text-gray-100 rounded-bl-md'
? 'bg-[#277AF7] text-white rounded-[18px] rounded-br-[6px]'
: isEmpty
? 'bg-transparent text-transparent'
: 'bg-[#000] text-[#F2F2F2] rounded-[18px] rounded-bl-[6px] border border-[#404040]'
}`}>
{message.content || (message.role === 'assistant' ? <span className="animate-pulse">...</span> : null)}
{isEmpty ? (
<span className="flex gap-1.5 py-1">
<span className="w-2 h-2 rounded-full bg-[#404040] animate-bounce" style={{animationDelay:'0ms'}} />
<span className="w-2 h-2 rounded-full bg-[#404040] animate-bounce" style={{animationDelay:'150ms'}} />
<span className="w-2 h-2 rounded-full bg-[#404040] animate-bounce" style={{animationDelay:'300ms'}} />
</span>
) : (
message.content
)}
</div>
{/* Spacer for user messages */}
{isUser && <div className="w-8 shrink-0 ml-2" />}
</div>
)
}