diff --git a/wwwroot/knowledge_bases_list/delete_tree_item.dspy b/wwwroot/knowledge_bases_list/delete_tree_item.dspy new file mode 100644 index 0000000..141f0bd --- /dev/null +++ b/wwwroot/knowledge_bases_list/delete_tree_item.dspy @@ -0,0 +1,7 @@ +ns = params_kw.copy() +db = DBPools() +dbname = get_module_dbname('rag') +async with db.sqlorContext(dbname) as sor: + await sor.sqlExe("DELETE FROM document_chunks WHERE id=${id}$", {"id": ns.get("id","")}) + return {"status": "SUCCEEDED"} +return {"error": "failed"} diff --git a/wwwroot/knowledge_bases_list/detail.ui b/wwwroot/knowledge_bases_list/detail.ui index 8b9b3c1..63f07d5 100644 --- a/wwwroot/knowledge_bases_list/detail.ui +++ b/wwwroot/knowledge_bases_list/detail.ui @@ -1,138 +1,60 @@ { "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('/knowledge_bases_list/index.ui')}}"}} + {"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", + "options": {"url": "{{entire_url('/knowledge_bases_list/index.ui')}}"}} ]}, {"widgettype": "Text", "options": {"text": " / ", "cfontsize": 14, "color": "#ccc"}}, {"widgettype": "Text", "options": {"text": "📚 产品文档", "cfontsize": 16, "fontWeight": "bold", "color": "#333"}}, - {"widgettype": "Text", "options": {"text": "", "css": "filler"}}, - {"widgettype": "Text", "options": {"text": "📄 12文档 · 📁 3目录 · 💾 256MB", "cfontsize": 12, "color": "#888"}} + {"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": 15, - "bgcolor": "#fafafa", - "borderRight": "1px solid #e0e0e0", - "spacing": 0 - }, + "options": {"cwidth": 16, "bgcolor": "#fafafa", "borderRight": "1px solid #e0e0e0", "spacing": 0}, "subwidgets": [ { "widgettype": "HBox", - "options": { - "padding": "10px 12px", - "bgcolor": "#f0f0f0", - "borderBottom": "1px solid #e0e0e0", - "justifyContent": "space-between", - "alignItems": "center" - }, + "options": {"padding": "10px 12px", "bgcolor": "#f0f0f0", "borderBottom": "1px solid #e0e0e0"}, "subwidgets": [ - {"widgettype": "Text", "options": {"text": "📁 目录结构", "cfontsize": 13, "fontWeight": "bold", "color": "#666"}}, - {"widgettype": "Text", "options": {"text": "+ 新建", "cfontsize": 12, "color": "#4a90d9", "css": "clickable"}} + {"widgettype": "Text", "options": {"text": "📁 目录结构", "cfontsize": 13, "fontWeight": "bold", "color": "#666"}} ] }, { "widgettype": "Tree", "options": { - "items": [ - { - "label": "技术文档", - "id": "folder_tech", - "icon": "📂", - "children": [ - {"label": "API参考.pdf", "id": "file_api", "icon": "📄"}, - {"label": "部署指南.md", "id": "file_deploy", "icon": "📄"}, - {"label": "接口规范", "id": "folder_api_spec", "icon": "📂", "children": [ - {"label": "REST API.md", "id": "file_rest", "icon": "📄"}, - {"label": "WebSocket.md", "id": "file_ws", "icon": "📄"} - ]} - ] - }, - { - "label": "产品介绍", - "id": "folder_product", - "icon": "📂" - }, - { - "label": "培训材料", - "id": "folder_training", - "icon": "📂" - } - ] - }, - "binds": [ - { - "wid": "self", - "event": "selected", - "actiontype": "urlwidget", - "target": "app.detail_content", - "mode": "replace", - "options": {"url": "{{entire_url('/knowledge_bases_list/folder_content.ui')}}", "params": {"folder_id": "${item.id}", "folder_label": "${item.label}"}} + "title": "目录", + "parentField": "parentid", + "idField": "id", + "textField": "label", + "dataurl": "{{entire_url('./get_tree_data.dspy')}}?kb_id=kb1", + "editable": { + "fields": [ + {"name": "name", "title": "名称", "type": "str", "length": 255, "uitype": "str", "label": "名称"} + ], + "add_url": "{{entire_url('./new_tree_item.dspy')}}?kb_id=kb1", + "update_url": "{{entire_url('./update_tree_item.dspy')}}", + "delete_url": "{{entire_url('./delete_tree_item.dspy')}}" } - ] + } } ] }, { "widgettype": "VBox", - "options": { - "id": "detail_content", - "css": "filler", - "padding": "16px", - "spacing": "12px" - }, + "options": {"id": "detail_content", "css": "filler", "padding": "16px", "spacing": "12px"}, "subwidgets": [ - { - "widgettype": "VBox", - "options": { - "width": "100%", - "cheight": 6, - "bgcolor": "#f8f9fa", - "padding": "16px", - "css": "card", - "border": "2px dashed #d0d0d0", - "alignItems": "center", - "justifyContent": "center" - }, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "📂 拖拽文件到此处上传", "cfontsize": 15, "color": "#888"}}, - {"widgettype": "Text", "options": {"text": "选中左侧目录后上传到该目录 · 支持 TXT/PDF/JPG/PNG/MP3/WAV/MP4", "cfontsize": 11, "color": "#aaa"}} - ] - }, - { - "widgettype": "Text", - "options": { - "text": "📂 全部分文件 · 请选择左侧目录查看具体内容", - "cfontsize": 13, - "color": "#aaa" - } - } + {"widgettype": "Text", "options": {"text": "📂 请选择左侧目录查看文件", "cfontsize": 14, "color": "#888"}} ] } ] diff --git a/wwwroot/knowledge_bases_list/folder_content.ui b/wwwroot/knowledge_bases_list/folder_content.ui deleted file mode 100644 index dd52050..0000000 --- a/wwwroot/knowledge_bases_list/folder_content.ui +++ /dev/null @@ -1,63 +0,0 @@ -{ - "widgettype": "VBox", - "options": { - "width": "100%", - "spacing": "12px" - }, - "subwidgets": [ - { - "widgettype": "HBox", - "options": { - "width": "100%", - "justifyContent": "space-between", - "alignItems": "center" - }, - "subwidgets": [ - { - "widgettype": "HBox", - "options": {"spacing": "4px", "alignItems": "center"}, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "📂", "cfontsize": 16}}, - {"widgettype": "Text", "options": {"text": "{{params_kw.folder_label or '全部文件'}}", "cfontsize": 16, "fontWeight": "bold", "color": "#333"}} - ] - }, - { - "widgettype": "HBox", - "options": {"spacing": "8px"}, - "subwidgets": [ - { - "widgettype": "Button", - "options": {"label": "📂 新建子目录", "bgcolor": "#e8e8e8", "color": "#666"}, - "binds": [ - { - "wid": "self", - "event": "tap", - "actiontype": "urlwidget", - "target": "app.detail_content", - "mode": "replace", - "options": { - "url": "{{entire_url('/knowledge_bases_list/new_dir_form.ui')}}", - "params": { - "kb_id": "{{params_kw.kb_id or ''}}", - "folder_id": "{{params_kw.folder_id or ''}}", - "folder_label": "{{params_kw.folder_label or ''}}" - } - } - } - ] - } - ] - } - ] - }, - { - "widgettype": "Text", - "options": { - "text": "当前目录暂无内容", - "color": "#aaa", - "cfontsize": 13, - "halign": "center" - } - } - ] -} diff --git a/wwwroot/knowledge_bases_list/get_tree_data.dspy b/wwwroot/knowledge_bases_list/get_tree_data.dspy new file mode 100644 index 0000000..a686236 --- /dev/null +++ b/wwwroot/knowledge_bases_list/get_tree_data.dspy @@ -0,0 +1,17 @@ +ns = params_kw.copy() +id = ns.get('id') +kb_id = ns.get('kb_id', '') +db = DBPools() +dbname = get_module_dbname('rag') +async with db.sqlorContext(dbname) as sor: + if not id: + recs = await sor.sqlExe( + "SELECT id, '' as parentid, content as label FROM document_chunks WHERE kb_id=${kb_id}$ AND chunk_type='directory' ORDER BY content", + {"kb_id": kb_id}) + return [dict(r) for r in recs] + else: + recs = await sor.sqlExe( + "SELECT id, '' as parentid, content as label FROM document_chunks WHERE kb_id=${kb_id}$ AND chunk_type='directory' AND parent_id=${id}$ ORDER BY content", + {"kb_id": kb_id, "id": id}) + return [dict(r) for r in recs] +return [] diff --git a/wwwroot/knowledge_bases_list/new_dir_form.ui b/wwwroot/knowledge_bases_list/new_dir_form.ui deleted file mode 100644 index 43cbc24..0000000 --- a/wwwroot/knowledge_bases_list/new_dir_form.ui +++ /dev/null @@ -1,55 +0,0 @@ -{ - "widgettype": "VBox", - "options": {"spacing": "12px", "padding": "16px"}, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "新建目录", "cfontsize": 18, "fontWeight": "bold"}}, - {"widgettype": "Text", "options": {"text": "", "cheight": 0.5}}, - {"widgettype": "Text", "options": {"text": "目录名称"}}, - { - "widgettype": "Input", - "options": {"id": "dir_name_input", "width": "100%"} - }, - { - "widgettype": "Button", - "options": {"label": "创建", "bgcolor": "#4a90d9", "color": "#fff"}, - "binds": [ - { - "wid": "self", - "event": "tap", - "actiontype": "urlwidget", - "target": "app.detail_content", - "mode": "replace", - "options": { - "url": "{{entire_url('/knowledge_bases_list/tree_crud.dspy')}}", - "params": { - "action": "create_dir", - "kb_id": "{{params_kw.kb_id or ''}}", - "dir_name": "${app.dir_name_input.text}", - "parent_id": "{{params_kw.folder_id or ''}}" - } - } - } - ] - }, - { - "widgettype": "Button", - "options": {"label": "取消", "bgcolor": "#e0e0e0", "color": "#666"}, - "binds": [ - { - "wid": "self", - "event": "tap", - "actiontype": "urlwidget", - "target": "app.detail_content", - "mode": "replace", - "options": { - "url": "{{entire_url('/knowledge_bases_list/folder_content.ui')}}", - "params": { - "folder_id": "{{params_kw.folder_id or ''}}", - "folder_label": "{{params_kw.folder_label or ''}}" - } - } - } - ] - } - ] -} diff --git a/wwwroot/knowledge_bases_list/new_tree_item.dspy b/wwwroot/knowledge_bases_list/new_tree_item.dspy new file mode 100644 index 0000000..957a836 --- /dev/null +++ b/wwwroot/knowledge_bases_list/new_tree_item.dspy @@ -0,0 +1,12 @@ +ns = params_kw.copy() +db = DBPools() +dbname = get_module_dbname('rag') +async with db.sqlorContext(dbname) as sor: + import uuid + dir_id = uuid.uuid4().hex[:16] + 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}$, ${parentid}$, NOW())", + {"id": dir_id, "kb_id": ns.get("kb_id",""), "name": ns.get("name",""), "parentid": ns.get("parentid","")}) + return {"status": "SUCCEEDED", "id": dir_id} +return {"error": "failed"} diff --git a/wwwroot/knowledge_bases_list/update_tree_item.dspy b/wwwroot/knowledge_bases_list/update_tree_item.dspy new file mode 100644 index 0000000..1f9b7b6 --- /dev/null +++ b/wwwroot/knowledge_bases_list/update_tree_item.dspy @@ -0,0 +1,8 @@ +ns = params_kw.copy() +db = DBPools() +dbname = get_module_dbname('rag') +async with db.sqlorContext(dbname) as sor: + await sor.sqlExe("UPDATE document_chunks SET content=${name}$ WHERE id=${id}$", + {"name": ns.get("name",""), "id": ns.get("id","")}) + return {"status": "SUCCEEDED"} +return {"error": "failed"}