From f923f6ccebc5e8090a83ba02fbf9668fb517aeed Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 22 Jul 2026 18:44:38 +0800 Subject: [PATCH] fix: api/kb/list returns widget JSON, remove broken dspy files --- init.py | 21 ++++++++- .../knowledge_bases_list/get_kb_cards.dspy | 46 ------------------- wwwroot/knowledge_bases_list/index.ui | 25 +++------- wwwroot/knowledge_bases_list/tree_crud.dspy | 42 ----------------- 4 files changed, 26 insertions(+), 108 deletions(-) delete mode 100644 wwwroot/knowledge_bases_list/get_kb_cards.dspy delete mode 100644 wwwroot/knowledge_bases_list/tree_crud.dspy diff --git a/init.py b/init.py index 30212a5..4ce6921 100644 --- a/init.py +++ b/init.py @@ -24,8 +24,25 @@ async def kb_list_handler(request, params_kw, *args, **kwargs): userorgid = await env.get_userorgid() async with get_sor_context(env, 'rag') as sor: recs = await sor.R("knowledge_bases", {"org_id": userorgid}) - rows = [dict(r) for r in recs] - return json.dumps({"status": "SUCCEEDED", "data": {"rows": rows, "total": len(rows)}}, ensure_ascii=False, default=str) + cards = [] + for r in recs: + doc_recs = await sor.R("documents", {"kb_id": r.id}) + doc_count = len(doc_recs) + total_size = r.total_size or 0 + size_str = f"{total_size/1024:.0f}KB" if total_size else "0B" + engine = r.embedding_engine or "CLIP" + card = {"widgettype":"VBox","options":{"cwidth":16,"cheight":12,"bgcolor":"#f0f7ff","padding":"16px","css":"card clickable","border":"1px solid #d0e4f7"},"subwidgets":[ + {"widgettype":"Text","options":{"text":"📚 " + str(r.name),"cfontsize":16,"fontWeight":"bold"}}, + {"widgettype":"Text","options":{"text":str(engine)+" · 1024维","cfontsize":12,"color":"#888"}}, + {"widgettype":"HBox","options":{"spacing":"12px"},"subwidgets":[ + {"widgettype":"Text","options":{"text":"📄 "+str(doc_count)+"文档","cfontsize":12,"color":"#666"}}, + {"widgettype":"Text","options":{"text":"💾 "+size_str,"cfontsize":12,"color":"#666"}}]}], + "binds":[{"wid":"self","event":"click","actiontype":"urlwidget","target":"app.rag_main_content","mode":"replace","options":{"url":"/knowledge_bases_list/detail.ui"}}]} + cards.append(card) + if not cards: + cards.append({"widgettype":"Text","options":{"text":"暂无知识库","color":"#aaa","cfontsize":14,"halign":"center"}}) + result = {"widgettype":"HBox","options":{"width":"100%","spacing":"12px","wrap":True},"subwidgets":cards} + return json.dumps(result, ensure_ascii=False) except Exception as e: exception(f"kb_list: {e}, {format_exc()}") return json.dumps({"error": str(e)}) diff --git a/wwwroot/knowledge_bases_list/get_kb_cards.dspy b/wwwroot/knowledge_bases_list/get_kb_cards.dspy deleted file mode 100644 index de5d854..0000000 --- a/wwwroot/knowledge_bases_list/get_kb_cards.dspy +++ /dev/null @@ -1,46 +0,0 @@ -import asyncio - -async def _do(): - env = request._run_ns - userorgid = await env.get_userorgid() - cards = [] - async with get_sor_context(env, 'rag') as sor: - recs = await sor.R("knowledge_bases", {"org_id": userorgid}) - for r in recs: - doc_recs = await sor.R("documents", {"kb_id": r.id}) - doc_count = len(doc_recs) - total_size = r.total_size or 0 - if total_size > 1073741824: - size_str = f"{total_size/1073741824:.1f}GB" - elif total_size > 1048576: - size_str = f"{total_size/1048576:.0f}MB" - else: - size_str = f"{total_size/1024:.0f}KB" - engine = r.embedding_engine or "CLIP" - card = { - "widgettype": "VBox", - "options": { - "cwidth": 16, "cheight": 12, "bgcolor": "#f0f7ff", - "padding": "16px", "css": "card clickable", - "border": "1px solid #d0e4f7" - }, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "📚 " + str(r.name), "cfontsize": 16, "fontWeight": "bold"}}, - {"widgettype": "Text", "options": {"text": str(engine) + " · 1024维", "cfontsize": 12, "color": "#888"}}, - {"widgettype": "HBox", "options": {"spacing": "12px"}, "subwidgets": [ - {"widgettype": "Text", "options": {"text": "📄 " + str(doc_count) + "文档", "cfontsize": 12, "color": "#666"}}, - {"widgettype": "Text", "options": {"text": "💾 " + size_str, "cfontsize": 12, "color": "#666"}} - ]} - ], - "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", - "target": "app.rag_main_content", "mode": "replace", - "options": {"url": entire_url('/knowledge_bases_list/detail.ui')}}] - } - cards.append(card) - return { - "widgettype": "HBox", - "options": {"width": "100%", "spacing": "12px", "wrap": True}, - "subwidgets": cards - } - -result = asyncio.get_event_loop().run_until_complete(_do()) diff --git a/wwwroot/knowledge_bases_list/index.ui b/wwwroot/knowledge_bases_list/index.ui index 0c448b4..e2656ed 100644 --- a/wwwroot/knowledge_bases_list/index.ui +++ b/wwwroot/knowledge_bases_list/index.ui @@ -9,30 +9,19 @@ "subwidgets": [ { "widgettype": "HBox", - "options": { - "width": "100%", - "justifyContent": "space-between", - "alignItems": "center" - }, + "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [ - { - "widgettype": "VBox", - "options": {"spacing": "4px"}, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "知识库", "cfontsize": 22, "fontWeight": "bold", "color": "#333"}}, - {"widgettype": "Text", "options": {"text": "点击知识库进入文档管理,支持多级目录和拖拽上传", "cfontsize": 14, "color": "#888"}} - ] - }, - { - "widgettype": "Button", - "options": {"label": "+ 新建知识库", "bgcolor": "#4a90d9", "color": "#fff"} - } + {"widgettype": "VBox", "options": {"spacing": "4px"}, "subwidgets": [ + {"widgettype": "Text", "options": {"text": "知识库", "cfontsize": 22, "fontWeight": "bold", "color": "#333"}}, + {"widgettype": "Text", "options": {"text": "点击知识库进入文档管理,支持多级目录和拖拽上传", "cfontsize": 14, "color": "#888"}} + ]}, + {"widgettype": "Button", "options": {"label": "+ 新建知识库", "bgcolor": "#4a90d9", "color": "#fff"}} ] }, { "widgettype": "urlwidget", "options": { - "url": "{{entire_url('/knowledge_bases_list/get_kb_cards.dspy')}}" + "url": "{{entire_url('/api/kb/list')}}" } } ] diff --git a/wwwroot/knowledge_bases_list/tree_crud.dspy b/wwwroot/knowledge_bases_list/tree_crud.dspy deleted file mode 100644 index 25693ac..0000000 --- a/wwwroot/knowledge_bases_list/tree_crud.dspy +++ /dev/null @@ -1,42 +0,0 @@ -import asyncio - -async def _do(): - action = params_kw.get("action", "") - kb_id = params_kw.get("kb_id", "") - env = request._run_ns - folder_label = params_kw.get("folder_label", "") - - if action == "create_dir": - dir_name = params_kw.get("dir_name", "") - parent_id = params_kw.get("parent_id", "") - if dir_name: - async with get_sor_context(env, 'rag') as sor: - dir_id = "dir_" + str(abs(hash(dir_name + parent_id)))[:12] - await sor.sqlExe( - "INSERT INTO document_chunks (id, doc_id, kb_id, chunk_index, chunk_type, content, description, created_at) " - "VALUES (${id}$, '', ${kb_id}$, 0, 'directory', ${name}$, ${parent}$, NOW())", - {"id": dir_id, "kb_id": kb_id, "name": dir_name, "parent": parent_id}) - folder_label = folder_label or dir_name - - elif action == "delete_item": - item_id = params_kw.get("item_id", "") - if item_id: - async with get_sor_context(env, 'rag') as sor: - await sor.sqlExe("DELETE FROM document_chunks WHERE id=${id}$", {"id": item_id}) - - return { - "widgettype": "VBox", - "options": {"spacing": "12px"}, - "subwidgets": [ - { - "widgettype": "HBox", - "options": {"spacing": "4px"}, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "📂 " + str(folder_label), "cfontsize": 16, "fontWeight": "bold", "color": "#333"}}, - {"widgettype": "Text", "options": {"text": "操作成功", "cfontsize": 12, "color": "#50b86c"}} - ] - } - ] - } - -result = asyncio.get_event_loop().run_until_complete(_do())