feat: 搜索结果持久化保存 + 结果数量可配置
- 新增 search_results 表,搜索结果按主题持久保存 - 搜索API自动保存结果到数据库,获取详情时更新raw_content - 页面加载时自动加载历史搜索结果,按搜索词分组显示 - 支持单条删除和清空所有搜索结果 - 搜索结果数量默认10条,可通过输入框调整(1-20) - 搜索面板标题显示结果计数badge
This commit is contained in:
88
app.py
88
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/<topic_id>/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/<result_id>', 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/<topic_id>/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'])
|
||||
|
||||
Reference in New Issue
Block a user