feat(opp): 当前项目过滤——opp_reports_list只显示当前项目报告+平台级调研(未挂项目),无项目提示'选择或新建'带直达按钮;opp_approvals get注入会话级强制过滤;三菜单加require_project门禁
This commit is contained in:
parent
09d77f7483
commit
5c37341f4c
@ -464,11 +464,11 @@ def register_opp_ability():
|
||||
roles=OPP_ROLES,
|
||||
menus=[
|
||||
{"label": "📊 研发报告", "icon": "", "url": "/pipeline-opportunity/api/opp_reports_list.dspy",
|
||||
"type": "popup", "width": "88%", "height": "82%"},
|
||||
"type": "popup", "width": "88%", "height": "82%", "require_project": True},
|
||||
{"label": "✅ 研发审批", "icon": "", "url": "/pipeline-opportunity/opp_approvals/index.ui",
|
||||
"type": "popup", "width": "88%", "height": "82%"},
|
||||
"type": "popup", "width": "88%", "height": "82%", "require_project": True},
|
||||
{"label": "📋 数据参考", "icon": "", "url": "/pipeline-opportunity/api/opp_references_popup.dspy",
|
||||
"type": "popup", "width": "70%", "height": "76%"},
|
||||
"type": "popup", "width": "70%", "height": "76%", "require_project": True},
|
||||
],
|
||||
)
|
||||
register_ability(ability)
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
# 替换原 CRUD 裸表页:按项目 owner 过滤(list_visible_reports 单一事实源),
|
||||
# 整行点击 → opp_report_detail.dspy 弹出详情(四节+成果文件下载)。
|
||||
# 交互范式对齐 opp_references_items.dspy(整行下钻,fetch+widgetBuild)。
|
||||
# 2026-09-11 会话当前项目过滤:只显示当前项目的报告 + 平台级调研(未挂项目,
|
||||
# 不属于任何项目、不构成跨项目泄漏);没当前项目 → 提示选择或新建项目。
|
||||
|
||||
import json as _json
|
||||
|
||||
@ -11,11 +13,55 @@ if not uid:
|
||||
|
||||
dbname = get_module_dbname('pipeline-opportunity')
|
||||
|
||||
session_id = (params_kw or {}).get('session_id', '') or ''
|
||||
pipeline_id = (params_kw or {}).get('pipeline_id', '') or 'opportunity_general'
|
||||
|
||||
# 会话当前项目(统一解析:session→全局兜底+产线隔离+悬空自愈)
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
_cur_pid = await get_session_project_id(sor, uid, session_id, pipeline_id) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
|
||||
if not _cur_pid:
|
||||
_proj_base = entire_url("/pipeline_core/api/agent_project_popup.dspy")
|
||||
_proj_q = []
|
||||
if session_id:
|
||||
_proj_q.append("session_id=" + session_id)
|
||||
if pipeline_id:
|
||||
_proj_q.append("pipeline_id=" + pipeline_id)
|
||||
|
||||
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 {"widgettype": "VBox",
|
||||
"options": {"width": "100%", "gap": "12px", "padding": "24px"},
|
||||
"subwidgets": [
|
||||
{"widgettype": "Text",
|
||||
"options": {"text": "当前会话还没有项目,请先选择或新建项目",
|
||||
"cfontsize": 1, "color": "#64748b"}},
|
||||
{"widgettype": "HBox",
|
||||
"options": {"width": "100%", "gap": "10px"},
|
||||
"subwidgets": [_pbtn("✨ 新建项目", "primary", "new"),
|
||||
_pbtn("🔀 切换项目", "small", "switch")]}
|
||||
]}
|
||||
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
from pipeline_opportunity.opp_report_capability import list_visible_reports
|
||||
reports = await list_visible_reports(sor, uid)
|
||||
await sor.sqlExe("COMMIT", {})
|
||||
|
||||
# 当前项目过滤:本项目报告 + 平台级调研(project_id 空,未挂任何项目)
|
||||
reports = [r for r in reports
|
||||
if (not str(r.get("project_id") or "")) or str(r.get("project_id")) == _cur_pid]
|
||||
|
||||
detail_url = entire_url("/pipeline-opportunity/api/opp_report_detail.dspy")
|
||||
|
||||
STATUS_TXT = {
|
||||
|
||||
@ -1,6 +1,26 @@
|
||||
|
||||
ns = params_kw.copy()
|
||||
|
||||
# 会话当前项目强制过滤(2026-09-11 用户要求):会话级解析(session→全局兜底+产线隔离+悬空自愈),
|
||||
# 无项目报错提示;强制覆盖前端 project_id 传值(含搜索框),列表只显示当前项目数据。
|
||||
_uid = await get_user()
|
||||
if not _uid:
|
||||
_uid = 'user-01'
|
||||
_sid = (params_kw or {}).get('session_id', '') or ''
|
||||
_pl = (params_kw or {}).get('pipeline_id', '') or 'opportunity_general'
|
||||
_cur_pid = ''
|
||||
try:
|
||||
from pipeline_service.workspace import get_session_project_id
|
||||
async with DBPools().sqlorContext(get_module_dbname('pipeline-opportunity')) as _sor:
|
||||
_cur_pid = await get_session_project_id(_sor, _uid, _sid, _pl) or ''
|
||||
except Exception:
|
||||
_cur_pid = ''
|
||||
if not _cur_pid:
|
||||
return {"widgettype":"Error","options":{"title":"错误","timeout":3,"cwidth":22,"cheight":9,"message":"当前会话没有项目,请先选择或新建项目"}}
|
||||
ns['_cur_pid'] = _cur_pid
|
||||
ns['project_id'] = _cur_pid
|
||||
|
||||
|
||||
|
||||
debug(f'get_opp_approvals.dspy:{ns=}')
|
||||
if not ns.get('page'):
|
||||
@ -12,7 +32,7 @@ if not ns.get('sort'):
|
||||
|
||||
|
||||
|
||||
sql = '''select * from opp_approvals where 1=1 [[filterstr]]'''
|
||||
sql = '''select * from opp_approvals where project_id = ${_cur_pid}$ [[filterstr]]'''
|
||||
|
||||
filterjson = params_kw.get('data_filter')
|
||||
if filterjson and isinstance(filterjson, str):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user