# 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) or '' if _pid: # 产线隔离:跨产线项目不算本产线的项目 precs = await sor.sqlExe( "SELECT pipeline_id FROM sd_projects WHERE id=${p}$", {"p": _pid}) proj_pl = getattr(precs[0], 'pipeline_id', '') or '' if precs else '' _has_project = (not pipeline_id) or (proj_pl == pipeline_id) except Exception: _has_project = True # 解析异常保守放行(不因校验故障误伤功能) if not _has_project: return json.dumps({ "widgettype": "PopupWindow", "options": {"title": "提示", "cwidth": 30, "cheight": 8, "auto_open": True}, "subwidgets": [{ "widgettype": "Text", "options": {"text": "请先在会话中切换项目", "cfontsize": 1, "color": "#64748b", "padding": "20px"} }] }, ensure_ascii=False) return json.dumps({ "widgettype": "PopupWindow", "options": {"title": title, "width": width, "height": height, "auto_open": True}, "subwidgets": [ {"widgettype": "urlwidget", "options": {"url": entire_url(url)}} ] }, ensure_ascii=False)