From c6110522c1f2c61057e2592ac7f07152a7149f57 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 30 Jul 2026 18:00:00 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20root=20folder=20upload=20=5F=5Froot=5F?= =?UTF-8?q?=5F=20=E2=86=92=20empty=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wwwroot/knowledge_bases_list/detail.ui | 248 ++++++++++++++++---- wwwroot/knowledge_bases_list/file_list.dspy | 2 +- 2 files changed, 204 insertions(+), 46 deletions(-) diff --git a/wwwroot/knowledge_bases_list/detail.ui b/wwwroot/knowledge_bases_list/detail.ui index d0109cb..6364e94 100644 --- a/wwwroot/knowledge_bases_list/detail.ui +++ b/wwwroot/knowledge_bases_list/detail.ui @@ -1,77 +1,235 @@ { "widgettype": "VBox", - "options": {"cheight": 40, "width": "100%", "padding": "0", "spacing": 0}, + "options": { + "cheight": 40, + "width": "100%", + "padding": "0", + "spacing": 0 + }, "subwidgets": [ { "widgettype": "HBox", - "options": {"width": "100%", "bgcolor": "#f8f9fa", "padding": "10px 16px", "alignItems": "center", "borderBottom": "1px solid #e0e0e0"}, + "options": { + "width": "100%", + "bgcolor": "#f8f9fa", + "padding": "10px 16px", + "alignItems": "center", + "borderBottom": "1px solid #e0e0e0" + }, "subwidgets": [ - {"widgettype": "Text", "options": {"text": "← 知识库列表", "css": "clickable", "cfontsize": 14, "color": "#4a90d9"}, - "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", - "options": {"url": "{{entire_url('/rag/knowledge_bases_list/index.ui')}}"}}]}, - {"widgettype": "Text", "options": {"text": " / ", "cfontsize": 14, "color": "#ccc"}}, - {"widgettype": "Text", "options": {"text": "📚 {{params_kw.kb_name or '知识库'}}", "cfontsize": 16, "fontWeight": "bold", "color": "#333"}}, - {"widgettype": "Text", "options": {"text": "", "css": "filler"}} + { + "widgettype": "Text", + "options": { + "text": "← 知识库列表", + "css": "clickable", + "cfontsize": 14, + "color": "#4a90d9" + }, + "binds": [ + { + "wid": "self", + "event": "click", + "actiontype": "urlwidget", + "target": "app.rag_main_content", + "mode": "replace", + "options": { + "url": "{{entire_url('/rag/knowledge_bases_list/index.ui')}}" + } + } + ] + }, + { + "widgettype": "Text", + "options": { + "text": " / ", + "cfontsize": 14, + "color": "#ccc" + } + }, + { + "widgettype": "Text", + "options": { + "text": "📚 {{params_kw.kb_name or '知识库'}}", + "cfontsize": 16, + "fontWeight": "bold", + "color": "#333" + } + }, + { + "widgettype": "Text", + "options": { + "text": "", + "css": "filler" + } + } ] }, { "widgettype": "HBox", - "options": {"css": "filler", "width": "100%", "spacing": 0}, + "options": { + "css": "filler", + "width": "100%", + "spacing": 0 + }, "subwidgets": [ { "widgettype": "VBox", - "options": {"cwidth": 16, "bgcolor": "#fafafa", "borderRight": "1px solid #e0e0e0", "spacing": 0, "overflow": "hidden", "flexShrink": "0"}, + "options": { + "cwidth": 16, + "bgcolor": "#fafafa", + "borderRight": "1px solid #e0e0e0", + "spacing": 0, + "overflow": "hidden", + "flexShrink": "0" + }, "subwidgets": [ - {"widgettype": "HBox", "options": {"padding": "10px 12px", "bgcolor": "#f0f0f0", "borderBottom": "1px solid #e0e0e0"}, - "subwidgets": [{"widgettype": "Text", "options": {"text": "📁 目录结构", "cfontsize": 13, "fontWeight": "bold", "color": "#666"}}]}, - {"widgettype": "Tree", "id": "dir_tree", - "options": {"select_only": true, "title": "目录", "parentField": "parentid", "idField": "id", "textField": "label", - "dataurl": "{{entire_url('./get_tree_data.dspy')}}?kb_id={{params_kw.kb_id}}", - "newdata_params": {"kb_id": "{{params_kw.kb_id}}"}, - "editable": {"fields": [{"name": "name", "title": "名称", "type": "str", "length": 255, "uitype": "str", "label": "名称"}], - "add_url": "{{entire_url('./new_tree_item.dspy')}}", - "update_url": "{{entire_url('./update_tree_item.dspy')}}", - "delete_url": "{{entire_url('./delete_tree_item.dspy')}}"}}} + { + "widgettype": "HBox", + "options": { + "padding": "10px 12px", + "bgcolor": "#f0f0f0", + "borderBottom": "1px solid #e0e0e0" + }, + "subwidgets": [ + { + "widgettype": "Text", + "options": { + "text": "📁 目录结构", + "cfontsize": 13, + "fontWeight": "bold", + "color": "#666" + } + } + ] + }, + { + "widgettype": "Tree", + "id": "dir_tree", + "options": { + "select_only": true, + "title": "目录", + "parentField": "parentid", + "idField": "id", + "textField": "label", + "dataurl": "{{entire_url('./get_tree_data.dspy')}}?kb_id={{params_kw.kb_id}}", + "newdata_params": { + "kb_id": "{{params_kw.kb_id}}" + }, + "editable": { + "fields": [ + { + "name": "name", + "title": "名称", + "type": "str", + "length": 255, + "uitype": "str", + "label": "名称" + } + ], + "add_url": "{{entire_url('./new_tree_item.dspy')}}", + "update_url": "{{entire_url('./update_tree_item.dspy')}}", + "delete_url": "{{entire_url('./delete_tree_item.dspy')}}" + } + } + } ] }, { "widgettype": "VBox", "id": "detail_content", - "options": {"css": "filler", "padding": "16px", "spacing": "12px"}, + "options": { + "css": "filler", + "padding": "16px", + "spacing": "12px" + }, "subwidgets": [ { - "widgettype": "UiFile", "id": "file_drop_zone", - "options": {"accept": "", "multiple": true, "preview": false, + "widgettype": "UiFile", + "id": "file_drop_zone", + "options": { + "accept": "", + "multiple": true, + "preview": false, "otext": "📂 拖拽文件到此处上传,或点击选择文件", - "width": "100%", "cheight": 10, "css": "card", - "border": "2px dashed #3b82f6", "alignItems": "center", "justifyContent": "center", - "kb_id": "{{params_kw.kb_id}}"}, + "width": "100%", + "cheight": 10, + "css": "card", + "border": "2px dashed #3b82f6", + "alignItems": "center", + "justifyContent": "center", + "kb_id": "{{params_kw.kb_id}}" + }, "binds": [ - {"wid": "self", "event": "dragover", "actiontype": "script", - "script": "event.preventDefault();event.stopPropagation()"}, - {"wid": "self", "event": "drop", "actiontype": "script", - "script": "event.preventDefault();event.stopPropagation()"} + { + "wid": "self", + "event": "dragover", + "actiontype": "script", + "script": "event.preventDefault();event.stopPropagation()" + }, + { + "wid": "self", + "event": "drop", + "actiontype": "script", + "script": "event.preventDefault();event.stopPropagation()" + } ] }, - {"widgettype": "Text", "id": "upload_status", - "options": {"cfontsize": 12, "color": "#50b86c", "marginTop": "0", "text": "支持 TXT/PDF/JPG/PNG/MP3/WAV/MP4"}}, - {"widgettype": "VScrollPanel", "id": "file_list_panel", - "options": {"css": "filler", "padding": "0", "spacing": "0"}, - "subwidgets": [ - {"widgettype": "urlwidget", - "options": {"url": "{{entire_url('./file_list.dspy')}}?kb_id={{params_kw.kb_id}}", "css": "filler"}} - ]} + { + "widgettype": "Text", + "id": "upload_status", + "options": { + "cfontsize": 12, + "color": "#50b86c", + "marginTop": "0", + "text": "支持 TXT/PDF/JPG/PNG/MP3/WAV/MP4" + } + }, + { + "widgettype": "VScrollPanel", + "id": "file_list_panel", + "options": { + "css": "filler", + "padding": "0", + "spacing": "0" + }, + "subwidgets": [ + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('./file_list.dspy')}}?kb_id={{params_kw.kb_id}}", + "css": "filler" + } + } + ] + } ] } ] } ], "binds": [ - {"wid": "dir_tree", "event": "node_selected", "actiontype": "script", - "script": "window._rag_folder=event.params.id||''"}, - {"wid": "file_drop_zone", "event": "changed", "actiontype": "script", "target": "file_drop_zone", - "script": "var kb_id=this.opts.kb_id||'';var tree=bricks.getWidgetById('dir_tree',bricks.app.root);var folder=window._rag_folder||'';var files=this.value;if(!files)return;if(!Array.isArray(files))files=[files];var st=document.getElementById('upload_status');var done=0;var total=files.length;function refreshList(){var fp=bricks.getWidgetById('file_list_panel',bricks.app.root);fp.clear_widgets();var url=location.origin+'/rag/knowledge_bases_list/file_list.dspy?_webbricks_=1&kb_id='+kb_id+(folder?'&id='+folder:'');bricks.widgetBuild({widgettype:'urlwidget',options:{url:url,css:'filler'}},fp).then(function(w){if(w)fp.add_widget(w)})};for(var i=0;i=total)refreshList()};x.onerror=function(){done++;if(st)st.innerText='上传失败';if(done>=total)refreshList()};x.send(f)})(files[i])}"}, - {"wid": "dir_tree", "event": "node_selected", "actiontype": "urlwidget", "target": "file_list_panel", "mode": "replace", - "options": {"url": "{{entire_url('./file_list.dspy')}}?kb_id={{params_kw.kb_id}}"}} + { + "wid": "dir_tree", + "event": "node_selected", + "actiontype": "script", + "script": "window._rag_folder=event.params.id||''" + }, + { + "wid": "file_drop_zone", + "event": "changed", + "actiontype": "script", + "target": "file_drop_zone", + "script": "var kb_id=this.opts.kb_id||'';var tree=bricks.getWidgetById('dir_tree',bricks.app.root);var folder=window._rag_folder||'';if(folder==='__root__')folder='';var files=this.value;if(!files)return;if(!Array.isArray(files))files=[files];var st=document.getElementById('upload_status');var done=0;var total=files.length;function refreshList(){var fp=bricks.getWidgetById('file_list_panel',bricks.app.root);fp.clear_widgets();var url=location.origin+'/rag/knowledge_bases_list/file_list.dspy?_webbricks_=1&kb_id='+kb_id+(folder?'&id='+folder:'');bricks.widgetBuild({widgettype:'urlwidget',options:{url:url,css:'filler'}},fp).then(function(w){if(w)fp.add_widget(w)})};for(var i=0;i=total)refreshList()};x.onerror=function(){done++;if(st)st.innerText='上传失败';if(done>=total)refreshList()};x.send(f)})(files[i])}" + }, + { + "wid": "dir_tree", + "event": "node_selected", + "actiontype": "urlwidget", + "target": "file_list_panel", + "mode": "replace", + "options": { + "url": "{{entire_url('./file_list.dspy')}}?kb_id={{params_kw.kb_id}}" + } + } ] -} +} \ No newline at end of file diff --git a/wwwroot/knowledge_bases_list/file_list.dspy b/wwwroot/knowledge_bases_list/file_list.dspy index 11b7b64..04942ea 100644 --- a/wwwroot/knowledge_bases_list/file_list.dspy +++ b/wwwroot/knowledge_bases_list/file_list.dspy @@ -18,7 +18,7 @@ try: {"kb_id": kb_id, "folder_id": folder_id}) else: recs = await sor.sqlExe( - "SELECT id, file_name, file_type, file_size, file_path, status, chunk_count, created_at FROM documents WHERE kb_id=${kb_id}$ AND (folder_id IS NULL OR folder_id='') ORDER BY created_at DESC", + "SELECT id, file_name, file_type, file_size, file_path, status, chunk_count, created_at FROM documents WHERE kb_id=${kb_id}$ AND (folder_id IS NULL OR folder_id IN ('','__root__')) ORDER BY created_at DESC", {"kb_id": kb_id}) for r in recs: rows.append({