diff --git a/wwwroot/knowledge_bases_list/save_tags.dspy b/wwwroot/knowledge_bases_list/save_tags.dspy new file mode 100644 index 0000000..0cc1fa9 --- /dev/null +++ b/wwwroot/knowledge_bases_list/save_tags.dspy @@ -0,0 +1,38 @@ +ns = params_kw.copy() +kb_id = ns.get('kb_id', '') +doc_id = ns.get('media_id', '') +tag_ids_str = ns.get('tag_ids', '') + +if not kb_id or not doc_id: + result = {"widgettype": "Text", "options": {"text": "\u274c \u53c2\u6570\u7f3a\u5931", + "cfontsize": 14, "color": "#e74c3c", "halign": "center", "padding": "20px"}} +else: + env = request._run_ns + try: + wanted_ids = [t.strip() for t in tag_ids_str.split(",") if t.strip()] + added = 0; removed = 0 + async with get_sor_context(env, 'rag') as sor: + recs = await sor.sqlExe( + "SELECT id, tag_id FROM media_tags WHERE media_type='document' AND media_id=${mid}$", + {"mid": doc_id}) + current = {r.tag_id: r.id for r in recs} + for tid, mt_id in list(current.items()): + if tid not in wanted_ids: + await sor.sqlExe("DELETE FROM media_tags WHERE id=${id}$", {"id": mt_id}) + removed += 1 + for tid in wanted_ids: + if tid not in current: + mt_id = uuid.uuid4().hex[:16] + await sor.sqlExe( + "INSERT INTO media_tags (id, kb_id, media_type, media_id, tag_id, created_at) " + "VALUES (${id}$, ${kb_id}$, 'document', ${mid}$, ${tid}$, NOW())", + {"id": mt_id, "kb_id": kb_id, "mid": doc_id, "tid": tid}) + added += 1 + msg = "\u2705 \u5df2\u4fdd\u5b58\uff1a\u65b0\u589e " + str(added) + " \u4e2a\uff0c\u79fb\u9664 " + str(removed) + " \u4e2a" + result = {"widgettype": "Text", "options": {"text": msg, + "cfontsize": 14, "color": "#27ae60", "halign": "center", "padding": "20px"}} + except Exception as e: + result = {"widgettype": "Text", "options": {"text": "\u274c \u4fdd\u5b58\u5931\u8d25\uff1a" + str(e)[:100], + "cfontsize": 14, "color": "#e74c3c", "halign": "center", "padding": "20px"}} + +return result diff --git a/wwwroot/knowledge_bases_list/tag_form.dspy b/wwwroot/knowledge_bases_list/tag_form.dspy index bb24aa4..b95f1ba 100644 --- a/wwwroot/knowledge_bases_list/tag_form.dspy +++ b/wwwroot/knowledge_bases_list/tag_form.dspy @@ -127,10 +127,10 @@ add_tag_js = ("var inp=document.querySelector('#new_tag_input');" submit_js = ("var rows=document.querySelectorAll('#tag_list_panel [data-sel]');" "var ids=[];rows.forEach(function(r){if(r.getAttribute('data-sel')==='1'){ids.push(r.id.replace('tagrow_',''))}});" "if(ids.length===0){alert('请至少勾选一个标签');return};" - "fetch('/api/tag/sync?kb_id=" + kb_id + "&media_type=document&media_id=" + doc_id + "&tag_ids='+encodeURIComponent(ids.join(',')))" - ".then(function(r){return r.json()}).then(function(d){" - "if(d&&d.status==='SUCCEEDED'){" + close_popup_js + "window.location.reload();" + "}" - "else{alert('保存失败:'+(d&&d.error||'未知错误'));}" + "var u='/rag/knowledge_bases_list/save_tags.dspy?kb_id=" + kb_id + "&media_id=" + doc_id + "&tag_ids='+encodeURIComponent(ids.join(','));" + "fetch(u).then(function(r){return r.json()}).then(function(d){" + "var pw=null;var w=this;while(w){if(w instanceof bricks.PopupWindow||w instanceof bricks.Popup){pw=w;break};w=w.parent};" + "if(pw){pw.clear_widgets();bricks.widgetBuild(d,pw).then(function(nw){if(nw)pw.add_widget(nw)})}" "}).catch(function(){alert('网络错误')});") # 组合弹窗内容