113 lines
6.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ns = params_kw.copy()
doc_id = ns.get('doc_id', '')
kb_id = ns.get('kb_id', '')
folder_id = ns.get('folder_id', '')
folder_label = ns.get('folder_label', '全部文件')
if not doc_id:
return json.dumps({"status": "error", "error": "doc_id required"}, ensure_ascii=False)
env = request._run_ns
userorgid = await env.get_userorgid()
async with get_sor_context(env, 'rag') as sor:
recs = await sor.sqlExe(
"SELECT file_path, file_size, kb_id FROM documents WHERE id=${id}$",
{"id": doc_id})
if not recs:
return json.dumps({"status": "error", "error": "file not found"}, ensure_ascii=False)
doc = recs[0]
file_path = doc.file_path
file_size = doc.file_size
# Delete document + chunks
await sor.sqlExe("DELETE FROM document_chunks WHERE doc_id=${doc_id}$", {"doc_id": doc_id})
await sor.sqlExe("DELETE FROM documents WHERE id=${id}$", {"id": doc_id})
# Update KB stats
await sor.sqlExe(
"UPDATE knowledge_bases SET doc_count=GREATEST(doc_count-1, 0), total_size=GREATEST(total_size-${size}$, 0) WHERE id=${kb_id}$",
{"size": file_size, "kb_id": kb_id})
# Delete physical file via env.realpath
if file_path and file_path.startswith("/idfile/"):
try:
real_path = env.realpath(file_path)
if os.path.exists(real_path):
os.remove(real_path)
except Exception:
pass
# Re-query and return refreshed file list
db = DBPools()
dbname = get_module_dbname('rag')
rows = []
async with db.sqlorContext(dbname) as sor:
if folder_id and folder_id != '__root__':
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=${folder_id}$ ORDER BY created_at DESC",
{"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",
{"kb_id": kb_id})
for r in recs:
rows.append({
"id": r.id, "file_name": r.file_name, "file_type": r.file_type or '',
"file_size": r.file_size or 0, "file_path": r.file_path or '',
"status": r.status or '', "chunk_count": r.chunk_count or 0,
"created_at": str(r.created_at)[:16] if r.created_at else ''
})
def fmt_size(sz):
if sz < 1024: return str(sz) + "B"
elif sz < 1024*1024: return str(round(sz/1024, 1)) + "KB"
else: return str(round(sz/(1024*1024), 1)) + "MB"
header = {
"widgettype": "HBox",
"options": {"width": "100%", "padding": "10px 0", "borderBottom": "1px solid #e0e0e0", "alignItems": "center"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": "📄 " + folder_label, "cfontsize": 14, "fontWeight": "bold", "color": "#333"}},
{"widgettype": "Text", "options": {"text": "" + str(len(rows)) + " 个文件)", "cfontsize": 12, "color": "#999", "marginLeft": "8px"}},
{"widgettype": "Text", "options": {"text": "", "css": "filler"}}
]
}
file_widgets = [header]
if not rows:
file_widgets.append({"widgettype": "Text", "options": {"text": "暂无文件", "cfontsize": 13, "color": "#aaa", "halign": "center", "marginTop": "40px"}})
else:
del_url_base = entire_url('./delete_file.dspy')
for f in rows:
sc = "#50b86c"; st = "已完成"
if f["status"] == "pending": sc = "#e6a23c"; st = "处理中"
elif f["status"] == "error": sc = "#f56c6c"; st = "失败"
file_url = entire_url(f["file_path"])
durl = del_url_base + "?kb_id=" + kb_id + "&doc_id=" + f["id"] + "&folder_id=" + folder_id + "&folder_label=" + folder_label
row = {
"widgettype": "HBox",
"options": {"width": "100%", "padding": "8px 12px", "borderBottom": "1px solid #f0f0f0", "alignItems": "center"},
"subwidgets": [
{"widgettype": "Text", "options": {"text": "📄 " + f["file_name"], "cfontsize": 13, "color": "#333", "textAlign": "left", "css": "filler"}},
{"widgettype": "Text", "options": {"text": f["file_type"].upper(), "cfontsize": 11, "color": "#999", "marginRight": "8px", "cwidth": 5, "textAlign": "center"}},
{"widgettype": "Text", "options": {"text": fmt_size(f["file_size"]), "cfontsize": 11, "color": "#999", "marginRight": "8px", "cwidth": 8, "textAlign": "right"}},
{"widgettype": "Text", "options": {"text": st, "cfontsize": 11, "color": sc, "marginRight": "8px", "cwidth": 6, "textAlign": "center"}},
{"widgettype": "Text", "options": {"text": f["created_at"], "cfontsize": 11, "color": "#999", "marginRight": "8px", "cwidth": 12}},
{"widgettype": "HBox", "options": {"spacing": "4px"}, "subwidgets": [
{"widgettype": "Text", "options": {"text": "👁", "cfontsize": 14, "css": "clickable", "color": "#4a90d9", "title": "查看"},
"binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self",
"script": "window.open(" + json.dumps(file_url) + ",'_blank')"}]},
{"widgettype": "Text", "options": {"text": "⬇", "cfontsize": 14, "css": "clickable", "color": "#50b86c", "title": "下载"},
"binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self",
"script": "var a=document.createElement('a');a.href=" + json.dumps(file_url) + ";a.download='';document.body.appendChild(a);a.click();document.body.removeChild(a)"}]},
{"widgettype": "Text", "options": {"text": "🗑", "cfontsize": 14, "css": "clickable", "color": "#f56c6c", "title": "删除"},
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "file_list_panel", "mode": "replace",
"options": {"url": durl}}]}
]}
]}
file_widgets.append(row)
result = {"widgettype": "VBox", "options": {"width": "100%", "spacing": "0"}, "subwidgets": file_widgets}
return result