feat(admin): Add activity logs page and fix AI chat markdown rendering

- Add paginated activity logs API with filters (date, module, action, keyword)

- Add ActivityLogsPage with table, filters, and detail modal

- Add markdown rendering support for AI chat messages

- Remove prototype placeholder content from chat sidebar

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-01 21:04:21 +08:00
parent aaa29ea9d3
commit 4c2c9b437b
9 changed files with 795 additions and 9 deletions

View File

@@ -28,6 +28,7 @@ import { ThinkingBlock } from '@/shared/components/Chat';
import { getAccessToken } from '@/framework/auth/api';
import { AGENTS, AGENT_PROMPTS, BRAND_COLORS } from '../constants';
import type { AgentConfig, Conversation, Message } from '../types';
import { MarkdownContent } from '../protocol-agent/components/MarkdownContent';
import '../styles/chat-workspace.css';
/**
@@ -651,14 +652,6 @@ export const ChatWorkspace: React.FC<ChatWorkspaceProps> = ({
</div>
</div>
{/* 用户信息 */}
<div className="sidebar-user">
<div className="user-avatar">U</div>
<div className="user-info">
<div className="user-name">Dr. Wang</div>
<div className="user-plan"></div>
</div>
</div>
</aside>
{/* 主对话区 */}
@@ -750,7 +743,11 @@ export const ChatWorkspace: React.FC<ChatWorkspaceProps> = ({
{/* 消息内容(有内容时才显示气泡) */}
{(msg.content || (msg.role === 'assistant' && isStreaming && index === messages.length - 1)) && (
<div className={`message-bubble ${msg.role}`}>
{msg.content}
{msg.role === 'assistant' ? (
<MarkdownContent content={msg.content || ''} />
) : (
msg.content
)}
{msg.role === 'assistant' && isStreaming && index === messages.length - 1 && (
<span className="typing-cursor"></span>
)}

View File

@@ -946,3 +946,93 @@
border-radius: 8px;
}
/* ============================================ */
/* MarkdownContent 组件样式 */
/* ============================================ */
.message-bubble .markdown-content {
white-space: normal;
}
.message-bubble .markdown-content p {
margin: 0 0 8px 0;
}
.message-bubble .markdown-content p:last-child {
margin-bottom: 0;
}
.message-bubble .markdown-content .md-divider {
border: none;
border-top: 1px solid #E5E7EB;
margin: 12px 0;
}
.message-bubble .markdown-content h1,
.message-bubble .markdown-content h2,
.message-bubble .markdown-content h3 {
margin: 16px 0 8px 0;
font-weight: 700;
line-height: 1.4;
}
.message-bubble .markdown-content h1:first-child,
.message-bubble .markdown-content h2:first-child,
.message-bubble .markdown-content h3:first-child {
margin-top: 0;
}
.message-bubble .markdown-content h1 {
font-size: 1.3em;
}
.message-bubble .markdown-content h2 {
font-size: 1.2em;
}
.message-bubble .markdown-content h3 {
font-size: 1.1em;
}
.message-bubble .markdown-content ul,
.message-bubble .markdown-content ol {
margin: 8px 0 12px 0;
padding-left: 24px;
}
.message-bubble .markdown-content ul {
list-style-type: disc;
}
.message-bubble .markdown-content ol {
list-style-type: decimal;
}
.message-bubble .markdown-content li {
margin: 6px 0;
line-height: 1.6;
display: list-item;
}
.message-bubble .markdown-content li::marker {
color: #4F6EF2;
}
.message-bubble .markdown-content strong {
font-weight: 700;
color: #1F2937;
}
.message-bubble .markdown-content em {
font-style: italic;
color: #4B5563;
}
.message-bubble .markdown-content code {
background: rgba(79, 110, 242, 0.1);
color: #4F6EF2;
padding: 2px 6px;
border-radius: 4px;
font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
font-size: 0.9em;
}