feat: 知识库数据添加显示开关功能

- knowledge API添加visible字段支持
- 前台过滤隐藏的知识条目(默认)
- 后台显示全部知识条目(all=1)
- 新增toggle knowledge visible API
- 知识库表格增加显示开关列
This commit is contained in:
2026-04-11 02:32:10 +08:00
parent 74be7688c9
commit 627148a87f
3 changed files with 42 additions and 6 deletions

19
app.py
View File

@@ -738,6 +738,11 @@ def api_knowledge():
"""获取知识列表""" """获取知识列表"""
knowledge = load_data(KNOWLEDGE_FILE) knowledge = load_data(KNOWLEDGE_FILE)
# 过滤隐藏项(前台默认隐藏)
hide_hidden = request.args.get('all', '0') == '0'
if hide_hidden:
knowledge = [k for k in knowledge if k.get('visible', True)]
keyword = request.args.get('q', '').strip().lower() keyword = request.args.get('q', '').strip().lower()
if keyword: if keyword:
knowledge = [k for k in knowledge if keyword in k.get('title', '').lower() or keyword in k.get('content', '').lower()] knowledge = [k for k in knowledge if keyword in k.get('title', '').lower() or keyword in k.get('content', '').lower()]
@@ -767,6 +772,7 @@ def api_create_knowledge():
data['id'] = uuid.uuid4().hex[:12] data['id'] = uuid.uuid4().hex[:12]
data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
data['visible'] = data.get('visible', True) # 默认显示
if 'order' not in data: if 'order' not in data:
data['order'] = len(knowledge) data['order'] = len(knowledge)
@@ -800,6 +806,19 @@ def api_delete_knowledge(knowledge_id):
return jsonify({'success': True}) return jsonify({'success': True})
@app.route('/api/knowledge/<knowledge_id>/visible', methods=['POST'])
def api_toggle_knowledge_visible(knowledge_id):
"""切换知识显示状态"""
knowledge = load_data(KNOWLEDGE_FILE)
item = next((k for k in knowledge if k['id'] == knowledge_id), None)
if not item:
return jsonify({'error': 'Knowledge not found'}), 404
item['visible'] = not item.get('visible', True)
save_data(KNOWLEDGE_FILE, knowledge)
return jsonify({'success': True, 'visible': item['visible']})
# ============ 动态分类数据API ============ # ============ 动态分类数据API ============
@app.route('/api/items/<category_id>') @app.route('/api/items/<category_id>')

10
data/config.json Normal file
View File

@@ -0,0 +1,10 @@
{
"site_name": "ParamHub",
"site_subtitle": "参数百科",
"footer_text": "ParamHub - 模型与硬件参数速查平台",
"icp_number": "",
"copyright_year": "2026",
"contact_email": "wlq@tphai.com",
"github_url": "",
"updated_at": "2026-04-11 02:28:39"
}

View File

@@ -235,10 +235,11 @@
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">分类</th> <th class="px-4 py-3 text-left text-sm font-medium text-gray-600">分类</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">简介</th> <th class="px-4 py-3 text-left text-sm font-medium text-gray-600">简介</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">排序</th> <th class="px-4 py-3 text-left text-sm font-medium text-gray-600">排序</th>
<th class="px-4 py-3 text-center text-sm font-medium text-gray-600">显示</th>
<th class="px-4 py-3 text-center text-sm font-medium text-gray-600">操作</th> <th class="px-4 py-3 text-center text-sm font-medium text-gray-600">操作</th>
</tr> </tr>
</thead> </thead>
<tbody id="admin-knowledge-table"><tr><td colspan="6" class="text-center text-gray-400 py-8">加载中...</td></tr></tbody> <tbody id="admin-knowledge-table"><tr><td colspan="7" class="text-center text-gray-400 py-8">加载中...</td></tr></tbody>
</table> </table>
</div> </div>
</section> </section>
@@ -702,20 +703,25 @@ GPT-4是OpenAI发布的大语言模型参数量约1.8万亿支持128K上
categories = await catRes.json(); categories = await catRes.json();
document.getElementById('category-filters').innerHTML = categories.map(c => `<button onclick="filterKnowledge('${c.id}')" class="px-3 py-1 rounded text-sm bg-gray-100 text-gray-600 hover:bg-gray-200">${c.name}</button>`).join(''); document.getElementById('category-filters').innerHTML = categories.map(c => `<button onclick="filterKnowledge('${c.id}')" class="px-3 py-1 rounded text-sm bg-gray-100 text-gray-600 hover:bg-gray-200">${c.name}</button>`).join('');
let url = '/api/knowledge'; let url = '/api/knowledge?all=1';
if (currentFilter) url += `?category=${currentFilter}`; if (currentFilter) url += `&category=${currentFilter}`;
const res = await fetch(url); const res = await fetch(url);
const knowledge = await res.json(); const knowledge = await res.json();
if (knowledge.length === 0) { document.getElementById('admin-knowledge-table').innerHTML = '<tr><td colspan="6" class="text-center text-gray-400 py-8">暂无数据</td></tr>'; return; } if (knowledge.length === 0) { document.getElementById('admin-knowledge-table').innerHTML = '<tr><td colspan="7" class="text-center text-gray-400 py-8">暂无数据</td></tr>'; return; }
document.getElementById('admin-knowledge-table').innerHTML = knowledge.map(k => { document.getElementById('admin-knowledge-table').innerHTML = knowledge.map(k => {
const cat = categories.find(c => c.id === k.category); const cat = categories.find(c => c.id === k.category);
return `<tr class="border-b hover:bg-gray-50"> return `<tr class="border-b hover:bg-gray-50 ${k.visible === false ? 'bg-gray-100 opacity-60' : ''}">
<td class="px-4 py-3"><i class="${k.icon || 'ri-file-list-line'} text-xl text-gray-400"></i></td> <td class="px-4 py-3"><i class="${k.icon || 'ri-file-list-line'} text-xl text-gray-400"></i></td>
<td class="px-4 py-3 font-medium text-gray-800">${k.title}</td> <td class="px-4 py-3 font-medium text-gray-800">${k.title}</td>
<td class="px-4 py-3 text-gray-600">${cat ? cat.name : '-'}</td> <td class="px-4 py-3 text-gray-600">${cat ? cat.name : '-'}</td>
<td class="px-4 py-3 text-gray-500 text-sm max-w-xs truncate">${k.content || '-'}</td> <td class="px-4 py-3 text-gray-500 text-sm max-w-xs truncate">${k.content || '-'}</td>
<td class="px-4 py-3">${k.order || 0}</td> <td class="px-4 py-3">${k.order || 0}</td>
<td class="px-4 py-3 text-center">
<button onclick="toggleVisible('knowledge', '${k.id}')" class="${k.visible === false ? 'text-gray-400' : 'text-green-600'} hover:opacity-80" title="${k.visible === false ? '点击显示' : '点击隐藏'}">
<i class="${k.visible === false ? 'ri-eye-off-line' : 'ri-eye-line'}"></i>
</button>
</td>
<td class="px-4 py-3 text-center"> <td class="px-4 py-3 text-center">
<button onclick="editItem('knowledge', '${k.id}')" class="text-blue-600 hover:text-blue-800 mr-2"><i class="ri-edit-line"></i></button> <button onclick="editItem('knowledge', '${k.id}')" class="text-blue-600 hover:text-blue-800 mr-2"><i class="ri-edit-line"></i></button>
<button onclick="deleteItem('knowledge', '${k.id}')" class="text-red-600 hover:text-red-800"><i class="ri-delete-bin-line"></i></button> <button onclick="deleteItem('knowledge', '${k.id}')" class="text-red-600 hover:text-red-800"><i class="ri-delete-bin-line"></i></button>
@@ -1027,6 +1033,7 @@ GPT-4是OpenAI发布的大语言模型参数量约1.8万亿支持128K上
else if (type === 'model') endpoint = `/api/models/${id}/visible`; else if (type === 'model') endpoint = `/api/models/${id}/visible`;
else if (type === 'gpu') endpoint = `/api/gpus/${id}/visible`; else if (type === 'gpu') endpoint = `/api/gpus/${id}/visible`;
else if (type === 'cpu') endpoint = `/api/cpus/${id}/visible`; else if (type === 'cpu') endpoint = `/api/cpus/${id}/visible`;
else if (type === 'knowledge') endpoint = `/api/knowledge/${id}/visible`;
else if (type === 'dynamic') endpoint = `/api/items/${dynamicCategoryId}/${id}/visible`; else if (type === 'dynamic') endpoint = `/api/items/${dynamicCategoryId}/${id}/visible`;
try { try {
@@ -1035,7 +1042,7 @@ GPT-4是OpenAI发布的大语言模型参数量约1.8万亿支持128K上
// 刷新列表 // 刷新列表
if (type === 'dynamic') showDynamicCategory(dynamicCategoryId); if (type === 'dynamic') showDynamicCategory(dynamicCategoryId);
else { else {
const loaders = {category: loadAdminCategories, model: loadAdminModels, gpu: loadAdminGpus, cpu: loadAdminCpus}; const loaders = {category: loadAdminCategories, model: loadAdminModels, gpu: loadAdminGpus, cpu: loadAdminCpus, knowledge: loadAdminKnowledge};
loaders[type](); loaders[type]();
} }
} catch (e) { } catch (e) {