|
|
@@ -848,6 +848,22 @@ def list_resources(
|
|
|
conn.close()
|
|
|
|
|
|
|
|
|
+@app.delete("/api/resource/{resource_id:path}")
|
|
|
+def delete_resource(resource_id: str):
|
|
|
+ """删除单个resource"""
|
|
|
+ conn = get_db()
|
|
|
+ try:
|
|
|
+ row = conn.execute("SELECT id FROM resources WHERE id = ?", (resource_id,)).fetchone()
|
|
|
+ if not row:
|
|
|
+ raise HTTPException(status_code=404, detail=f"Resource not found: {resource_id}")
|
|
|
+
|
|
|
+ conn.execute("DELETE FROM resources WHERE id = ?", (resource_id,))
|
|
|
+ conn.commit()
|
|
|
+ return {"status": "ok", "id": resource_id}
|
|
|
+ finally:
|
|
|
+ conn.close()
|
|
|
+
|
|
|
+
|
|
|
# --- Knowledge API ---
|
|
|
|
|
|
|
|
|
@@ -2723,18 +2739,24 @@ def frontend():
|
|
|
class="text-xs px-2 py-1 bg-gray-100 hover:bg-gray-200 border rounded cursor-pointer text-gray-700 font-mono transition">
|
|
|
${kid.length > 24 ? kid.slice(0, 24) + '...' : kid}
|
|
|
</span>`).join('');
|
|
|
+
|
|
|
+ const meta = tool.metadata || {};
|
|
|
+ const scenariosMd = Array.isArray(meta.scenarios) && meta.scenarios.length > 0
|
|
|
+ ? meta.scenarios.map(s => `<li>${escapeHtml(s)}</li>`).join('')
|
|
|
+ : '<li class="text-gray-400">暂无</li>';
|
|
|
+
|
|
|
detailEl.innerHTML = `
|
|
|
<div class="mb-6 border-b pb-4">
|
|
|
<h2 class="text-3xl font-black text-gray-900 mb-3">${escapeHtml(tool.title || id)}</h2>
|
|
|
<div class="flex gap-2 flex-wrap text-sm mb-3">
|
|
|
<span class="px-2.5 py-1 bg-indigo-50 text-indigo-700 rounded-md border border-indigo-100">
|
|
|
- 📁 分类: ${escapeHtml(tool.metadata && tool.metadata.category ? tool.metadata.category : '–')}
|
|
|
+ 📁 分类: ${escapeHtml(meta.category || '–')}
|
|
|
</span>
|
|
|
<span class="px-2.5 py-1 bg-gray-50 text-gray-700 rounded-md border border-gray-200">
|
|
|
- 🏷️ 状态: ${escapeHtml(tool.metadata && tool.metadata.status ? tool.metadata.status : '–')}
|
|
|
+ 🏷️ 状态: ${escapeHtml(meta.status || '–')}
|
|
|
</span>
|
|
|
<span class="px-2.5 py-1 bg-blue-50 text-blue-700 rounded-md border border-blue-100">
|
|
|
- 📌 Slug: ${escapeHtml(tool.metadata && tool.metadata.tool_slug ? tool.metadata.tool_slug : '–')}
|
|
|
+ 📌 Slug: ${escapeHtml(meta.tool_slug || '–')}
|
|
|
</span>
|
|
|
</div>
|
|
|
<div class="flex gap-1 flex-wrap items-center">
|
|
|
@@ -2742,15 +2764,60 @@ def frontend():
|
|
|
${knowledgeHtml}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="markdown-body text-gray-800 leading-relaxed max-w-none">
|
|
|
- <style>
|
|
|
- .markdown-body h2 { font-size: 1.4rem; font-weight: 700; margin-top: 1.5rem; margin-bottom: 0.75rem; border-bottom: 1px solid #e5e7eb; padding-bottom: 0.25rem; }
|
|
|
- .markdown-body h3 { font-size: 1.15rem; font-weight: 600; margin-top: 1.25rem; margin-bottom: 0.5rem; }
|
|
|
- .markdown-body ul { list-style-type: disc; padding-left: 1.5rem; margin-bottom: 1rem; }
|
|
|
- .markdown-body p { margin-bottom: 0.75rem; }
|
|
|
- .markdown-body strong { font-weight: 600; color: #111827; }
|
|
|
- </style>
|
|
|
- ${typeof marked !== 'undefined' ? marked.parse(tool.body || '*(该工具没有文档内容)*') : escapeHtml(tool.body || '*(该工具没有文档内容)*')}
|
|
|
+
|
|
|
+ <div class="text-gray-800 leading-relaxed max-w-none space-y-6">
|
|
|
+ <div>
|
|
|
+ <h3 class="text-lg font-bold border-b pb-2 mb-3">基础概览</h3>
|
|
|
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
|
|
+ <div><span class="text-gray-500 font-semibold">工具版本:</span> ${escapeHtml(meta.version || '–')}</div>
|
|
|
+ </div>
|
|
|
+ <div class="mt-3">
|
|
|
+ <span class="text-gray-500 font-semibold text-sm block mb-1">功能介绍:</span>
|
|
|
+ <div class="bg-gray-50 p-3 rounded-md text-sm border">${escapeHtml(meta.description || '暂无')}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <h3 class="text-lg font-bold border-b pb-2 mb-3">使用指南</h3>
|
|
|
+ <div class="mb-4">
|
|
|
+ <span class="text-gray-500 font-semibold text-sm block mb-1">用法:</span>
|
|
|
+ <div class="bg-gray-50 p-3 rounded-md text-sm border whitespace-pre-wrap">${escapeHtml(meta.usage || '暂无')}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500 font-semibold text-sm block mb-1">应用场景:</span>
|
|
|
+ <ul class="list-disc pl-5 space-y-1 text-sm">${scenariosMd}</ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <h3 class="text-lg font-bold border-b pb-2 mb-3">技术规格</h3>
|
|
|
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500 font-semibold text-sm block mb-1">输入:</span>
|
|
|
+ <div class="bg-gray-50 p-3 rounded-md text-sm border h-full">${escapeHtml(meta.input || '暂无')}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="text-gray-500 font-semibold text-sm block mb-1">输出:</span>
|
|
|
+ <div class="bg-gray-50 p-3 rounded-md text-sm border h-full">${escapeHtml(meta.output || '暂无')}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ ${meta.source ? `
|
|
|
+ <div>
|
|
|
+ <h3 class="text-lg font-bold border-b pb-2 mb-3">消息信源</h3>
|
|
|
+ <div class="text-sm overflow-hidden break-words text-blue-600 hover:underline">
|
|
|
+ ${escapeHtml(meta.source)}
|
|
|
+ </div>
|
|
|
+ </div>` : ''}
|
|
|
+
|
|
|
+ ${tool.body ? `
|
|
|
+ <div class="pt-4 mt-6 border-t border-dashed">
|
|
|
+ <h3 class="text-lg font-bold mb-3 text-gray-500">补充说明 (文档内容)</h3>
|
|
|
+ <div class="markdown-body bg-gray-50 p-4 rounded-lg border text-sm">
|
|
|
+ ${typeof marked !== 'undefined' ? marked.parse(tool.body) : escapeHtml(tool.body)}
|
|
|
+ </div>
|
|
|
+ </div>` : ''}
|
|
|
</div>`;
|
|
|
} catch (err) {
|
|
|
detailEl.innerHTML = '<div class="text-red-500 flex h-full items-center justify-center">加载详情失败,请检查网络或日志</div>';
|