diff --git a/backend/python/app/api/chat_media.py b/backend/python/app/api/chat_media.py index feaa7d7..b444fa7 100644 --- a/backend/python/app/api/chat_media.py +++ b/backend/python/app/api/chat_media.py @@ -1430,7 +1430,7 @@ async def _generate_media_task(ai_msg_id: str, ai_model_id: str, prompt: str, us logger.info(f"[_generate_media_task] 启动 media 生成 msg={ai_msg_id} model={ai_model_id} prompt={prompt[:60]!r}") caps = [c.lower() for c in (ai_model.capabilities or [])] is_video = "video" in caps - timeout_seconds = 300 if is_video else 90 + timeout_seconds = 300 if is_video else 180 try: result = await asyncio.wait_for( _generate_media(db, ai_model, prompt, user_id), diff --git a/backend/python/app/api/chat_service.py b/backend/python/app/api/chat_service.py index c06e352..bda1f8b 100644 --- a/backend/python/app/api/chat_service.py +++ b/backend/python/app/api/chat_service.py @@ -1657,6 +1657,16 @@ async def _send_message_core( + # 媒体分支直接返回,不会进入 LLM 工具调用;提前初始化避免未绑定 + + called_skill_names = [] + + + + called_mcp_names = [] + + + if effective_skill_ids: diff --git a/frontend/src/pages/front/ChatPage.css b/frontend/src/pages/front/ChatPage.css index a8db290..afd0eb5 100644 --- a/frontend/src/pages/front/ChatPage.css +++ b/frontend/src/pages/front/ChatPage.css @@ -471,10 +471,15 @@ } .md-table td { - padding: 10px 14px; + padding: 8px 12px; border-bottom: 1px solid #EEF0F4; color: var(--color-text-primary); vertical-align: top; + line-height: 1.5; +} + +.md-table td br { + line-height: 0.8; } .md-table tbody tr:last-child td { diff --git a/frontend/src/pages/front/ChatPage.tsx b/frontend/src/pages/front/ChatPage.tsx index 4b5f2e4..edc3b06 100644 --- a/frontend/src/pages/front/ChatPage.tsx +++ b/frontend/src/pages/front/ChatPage.tsx @@ -189,41 +189,8 @@ const MarkdownContent: React.FC<{ content: string }> = ({ content }) => { return '\x00MEDIA' + (mediaBlocks.length - 1) + '\x00'; }); - // 2.7 Extract Markdown tables: | h1 | h2 |\n|---|---| ... | - // 把整段表格替换为占位符,表格内容(已转义)放入 tableBlocks 数组 - const tableBlocks: string[] = []; - text = text.replace( - /((?:^\|.+\|\r?\n)+^\|[\s\-:|]+\|\r?\n(?:^\|.+\|\r?\n?)+)/gm, - (_m: string, block: string) => { - const lines = block.trim().split(/\r?\n/).filter((l: string) => l.trim()); - if (lines.length < 2) return block; - const headerCells = lines[0].split('|').slice(1, -1).map((c: string) => c.trim()); - const alignCells = lines[1].split('|').slice(1, -1).map((c: string) => { - const t = c.trim(); - const left = t.startsWith(':'); - const right = t.endsWith(':'); - if (left && right) return 'center'; - if (right) return 'right'; - if (left) return 'left'; - return 'left'; - }); - const bodyRows = lines.slice(2).map((row: string) => - row.split('|').slice(1, -1).map((c: string) => c.trim()) - ); - const thead = headerCells.map((c: string, i: number) => - `
');
- text = text.replace(/\n/g, '
');
+ text = text.replace(/\n/g, ' ');
// 10. Restore code blocks and inline codes
text = text.replace(/\x00CODEBLOCK(\d+)\x00/g, (_m: string, idx: string) => codeBlocks[parseInt(idx)] || '');