95 lines
4.6 KiB
Plaintext
95 lines
4.6 KiB
Plaintext
# agent_menu_open.dspy - 通用功能弹窗:返回 PopupWindow,内嵌 urlwidget 加载目标 .ui
|
||
# 供 AgentIO 上方功能菜单按钮用(按钮 actiontype=urlwidget 打开本 dspy,通过参数控制弹窗大小)
|
||
# 参数:url(必填) title width height(百分比字符串,默认 85%/80%)
|
||
# 注意:PopupWindow 用 width/height 百分比(cwidth/cheight 是字符单位,对列表页太小)
|
||
#
|
||
# 「需要项目」校验在【点击时】做(本请求实时查会话项目),不在菜单渲染时固化——
|
||
# 渲染时固化是老 bug:页面加载时还没切项目 → 按钮写死报错脚本,之后切了项目仍报错。
|
||
|
||
import json
|
||
|
||
url = (params_kw or {}).get('url', '') or ''
|
||
title = (params_kw or {}).get('title', '') or '功能'
|
||
width = (params_kw or {}).get('width', '') or '85%'
|
||
height = (params_kw or {}).get('height', '') or '80%'
|
||
require_project = str((params_kw or {}).get('require_project', '') or '') in ('1', 'true', 'True')
|
||
session_id = (params_kw or {}).get('session_id', '') or ''
|
||
pipeline_id = (params_kw or {}).get('pipeline_id', '') or ''
|
||
|
||
if not url:
|
||
return json.dumps({
|
||
"widgettype": "Text",
|
||
"options": {"text": "缺少 url 参数", "cfontsize": 1, "color": "#64748b", "padding": "20px"}
|
||
}, ensure_ascii=False)
|
||
|
||
# 需要项目的入口:点击时实时解析会话项目(与菜单解析同一函数,语义不漂移)
|
||
if require_project:
|
||
_has_project = False
|
||
try:
|
||
uid = await get_user()
|
||
if not uid:
|
||
uid = 'user-01'
|
||
from pipeline_service.workspace import get_session_project_id
|
||
dbname = get_module_dbname('pipeline_core')
|
||
async with DBPools().sqlorContext(dbname) as sor:
|
||
_pid = await get_session_project_id(sor, uid, session_id, pipeline_id) or ''
|
||
_has_project = bool(_pid)
|
||
except Exception:
|
||
_has_project = True # 解析异常保守放行(不因校验故障误伤功能)
|
||
if not _has_project:
|
||
# 2026-09-11 用户要求:没当前项目 → 提示选择或新建项目(给直达按钮,不给死胡同)
|
||
_proj_q = []
|
||
if session_id:
|
||
_proj_q.append("session_id=" + session_id)
|
||
if pipeline_id:
|
||
_proj_q.append("pipeline_id=" + pipeline_id)
|
||
_proj_base = entire_url("/pipeline_core/api/agent_project_popup.dspy")
|
||
|
||
def _pbtn(label, css, op):
|
||
_js = ("var r=await fetch(" + json.dumps(_proj_base + "?op=" + op +
|
||
(("&" + "&".join(_proj_q)) if _proj_q else "")) + ");"
|
||
"var d=await r.json();if(d){bricks.widgetBuild(d,bricks.app);}")
|
||
return {"widgettype": "Button", "options": {"label": label, "css": css},
|
||
"binds": [{"wid": "self", "event": "click", "actiontype": "script",
|
||
"target": "self", "script": _js}]}
|
||
|
||
return json.dumps({
|
||
"widgettype": "PopupWindow",
|
||
"id": "agent_menu_no_project_pw",
|
||
"options": {"title": "提示", "cwidth": 38, "cheight": 10, "auto_open": True},
|
||
"subwidgets": [{
|
||
"widgettype": "VBox",
|
||
"options": {"width": "100%", "gap": "12px", "padding": "18px 22px"},
|
||
"subwidgets": [
|
||
{"widgettype": "Text",
|
||
"options": {"text": "当前会话还没有项目,请先选择或新建项目",
|
||
"cfontsize": 1, "color": "#64748b"}},
|
||
{"widgettype": "HBox",
|
||
"options": {"width": "100%", "gap": "10px"},
|
||
"subwidgets": [_pbtn("✨ 新建项目", "primary", "new"),
|
||
_pbtn("🔀 切换项目", "small", "switch")]}
|
||
]
|
||
}]
|
||
}, ensure_ascii=False)
|
||
|
||
# 把 session_id/pipeline_id 透传给内嵌页面(多 tab 会话级项目隔离):
|
||
# 内嵌 index.ui 的 data_params 会把请求参数转发给 get_*.dspy,注入的项目过滤
|
||
# 代码据此按会话解析当前项目;不透传会退回全局指针(串 tab)。
|
||
# ⚠️ 查询串拼在 entire_url() 之后(workspace_popup 同款写法),不把 query 喂给 entire_url。
|
||
_inner_url = entire_url(url)
|
||
_fwd = []
|
||
if session_id:
|
||
_fwd.append("session_id=" + session_id)
|
||
if pipeline_id:
|
||
_fwd.append("pipeline_id=" + pipeline_id)
|
||
if _fwd:
|
||
_inner_url += ("&" if "?" in _inner_url else "?") + "&".join(_fwd)
|
||
|
||
return json.dumps({
|
||
"widgettype": "PopupWindow",
|
||
"options": {"title": title, "width": width, "height": height, "auto_open": True},
|
||
"subwidgets": [
|
||
{"widgettype": "urlwidget", "options": {"url": _inner_url}}
|
||
]
|
||
}, ensure_ascii=False)
|