戒酒的李白

Web app bug fix.

@@ -20,13 +20,25 @@ def main(): @@ -20,13 +20,25 @@ def main():
20 """主函数""" 20 """主函数"""
21 st.set_page_config( 21 st.set_page_config(
22 page_title="Insight Agent", 22 page_title="Insight Agent",
23 - page_icon="", 23 + page_icon="🔍",
24 layout="wide" 24 layout="wide"
25 ) 25 )
26 26
27 st.title("Insight Agent") 27 st.title("Insight Agent")
28 st.markdown("私有舆情数据库深度分析AI代理") 28 st.markdown("私有舆情数据库深度分析AI代理")
29 29
  30 + # 检查URL参数
  31 + try:
  32 + # 尝试使用新版本的query_params
  33 + query_params = st.query_params
  34 + auto_query = query_params.get('query', '')
  35 + auto_search = query_params.get('auto_search', 'false').lower() == 'true'
  36 + except AttributeError:
  37 + # 兼容旧版本
  38 + query_params = st.experimental_get_query_params()
  39 + auto_query = query_params.get('query', [''])[0]
  40 + auto_search = query_params.get('auto_search', ['false'])[0].lower() == 'true'
  41 +
30 # ----- 配置被硬编码 ----- 42 # ----- 配置被硬编码 -----
31 # 强制使用 Kimi 43 # 强制使用 Kimi
32 llm_provider = "kimi" 44 llm_provider = "kimi"
@@ -40,8 +52,13 @@ def main(): @@ -40,8 +52,13 @@ def main():
40 52
41 with col1: 53 with col1:
42 st.header("研究查询") 54 st.header("研究查询")
  55 +
  56 + # 如果有自动查询,使用它作为默认值
  57 + default_query = auto_query if auto_query else ""
  58 +
43 query = st.text_area( 59 query = st.text_area(
44 "请输入您要研究的问题", 60 "请输入您要研究的问题",
  61 + value=default_query,
45 placeholder="例如:2025年人工智能发展趋势", 62 placeholder="例如:2025年人工智能发展趋势",
46 height=100 63 height=100
47 ) 64 )
@@ -60,6 +77,12 @@ def main(): @@ -60,6 +77,12 @@ def main():
60 col1_btn, col2_btn, col3_btn = st.columns([1, 1, 1]) 77 col1_btn, col2_btn, col3_btn = st.columns([1, 1, 1])
61 with col2_btn: 78 with col2_btn:
62 start_research = st.button("开始研究", type="primary", use_container_width=True) 79 start_research = st.button("开始研究", type="primary", use_container_width=True)
  80 +
  81 + # 自动搜索逻辑
  82 + if auto_search and auto_query and 'auto_search_executed' not in st.session_state:
  83 + st.session_state.auto_search_executed = True
  84 + start_research = True
  85 + query = auto_query
63 86
64 # 验证配置 87 # 验证配置
65 if start_research: 88 if start_research:
@@ -20,13 +20,25 @@ def main(): @@ -20,13 +20,25 @@ def main():
20 """主函数""" 20 """主函数"""
21 st.set_page_config( 21 st.set_page_config(
22 page_title="Media Agent", 22 page_title="Media Agent",
23 - page_icon="", 23 + page_icon="🔍",
24 layout="wide" 24 layout="wide"
25 ) 25 )
26 26
27 st.title("Media Agent") 27 st.title("Media Agent")
28 st.markdown("具备强大多模态能力的AI代理") 28 st.markdown("具备强大多模态能力的AI代理")
29 29
  30 + # 检查URL参数
  31 + try:
  32 + # 尝试使用新版本的query_params
  33 + query_params = st.query_params
  34 + auto_query = query_params.get('query', '')
  35 + auto_search = query_params.get('auto_search', 'false').lower() == 'true'
  36 + except AttributeError:
  37 + # 兼容旧版本
  38 + query_params = st.experimental_get_query_params()
  39 + auto_query = query_params.get('query', [''])[0]
  40 + auto_search = query_params.get('auto_search', ['false'])[0].lower() == 'true'
  41 +
30 # ----- 配置被硬编码 ----- 42 # ----- 配置被硬编码 -----
31 # 强制使用 Gemini 43 # 强制使用 Gemini
32 llm_provider = "gemini" 44 llm_provider = "gemini"
@@ -40,8 +52,13 @@ def main(): @@ -40,8 +52,13 @@ def main():
40 52
41 with col1: 53 with col1:
42 st.header("研究查询") 54 st.header("研究查询")
  55 +
  56 + # 如果有自动查询,使用它作为默认值
  57 + default_query = auto_query if auto_query else ""
  58 +
43 query = st.text_area( 59 query = st.text_area(
44 "请输入您要研究的问题", 60 "请输入您要研究的问题",
  61 + value=default_query,
45 placeholder="例如:2025年人工智能发展趋势", 62 placeholder="例如:2025年人工智能发展趋势",
46 height=100 63 height=100
47 ) 64 )
@@ -60,6 +77,12 @@ def main(): @@ -60,6 +77,12 @@ def main():
60 col1_btn, col2_btn, col3_btn = st.columns([1, 1, 1]) 77 col1_btn, col2_btn, col3_btn = st.columns([1, 1, 1])
61 with col2_btn: 78 with col2_btn:
62 start_research = st.button("开始研究", type="primary", use_container_width=True) 79 start_research = st.button("开始研究", type="primary", use_container_width=True)
  80 +
  81 + # 自动搜索逻辑
  82 + if auto_search and auto_query and 'auto_search_executed' not in st.session_state:
  83 + st.session_state.auto_search_executed = True
  84 + start_research = True
  85 + query = auto_query
63 86
64 # 验证配置 87 # 验证配置
65 if start_research: 88 if start_research:
@@ -27,6 +27,18 @@ def main(): @@ -27,6 +27,18 @@ def main():
27 st.title("Query Agent") 27 st.title("Query Agent")
28 st.markdown("具备强大网页搜索能力的AI代理") 28 st.markdown("具备强大网页搜索能力的AI代理")
29 29
  30 + # 检查URL参数
  31 + try:
  32 + # 尝试使用新版本的query_params
  33 + query_params = st.query_params
  34 + auto_query = query_params.get('query', '')
  35 + auto_search = query_params.get('auto_search', 'false').lower() == 'true'
  36 + except AttributeError:
  37 + # 兼容旧版本
  38 + query_params = st.experimental_get_query_params()
  39 + auto_query = query_params.get('query', [''])[0]
  40 + auto_search = query_params.get('auto_search', ['false'])[0].lower() == 'true'
  41 +
30 # ----- 配置被硬编码 ----- 42 # ----- 配置被硬编码 -----
31 # 强制使用 DeepSeek 43 # 强制使用 DeepSeek
32 llm_provider = "deepseek" 44 llm_provider = "deepseek"
@@ -40,8 +52,13 @@ def main(): @@ -40,8 +52,13 @@ def main():
40 52
41 with col1: 53 with col1:
42 st.header("研究查询") 54 st.header("研究查询")
  55 +
  56 + # 如果有自动查询,使用它作为默认值
  57 + default_query = auto_query if auto_query else ""
  58 +
43 query = st.text_area( 59 query = st.text_area(
44 "请输入您要研究的问题", 60 "请输入您要研究的问题",
  61 + value=default_query,
45 placeholder="例如:2025年人工智能发展趋势", 62 placeholder="例如:2025年人工智能发展趋势",
46 height=100 63 height=100
47 ) 64 )
@@ -60,6 +77,12 @@ def main(): @@ -60,6 +77,12 @@ def main():
60 col1_btn, col2_btn, col3_btn = st.columns([1, 1, 1]) 77 col1_btn, col2_btn, col3_btn = st.columns([1, 1, 1])
61 with col2_btn: 78 with col2_btn:
62 start_research = st.button("开始研究", type="primary", use_container_width=True) 79 start_research = st.button("开始研究", type="primary", use_container_width=True)
  80 +
  81 + # 自动搜索逻辑
  82 + if auto_search and auto_query and 'auto_search_executed' not in st.session_state:
  83 + st.session_state.auto_search_executed = True
  84 + start_research = True
  85 + query = auto_query
63 86
64 # 验证配置 87 # 验证配置
65 if start_research: 88 if start_research:
@@ -221,6 +221,7 @@ def start_app(app_name): @@ -221,6 +221,7 @@ def start_app(app_name):
221 processes[app_name]['port'] 221 processes[app_name]['port']
222 ) 222 )
223 223
  224 +
224 if success: 225 if success:
225 # 等待应用启动 226 # 等待应用启动
226 startup_success, startup_message = wait_for_app_startup(app_name, 15) 227 startup_success, startup_message = wait_for_app_startup(app_name, 15)
@@ -106,6 +106,7 @@ @@ -106,6 +106,7 @@
106 .embedded-content { 106 .embedded-content {
107 height: calc(100% - 60px); 107 height: calc(100% - 60px);
108 position: relative; 108 position: relative;
  109 + overflow: hidden;
109 } 110 }
110 111
111 /* 控制台输出区域 */ 112 /* 控制台输出区域 */
@@ -332,6 +333,11 @@ @@ -332,6 +333,11 @@
332 setInterval(updateTime, 1000); 333 setInterval(updateTime, 1000);
333 checkStatus(); 334 checkStatus();
334 setInterval(checkStatus, 5000); 335 setInterval(checkStatus, 5000);
  336 +
  337 + // 延迟预加载iframe以确保应用启动完成
  338 + setTimeout(() => {
  339 + preloadIframes();
  340 + }, 3000);
335 }); 341 });
336 342
337 // Socket.IO连接 343 // Socket.IO连接
@@ -389,29 +395,49 @@ @@ -389,29 +395,49 @@
389 button.disabled = true; 395 button.disabled = true;
390 button.innerHTML = '<span class="loading"></span> 搜索中...'; 396 button.innerHTML = '<span class="loading"></span> 搜索中...';
391 397
392 - fetch('/api/search', {  
393 - method: 'POST',  
394 - headers: {  
395 - 'Content-Type': 'application/json',  
396 - },  
397 - body: JSON.stringify({ query: query })  
398 - })  
399 - .then(response => response.json())  
400 - .then(data => {  
401 - if (data.success) {  
402 - showMessage('搜索请求已发送到所有运行中的应用', 'success');  
403 - } else {  
404 - showMessage(data.message || '搜索失败', 'error'); 398 + // 确保所有iframe已初始化
  399 + if (!iframesInitialized) {
  400 + preloadIframes();
  401 + }
  402 +
  403 + // 向所有运行中的应用发送搜索请求(通过新窗口方式避免刷新现有iframe)
  404 + let totalRunning = 0;
  405 + const ports = { insight: 8501, media: 8502, query: 8503 };
  406 +
  407 + Object.keys(appStatus).forEach(app => {
  408 + if (appStatus[app] === 'running') {
  409 + totalRunning++;
  410 +
  411 + // 为每个应用创建一个临时的搜索iframe,避免干扰主iframe
  412 + const searchIframe = document.createElement('iframe');
  413 + searchIframe.style.display = 'none';
  414 + searchIframe.style.position = 'absolute';
  415 + searchIframe.style.top = '-9999px';
  416 +
  417 + const searchUrl = `http://localhost:${ports[app]}?query=${encodeURIComponent(query)}&auto_search=true`;
  418 + console.log(`向 ${app} 发送搜索请求: ${searchUrl}`);
  419 +
  420 + searchIframe.src = searchUrl;
  421 + document.body.appendChild(searchIframe);
  422 +
  423 + // 几秒后移除临时iframe
  424 + setTimeout(() => {
  425 + if (searchIframe.parentNode) {
  426 + searchIframe.parentNode.removeChild(searchIframe);
  427 + }
  428 + }, 5000);
405 } 429 }
406 - })  
407 - .catch(error => {  
408 - console.error('搜索错误:', error);  
409 - showMessage('搜索请求失败', 'error');  
410 - })  
411 - .finally(() => { 430 + });
  431 +
  432 + if (totalRunning === 0) {
412 button.disabled = false; 433 button.disabled = false;
413 button.innerHTML = '搜索'; 434 button.innerHTML = '搜索';
414 - }); 435 + showMessage('没有运行中的应用,无法执行搜索', 'error');
  436 + } else {
  437 + button.disabled = false;
  438 + button.innerHTML = '搜索';
  439 + showMessage(`已向 ${totalRunning} 个应用发送搜索请求`, 'success');
  440 + }
415 } 441 }
416 442
417 // 切换应用 443 // 切换应用
@@ -472,6 +498,40 @@ @@ -472,6 +498,40 @@
472 consoleOutput.scrollTop = consoleOutput.scrollHeight; 498 consoleOutput.scrollTop = consoleOutput.scrollHeight;
473 } 499 }
474 500
  501 + // 预加载的iframe存储
  502 + let preloadedIframes = {};
  503 + let iframesInitialized = false;
  504 +
  505 + // 预加载所有iframe(只执行一次)
  506 + function preloadIframes() {
  507 + if (iframesInitialized) return;
  508 +
  509 + const ports = { insight: 8501, media: 8502, query: 8503 };
  510 + const content = document.getElementById('embeddedContent');
  511 +
  512 + for (const [app, port] of Object.entries(ports)) {
  513 + const iframe = document.createElement('iframe');
  514 + iframe.src = `http://localhost:${port}`;
  515 + iframe.style.width = '100%';
  516 + iframe.style.height = '100%';
  517 + iframe.style.border = 'none';
  518 + iframe.style.position = 'absolute';
  519 + iframe.style.top = '0';
  520 + iframe.style.left = '0';
  521 + iframe.style.display = 'none';
  522 + iframe.id = `iframe-${app}`;
  523 +
  524 + // 直接添加到content区域
  525 + content.appendChild(iframe);
  526 + preloadedIframes[app] = iframe;
  527 +
  528 + console.log(`预加载 ${app} 应用完成`);
  529 + }
  530 +
  531 + iframesInitialized = true;
  532 + console.log('所有iframe预加载完成,准备进行无缝切换');
  533 + }
  534 +
475 // 更新嵌入页面 535 // 更新嵌入页面
476 function updateEmbeddedPage(app) { 536 function updateEmbeddedPage(app) {
477 const header = document.getElementById('embeddedHeader'); 537 const header = document.getElementById('embeddedHeader');
@@ -485,16 +545,47 @@ @@ -485,16 +545,47 @@
485 545
486 header.textContent = appNames[app] || app; 546 header.textContent = appNames[app] || app;
487 547
488 - // 如果应用正在运行,显示iframe 548 + // 如果应用正在运行,显示对应的iframe
489 if (appStatus[app] === 'running') { 549 if (appStatus[app] === 'running') {
490 - const ports = { insight: 8501, media: 8502, query: 8503 };  
491 - content.innerHTML = `<iframe src="http://localhost:${ports[app]}" style="width: 100%; height: 100%; border: none;"></iframe>`; 550 + // 确保iframe已初始化
  551 + if (!iframesInitialized) {
  552 + preloadIframes();
  553 + }
  554 +
  555 + // 隐藏所有iframe
  556 + Object.values(preloadedIframes).forEach(iframe => {
  557 + iframe.style.display = 'none';
  558 + });
  559 +
  560 + // 移除占位符
  561 + const placeholder = content.querySelector('.status-placeholder');
  562 + if (placeholder) {
  563 + placeholder.remove();
  564 + }
  565 +
  566 + // 显示当前应用的iframe
  567 + if (preloadedIframes[app]) {
  568 + preloadedIframes[app].style.display = 'block';
  569 + console.log(`切换到 ${app} 应用 - 无刷新切换`);
  570 + }
492 } else { 571 } else {
493 - content.innerHTML = `  
494 - <div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #666; flex-direction: column;">  
495 - <div style="margin-bottom: 10px;">${appNames[app]} 未运行</div>  
496 - <div style="font-size: 12px;">状态: ${appStatus[app]}</div>  
497 - </div> 572 + // 隐藏所有iframe
  573 + Object.values(preloadedIframes).forEach(iframe => {
  574 + iframe.style.display = 'none';
  575 + });
  576 +
  577 + // 显示状态信息
  578 + let placeholder = content.querySelector('.status-placeholder');
  579 + if (!placeholder) {
  580 + placeholder = document.createElement('div');
  581 + placeholder.className = 'status-placeholder';
  582 + placeholder.style.cssText = 'display: flex; align-items: center; justify-content: center; height: 100%; color: #666; flex-direction: column; position: absolute; top: 0; left: 0; width: 100%;';
  583 + content.appendChild(placeholder);
  584 + }
  585 +
  586 + placeholder.innerHTML = `
  587 + <div style="margin-bottom: 10px;">${appNames[app]} 未运行</div>
  588 + <div style="font-size: 12px;">状态: ${appStatus[app]}</div>
498 `; 589 `;
499 } 590 }
500 } 591 }
@@ -514,10 +605,13 @@ @@ -514,10 +605,13 @@
514 // 更新应用状态 605 // 更新应用状态
515 function updateAppStatus(data) { 606 function updateAppStatus(data) {
516 for (const [app, info] of Object.entries(data)) { 607 for (const [app, info] of Object.entries(data)) {
517 - appStatus[app] = info.status; 608 + // 适配实际的API格式:{app: {status: string, port: int, output_lines: int}}
  609 + const status = info.status === 'running' ? 'running' : 'stopped';
  610 + appStatus[app] = status;
  611 +
518 const indicator = document.getElementById(`status-${app}`); 612 const indicator = document.getElementById(`status-${app}`);
519 if (indicator) { 613 if (indicator) {
520 - indicator.className = `status-indicator ${info.status}`; 614 + indicator.className = `status-indicator ${status}`;
521 } 615 }
522 } 616 }
523 617