fix: use simple VBox bar instead of ProgressBar
This commit is contained in:
parent
b6b20ab19b
commit
fecdc753a2
@ -22,27 +22,15 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"widgettype": "VBox",
|
"widgettype": "VBox",
|
||||||
"options": {
|
"options": {"width": "100%", "bgcolor": "#f8f9fa", "padding": "16px", "css": "card", "spacing": "4px"},
|
||||||
"width": "100%",
|
|
||||||
"bgcolor": "#f8f9fa",
|
|
||||||
"padding": "16px",
|
|
||||||
"css": "card",
|
|
||||||
"spacing": "8px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
"subwidgets": [
|
||||||
{"widgettype": "Text", "options": {"text": "💾 存储容量", "cfontsize": 14, "fontWeight": "bold", "color": "#333"}},
|
{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between"}, "subwidgets": [
|
||||||
{
|
{"widgettype": "Text", "options": {"text": "💾 存储容量", "cfontsize": 14, "fontWeight": "bold", "color": "#333"}},
|
||||||
"widgettype": "ProgressBar",
|
{"widgettype": "Text", "options": {"text": "已用 0MB / 总计 100MB", "cfontsize": 12, "color": "#888"}}
|
||||||
"options": {
|
]},
|
||||||
"value": 15,
|
{"widgettype": "VBox", "options": {"width": "100%", "cheight": 0.5, "bgcolor": "#e0e0e0", "css": ""}, "subwidgets": [
|
||||||
"total": 100,
|
{"widgettype": "VBox", "options": {"cwidth": 0, "cheight": 0.5, "bgcolor": "#4a90d9", "css": ""}}
|
||||||
"width": "100%",
|
]}
|
||||||
"cheight": 1.2,
|
|
||||||
"bgcolor": "#e0e0e0",
|
|
||||||
"color": "#4a90d9"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{"widgettype": "Text", "options": {"text": "已用 15MB / 总计 100MB · 15%", "cfontsize": 12, "color": "#888"}}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -125,8 +125,8 @@ async with db.sqlorContext(dbname) as sor:
|
|||||||
"options": {"url": base_url + '?kb_id=' + kb_id + '&media_type=' + mt}}]}
|
"options": {"url": base_url + '?kb_id=' + kb_id + '&media_type=' + mt}}]}
|
||||||
)
|
)
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"widgettype": "VBox",
|
"widgettype": "VBox",
|
||||||
"options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"},
|
"options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"},
|
||||||
"subwidgets": [
|
"subwidgets": [
|
||||||
{"widgettype": "Text", "options": {"text": "🏷️ 标签分配", "cfontsize": 20, "fontWeight": "bold", "color": "#333"}},
|
{"widgettype": "Text", "options": {"text": "🏷️ 标签分配", "cfontsize": 20, "fontWeight": "bold", "color": "#333"}},
|
||||||
@ -154,4 +154,4 @@ result = {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
|
|||||||
@ -5,22 +5,20 @@ match_mode = ns.get('match_mode', 'any')
|
|||||||
query = ns.get('query', '')
|
query = ns.get('query', '')
|
||||||
tag_ids = [t for t in tag_ids_str.split(',') if t] if tag_ids_str else []
|
tag_ids = [t for t in tag_ids_str.split(',') if t] if tag_ids_str else []
|
||||||
|
|
||||||
|
import json
|
||||||
db = DBPools()
|
db = DBPools()
|
||||||
dbname = get_module_dbname('rag')
|
dbname = get_module_dbname('rag')
|
||||||
base_url = entire_url('/tag_search/index.dspy')
|
base_url = entire_url('/tag_search/index.dspy')
|
||||||
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
async with db.sqlorContext(dbname) as sor:
|
||||||
# Get knowledge bases
|
|
||||||
kbs = await sor.R('knowledge_bases', {})
|
kbs = await sor.R('knowledge_bases', {})
|
||||||
kb_options = [{"value": k.id, "text": k.name} for k in kbs]
|
kb_options = [{"value": k.id, "text": k.name} for k in kbs]
|
||||||
|
|
||||||
# Get all tags for selected kb
|
|
||||||
tags = []
|
tags = []
|
||||||
if kb_id:
|
if kb_id:
|
||||||
tag_recs = await sor.R('tags', {'kb_id': kb_id})
|
tag_recs = await sor.R('tags', {'kb_id': kb_id})
|
||||||
tags = [{"id": t.id, "name": t.name, "color": t.color} for t in tag_recs]
|
tags = [{"id": t.id, "name": t.name, "color": t.color} for t in tag_recs]
|
||||||
|
|
||||||
# --- Build tag pills ---
|
|
||||||
tag_pills = []
|
tag_pills = []
|
||||||
for t in tags:
|
for t in tags:
|
||||||
is_selected = t['id'] in tag_ids
|
is_selected = t['id'] in tag_ids
|
||||||
@ -35,26 +33,20 @@ async with db.sqlorContext(dbname) as sor:
|
|||||||
"widgettype": "Button",
|
"widgettype": "Button",
|
||||||
"options": {
|
"options": {
|
||||||
"label": ('✓ ' if is_selected else '') + t['name'],
|
"label": ('✓ ' if is_selected else '') + t['name'],
|
||||||
"bgcolor": pill_bg,
|
"bgcolor": pill_bg, "color": pill_color,
|
||||||
"color": pill_color,
|
"cfontsize": 12, "padding": "4px 12px",
|
||||||
"cfontsize": 12,
|
"marginRight": "6px", "marginBottom": "6px"
|
||||||
"padding": "4px 12px",
|
|
||||||
"marginRight": "6px",
|
|
||||||
"marginBottom": "6px"
|
|
||||||
},
|
},
|
||||||
"binds": [{
|
"binds": [{
|
||||||
"wid": "self", "event": "click",
|
"wid": "self", "event": "click",
|
||||||
"actiontype": "urlwidget",
|
"actiontype": "urlwidget",
|
||||||
"target": "app.rag_main_content",
|
"target": "app.rag_main_content", "mode": "replace",
|
||||||
"mode": "replace",
|
|
||||||
"options": {"url": url}
|
"options": {"url": url}
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
|
|
||||||
# --- Build results ---
|
|
||||||
results_widgets = []
|
results_widgets = []
|
||||||
if tag_ids and not query:
|
if tag_ids:
|
||||||
# Tag-only search via our API
|
|
||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
try:
|
try:
|
||||||
api_url = 'http://localhost:9181/api/tag/search?kb_id=' + kb_id + '&tag_ids=' + tag_ids_str + '&match_mode=' + match_mode
|
api_url = 'http://localhost:9181/api/tag/search?kb_id=' + kb_id + '&tag_ids=' + tag_ids_str + '&match_mode=' + match_mode
|
||||||
@ -64,76 +56,47 @@ async with db.sqlorContext(dbname) as sor:
|
|||||||
if isinstance(res, list):
|
if isinstance(res, list):
|
||||||
for r in res:
|
for r in res:
|
||||||
icon = '📄' if r['type'] == 'document' else ('👤' if r['type'] == 'face' else '🎤')
|
icon = '📄' if r['type'] == 'document' else ('👤' if r['type'] == 'face' else '🎤')
|
||||||
results_widgets.append({
|
entry = {
|
||||||
"widgettype": "HBox",
|
"widgettype": "HBox",
|
||||||
"options": {"padding": "8px 12px", "bgcolor": "#f9fafb", "marginBottom": "4px", "alignItems": "center"},
|
"options": {"padding": "8px 12px", "bgcolor": "#f9fafb", "marginBottom": "4px", "alignItems": "center"},
|
||||||
"subwidgets": [
|
"subwidgets": [
|
||||||
{"widgettype": "Text", "options": {"text": icon + ' ' + (r.get('name') or r.get('id','')), "cfontsize": 13, "color": "#333"}},
|
{"widgettype": "Text", "options": {"text": icon + ' ' + (r.get('name') or r.get('id','')), "cfontsize": 13, "color": "#333"}},
|
||||||
{"widgettype": "Text", "options": {"text": r['type'] + ' · ' + (r.get('file_type','')), "cfontsize": 11, "color": "#888", "css": "filler"}}
|
{"widgettype": "Text", "options": {"text": r['type'] + ' · ' + (r.get('file_type','')), "cfontsize": 11, "color": "#888", "css": "filler"}}
|
||||||
]
|
]
|
||||||
})
|
}
|
||||||
# Show tags for this item
|
results_widgets.append(entry)
|
||||||
try:
|
|
||||||
tag_url = 'http://localhost:9181/api/tag/media_tags?media_type=' + ('document' if r['type'] in ('document','text','image','audio','video') else r['type']) + '&media_id=' + r['id']
|
|
||||||
tag_data = json.loads(urlopen(Request(tag_url), timeout=3).read())
|
|
||||||
item_tags = tag_data.get('tags', [])
|
|
||||||
for it in item_tags:
|
|
||||||
results_widgets[-1]['subwidgets'].append({
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {"text": it['name'], "cfontsize": 10, "color": "#fff", "bgcolor": it['color'], "padding": "1px 6px", "marginLeft": "4px"}
|
|
||||||
})
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
for key, items in res.items():
|
|
||||||
if isinstance(items, list):
|
|
||||||
for r in items:
|
|
||||||
results_widgets.append({
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {"text": str(r.get('name') or r.get('id','')), "cfontsize": 13, "color": "#333", "padding": "4px 0"}
|
|
||||||
})
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
results_widgets.append({"widgettype": "Text", "options": {"text": '搜索出错: ' + str(e), "color": "#e53e3e"}})
|
results_widgets.append({"widgettype": "Text", "options": {"text": '搜索出错: ' + str(e), "color": "#e53e3e"}})
|
||||||
|
|
||||||
if not results_widgets and (tag_ids or query):
|
if not results_widgets and tag_ids:
|
||||||
results_widgets.append({"widgettype": "Text", "options": {"text": '未找到匹配的媒体文件', "color": "#888", "cfontsize": 14, "halign": "center", "padding": "40px 0"}})
|
results_widgets.append({"widgettype": "Text", "options": {"text": '未找到匹配的媒体文件', "color": "#888", "cfontsize": 14, "halign": "center", "padding": "40px 0"}})
|
||||||
|
|
||||||
# --- Match mode toggle ---
|
|
||||||
any_url = base_url + '?kb_id=' + kb_id + '&tag_ids=' + tag_ids_str + '&match_mode=any&query=' + query
|
any_url = base_url + '?kb_id=' + kb_id + '&tag_ids=' + tag_ids_str + '&match_mode=any&query=' + query
|
||||||
all_url = base_url + '?kb_id=' + kb_id + '&tag_ids=' + tag_ids_str + '&match_mode=all&query=' + query
|
all_url = base_url + '?kb_id=' + kb_id + '&tag_ids=' + tag_ids_str + '&match_mode=all&query=' + query
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"widgettype": "VBox",
|
"widgettype": "VBox",
|
||||||
"options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"},
|
"options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"},
|
||||||
"subwidgets": [
|
"subwidgets": [
|
||||||
{"widgettype": "Text", "options": {"text": "🔍 标签检索", "cfontsize": 20, "fontWeight": "bold", "color": "#333"}},
|
{"widgettype": "Text", "options": {"text": "🔍 标签检索", "cfontsize": 20, "fontWeight": "bold", "color": "#333"}},
|
||||||
{"widgettype": "Text", "options": {"text": "组合标签筛选 + 语义搜索", "cfontsize": 13, "color": "#888"}},
|
{"widgettype": "Text", "options": {"text": "组合标签筛选 + 语义搜索", "cfontsize": 13, "color": "#888"}},
|
||||||
# KB selector
|
{"widgettype": "Text", "options": {"text": "知识库:", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
||||||
{"widgettype": "Text", "options": {"text": "知识库:", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
{"widgettype": "HBox", "options": {"spacing": "6px", "wrap": True}, "subwidgets": [
|
||||||
{"widgettype": "HBox", "options": {"spacing": "6px", "wrap": True}, "subwidgets": [
|
{"widgettype": "Button", "options": {"label": k['text'], "bgcolor": "#3b82f6" if k['value']==kb_id else "#e5e7eb", "color": "#fff" if k['value']==kb_id else "#666", "cfontsize": 12, "padding": "6px 14px", "marginRight": "4px", "marginBottom": "4px"},
|
||||||
{"widgettype": "Button", "options": {"label": k['text'], "bgcolor": "#3b82f6" if k['value']==kb_id else "#e5e7eb", "color": "#fff" if k['value']==kb_id else "#666", "cfontsize": 12, "padding": "6px 14px", "marginRight": "4px", "marginBottom": "4px"},
|
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace",
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace",
|
"options": {"url": base_url + '?kb_id=' + k['value'] + '&match_mode=' + match_mode}}]}
|
||||||
"options": {"url": base_url + '?kb_id=' + k['value'] + '&match_mode=' + match_mode}}]}
|
for k in kb_options]},
|
||||||
for k in kb_options]},
|
{"widgettype": "Text", "options": {"text": '标签 (' + str(len(tag_ids)) + ' 已选):', "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
||||||
# Tags
|
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": tag_pills},
|
||||||
{"widgettype": "Text", "options": {"text": '标签 (' + str(len(tag_ids)) + ' 已选):', "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
{"widgettype": "HBox", "options": {"spacing": "8px", "alignItems": "center", "marginTop": "4px"}, "subwidgets": [
|
||||||
{"widgettype": "HBox", "options": {"spacing": "4px", "wrap": True}, "subwidgets": tag_pills},
|
{"widgettype": "Text", "options": {"text": "匹配:", "cfontsize": 13, "color": "#555"}},
|
||||||
# Match mode
|
{"widgettype": "Button", "options": {"label": "任一 (OR)", "bgcolor": "#3b82f6" if match_mode=='any' else "#e5e7eb", "color": "#fff" if match_mode=='any' else "#666", "cfontsize": 12, "padding": "4px 12px"},
|
||||||
{"widgettype": "HBox", "options": {"spacing": "8px", "alignItems": "center", "marginTop": "4px"}, "subwidgets": [
|
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": any_url}}]},
|
||||||
{"widgettype": "Text", "options": {"text": "匹配:", "cfontsize": 13, "color": "#555"}},
|
{"widgettype": "Button", "options": {"label": "全部 (AND)", "bgcolor": "#3b82f6" if match_mode=='all' else "#e5e7eb", "color": "#fff" if match_mode=='all' else "#666", "cfontsize": 12, "padding": "4px 12px"},
|
||||||
{"widgettype": "Button", "options": {"label": "任一 (OR)", "bgcolor": "#3b82f6" if match_mode=='any' else "#e5e7eb", "color": "#fff" if match_mode=='any' else "#666", "cfontsize": 12, "padding": "4px 12px"},
|
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": all_url}}]}
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": any_url}}]},
|
]},
|
||||||
{"widgettype": "Button", "options": {"label": "全部 (AND)", "bgcolor": "#3b82f6" if match_mode=='all' else "#e5e7eb", "color": "#fff" if match_mode=='all' else "#666", "cfontsize": 12, "padding": "4px 12px"},
|
{"widgettype": "Text", "options": {"text": "结果 (" + str(len(results_widgets)) + "):", "cfontsize": 14, "fontWeight": "bold", "color": "#333", "marginTop": "16px"}},
|
||||||
"binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "app.rag_main_content", "mode": "replace", "options": {"url": all_url}}]}
|
{"widgettype": "VBox", "options": {"spacing": "4px"}, "subwidgets": results_widgets}
|
||||||
]},
|
]
|
||||||
# Query input + search button (using form or simple text)
|
}
|
||||||
{"widgettype": "Text", "options": {"text": "语义查询 (可选):", "cfontsize": 13, "color": "#555", "marginTop": "8px"}},
|
result
|
||||||
{"widgettype": "HBox", "options": {"spacing": "8px", "alignItems": "center"}, "subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": query if query else '(输入查询关键词)', "cfontsize": 13, "color": "#333" if query else "#aaa", "bgcolor": "#f9fafb", "padding": "8px 12px", "css": "filler", "border": "1px solid #e0e0e0"}}
|
|
||||||
]},
|
|
||||||
# Results
|
|
||||||
{"widgettype": "Text", "options": {"text": '结果 (' + str(len(results_widgets)) + '):', "cfontsize": 14, "fontWeight": "bold", "color": "#333", "marginTop": "16px"}},
|
|
||||||
{"widgettype": "VBox", "options": {"spacing": "4px"}, "subwidgets": results_widgets}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
result
|
|
||||||
|
|||||||
32
wwwroot/tags_list/index.ui
Normal file
32
wwwroot/tags_list/index.ui
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {"cheight": 40, "width": "100%", "padding": "16px", "spacing": "12px"},
|
||||||
|
"subwidgets": [
|
||||||
|
{"widgettype": "Text", "options": {"text": "🏷️ 标签管理", "cfontsize": 22, "fontWeight": "bold", "color": "#333"}},
|
||||||
|
{"widgettype": "Text", "options": {"text": "创建和管理知识库标签", "cfontsize": 14, "color": "#888"}},
|
||||||
|
{
|
||||||
|
"widgettype": "Tabular",
|
||||||
|
"options": {
|
||||||
|
"dataurl": "{{entire_url('/tags_list/data.dspy')}}",
|
||||||
|
"title": "标签列表",
|
||||||
|
"height": "70vh",
|
||||||
|
"browserfields": [
|
||||||
|
{"field": "name", "title": "标签名", "width": "25%"},
|
||||||
|
{"field": "color", "title": "颜色", "width": "15%"},
|
||||||
|
{"field": "kb_id", "title": "知识库", "width": "30%"},
|
||||||
|
{"field": "created_at", "title": "创建时间", "width": "30%"}
|
||||||
|
],
|
||||||
|
"editable": {
|
||||||
|
"fields": [
|
||||||
|
{"field": "name", "title": "标签名", "uitype": "str", "label": "标签名", "required": true},
|
||||||
|
{"field": "kb_id", "title": "知识库ID", "uitype": "str", "label": "知识库ID", "required": true},
|
||||||
|
{"field": "color", "title": "颜色", "uitype": "str", "label": "颜色(#hex)", "default": "#3b82f6"}
|
||||||
|
],
|
||||||
|
"add_url": "{{entire_url('/tags_list/add.dspy')}}",
|
||||||
|
"update_url": "{{entire_url('/tags_list/update.dspy')}}",
|
||||||
|
"delete_url": "{{entire_url('/tags_list/delete.dspy')}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user