From bf6b9457c4a5e25adb90f27b66837a0db7a5ccd7 Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Sat, 23 May 2026 23:48:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=90=9C=E7=B4=A2=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E6=8C=81=E4=B9=85=E5=8C=96=E4=BF=9D=E5=AD=98=20+=20=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E6=95=B0=E9=87=8F=E5=8F=AF=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 search_results 表,搜索结果按主题持久保存 - 搜索API自动保存结果到数据库,获取详情时更新raw_content - 页面加载时自动加载历史搜索结果,按搜索词分组显示 - 支持单条删除和清空所有搜索结果 - 搜索结果数量默认10条,可通过输入框调整(1-20) - 搜索面板标题显示结果计数badge --- app.py | 88 +++++++++++++++- templates/topic.html | 234 +++++++++++++++++++++++++++++-------------- 2 files changed, 244 insertions(+), 78 deletions(-) diff --git a/app.py b/app.py index 3f32626..318c153 100644 --- a/app.py +++ b/app.py @@ -123,6 +123,20 @@ def init_db(): api_key TEXT DEFAULT '', updated_at TEXT DEFAULT (datetime('now','localtime')) ); + CREATE TABLE IF NOT EXISTS search_results ( + id TEXT PRIMARY KEY, + topic_id TEXT NOT NULL, + query TEXT NOT NULL, + title TEXT DEFAULT '', + url TEXT DEFAULT '', + snippet TEXT DEFAULT '', + raw_content TEXT DEFAULT '', + score REAL DEFAULT 0, + search_depth TEXT DEFAULT 'basic', + max_results INTEGER DEFAULT 10, + created_at TEXT DEFAULT (datetime('now','localtime')), + FOREIGN KEY (topic_id) REFERENCES topics(id) ON DELETE CASCADE + ); ''') # 初始化默认Prompt模板 default_templates = [ @@ -776,9 +790,10 @@ def update_search_config(): @app.route('/api/search', methods=['POST']) def search_web(): - """调用 Tavily Search API 进行搜索""" + """调用 Tavily Search API 进行搜索,结果保存到数据库""" data = request.get_json(force=True) query = data.get('query', '').strip() + topic_id = data.get('topic_id', '').strip() if not query: return jsonify({'error': '搜索关键词不能为空'}), 400 @@ -786,7 +801,7 @@ def search_web(): if not search_config['api_key']: return jsonify({'error': '请先配置搜索API Key(首页右上角设置)'}), 400 - max_results = data.get('max_results', 8) + max_results = data.get('max_results', 10) search_depth = data.get('search_depth', 'basic') time_range = data.get('time_range', None) @@ -811,19 +826,43 @@ def search_web(): ) resp.raise_for_status() result = resp.json() - return jsonify(result) except requests.exceptions.HTTPError as e: return jsonify({'error': f'搜索请求失败: HTTP {e.response.status_code}'}), 502 except Exception as e: return jsonify({'error': f'搜索失败: {str(e)}'}), 500 + # 保存搜索结果到数据库 + if topic_id: + conn = get_db() + now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + saved_results = [] + for r in result.get('results', []): + rid = str(uuid.uuid4())[:8] + conn.execute( + 'INSERT INTO search_results (id, topic_id, query, title, url, snippet, score, search_depth, max_results, created_at) VALUES (?,?,?,?,?,?,?,?,?,?)', + (rid, topic_id, query, r.get('title', ''), r.get('url', ''), r.get('content', ''), r.get('score', 0), search_depth, max_results, now) + ) + saved_results.append({ + 'id': rid, + 'title': r.get('title', ''), + 'url': r.get('url', ''), + 'content': r.get('content', ''), + 'score': r.get('score', 0), + }) + conn.commit() + conn.close() + result['saved_results'] = saved_results + + return jsonify(result) + @app.route('/api/search/detail', methods=['POST']) def search_detail(): - """调用 Tavily Search API 获取详细内容(include_raw_content)""" + """获取搜索结果详细内容,并更新数据库中的 raw_content""" data = request.get_json(force=True) query = data.get('query', '').strip() url = data.get('url', '').strip() + result_id = data.get('result_id', '').strip() if not query: return jsonify({'error': '搜索关键词不能为空'}), 400 @@ -855,11 +894,52 @@ def search_detail(): # 如果指定了URL,过滤只返回该URL的结果 if url: result['results'] = [r for r in result.get('results', []) if r.get('url') == url] + + # 更新数据库中的 raw_content + if result_id and result.get('results'): + raw_content = result['results'][0].get('raw_content', '') or result['results'][0].get('content', '') + conn = get_db() + conn.execute('UPDATE search_results SET raw_content=? WHERE id=?', (raw_content, result_id)) + conn.commit() + conn.close() + return jsonify(result) except Exception as e: return jsonify({'error': f'获取详情失败: {str(e)}'}), 500 +@app.route('/api/topics//search-results', methods=['GET']) +def get_topic_search_results(topic_id): + """获取主题的所有搜索结果""" + conn = get_db() + results = conn.execute( + 'SELECT * FROM search_results WHERE topic_id=? ORDER BY created_at DESC', + (topic_id,) + ).fetchall() + conn.close() + return jsonify([dict(r) for r in results]) + + +@app.route('/api/search-results/', methods=['DELETE']) +def delete_search_result(result_id): + """删除单条搜索结果""" + conn = get_db() + conn.execute('DELETE FROM search_results WHERE id=?', (result_id,)) + conn.commit() + conn.close() + return jsonify({'ok': True}) + + +@app.route('/api/topics//search-results', methods=['DELETE']) +def clear_topic_search_results(topic_id): + """清空主题的所有搜索结果""" + conn = get_db() + conn.execute('DELETE FROM search_results WHERE topic_id=?', (topic_id,)) + conn.commit() + conn.close() + return jsonify({'ok': True}) + + # ==================== LLM配置API ==================== @app.route('/api/llm-config', methods=['GET']) diff --git a/templates/topic.html b/templates/topic.html index 71a4085..57c09aa 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -221,14 +221,20 @@
- 网络搜索 - + 网络搜索 0 +
+ + +