feat: cockpit_context端点 + UI context_bar动态化

- 新增 cockpit_context.dspy API(读 pipeline_agent_settings,返回项目/迭代/workspace)
- index_cockpit.ui & index.ui context_bar:
  - 静态'当前项目/迭代:--' → Button(link样式)+datawidget自动加载
  - 点击项目/迭代弹出 PopupWindow 查看详情
This commit is contained in:
yumoqing 2026-08-05 18:10:56 +08:00
parent 746b372a6e
commit 8d158dcc86
3 changed files with 111 additions and 18 deletions

View File

@ -0,0 +1,35 @@
# cockpit_context.dspy — 返回当前上下文(项目/迭代),供前端 context_bar 显示
async with DBPools().sqlorContext(dbname) as sor:
recs = await sor.sqlExe(
"SELECT current_project_id, current_iteration_id FROM pipeline_agent_settings WHERE user_id=${uid}$",
{"uid": uid})
pid = ''
iid = ''
if recs and len(recs) > 0:
pid = getattr(recs[0], 'current_project_id', '') or ''
iid = getattr(recs[0], 'current_iteration_id', '') or ''
# 拿到项目名和迭代名
pname = ''
iname = ''
ws_dir = ''
if pid:
precs = await sor.sqlExe(
"SELECT name, workspace_dir FROM sd_projects WHERE id=${pid}$", {"pid": pid})
if precs and len(precs) > 0:
pname = getattr(precs[0], 'name', '') or ''
ws_dir = getattr(precs[0], 'workspace_dir', '') or ''
if iid:
irecs = await sor.sqlExe(
"SELECT iteration_name FROM sd_iterations WHERE id=${iid}$", {"iid": iid})
if irecs and len(irecs) > 0:
iname = getattr(irecs[0], 'iteration_name', '') or ''
return json.dumps({
"project_name": pname,
"iteration_name": iname,
"project_id": pid,
"iteration_id": iid,
"workspace_dir": ws_dir,
}, ensure_ascii=False)

View File

@ -89,19 +89,48 @@
},
"subwidgets": [
{
"widgettype": "Text",
"widgettype": "Button",
"id": "project_label",
"options": {
"text": "📁 当前项目:--",
"cfontsize": 0.85,
"color": "#1e40af"
}
"label": "\ud83d\udcc1 \u5f53\u524d\u9879\u76ee\uff1a\u52a0\u8f7d\u4e2d...",
"css": "link",
"action": "click"
},
"binds": [
{
"wid": "self",
"event": "click",
"actiontype": "script",
"target": "self",
"script": "var ctx=bricks.getWidgetById('context_data',bricks.app);var d=ctx?ctx.getValue():{};var pid=d.project_id||'';if(!pid){bricks.showError('\u8bf7\u5148\u9009\u62e9\u9879\u76ee');return;}var pw=new bricks.PopupWindow({title:'\u9879\u76ee\u8be6\u60c5',cwidth:42,cheight:30,auto_open:true});bricks.widgetBuild({widgettype:'urlwidget',options:{url:bricks.entire_url('/pipeline_core/projects/index.ui?project_id='+pid),method:'GET'}},pw.content_w).then(function(w){if(w)pw.content_w.add_widget(w);});"
}
]
},
{
"widgettype": "Text",
"widgettype": "Button",
"id": "iteration_label",
"options": {
"text": "🔄 当前迭代:--",
"cfontsize": 0.85,
"color": "#1e40af"
"label": "\ud83d\udd04 \u5f53\u524d\u8fed\u4ee3\uff1a\u52a0\u8f7d\u4e2d...",
"css": "link",
"action": "click"
},
"binds": [
{
"wid": "self",
"event": "click",
"actiontype": "script",
"target": "self",
"script": "var ctx=bricks.getWidgetById('context_data',bricks.app);var d=ctx?ctx.getValue():{};var iid=d.iteration_id||'';var pid=d.project_id||'';if(!iid){bricks.showError('\u8bf7\u5148\u9009\u62e9\u8fed\u4ee3');return;}var pw=new bricks.PopupWindow({title:'\u8fed\u4ee3\u8be6\u60c5',cwidth:42,cheight:30,auto_open:true});bricks.widgetBuild({widgettype:'urlwidget',options:{url:bricks.entire_url('/pipeline_core/iterations/index.ui?project_id='+pid+'&iteration_id='+iid),method:'GET'}},pw.content_w).then(function(w){if(w)pw.content_w.add_widget(w);});"
}
]
},
{
"widgettype": "datawidget",
"id": "context_data",
"options": {
"dataurl": "/pipeline-sdlc/api/cockpit_context.dspy",
"method": "GET",
"datascript": "(function(d){var d=d||{};var pl=bricks.getWidgetById('project_label',bricks.app);var il=bricks.getWidgetById('iteration_label',bricks.app);if(pl){pl.setText(d.project_name?'\\ud83d\\udcc1 \\u5f53\\u524d\\u9879\\u76ee\\uff1a'+d.project_name:'\\ud83d\\udcc1 \\u5f53\\u524d\\u9879\\u76ee\\uff1a--');}if(il){il.setText('\\ud83d\\udd04 \\u5f53\\u524d\\u8fed\\u4ee3\\uff1a'+(d.iteration_name||'--'));}return d;})"
}
}
]

View File

@ -108,19 +108,48 @@
},
"subwidgets": [
{
"widgettype": "Text",
"widgettype": "Button",
"id": "project_label",
"options": {
"text": "📁 当前项目:--",
"cfontsize": 0.85,
"color": "#1e40af"
}
"label": "\ud83d\udcc1 \u5f53\u524d\u9879\u76ee\uff1a\u52a0\u8f7d\u4e2d...",
"css": "link",
"action": "click"
},
"binds": [
{
"wid": "self",
"event": "click",
"actiontype": "script",
"target": "self",
"script": "var ctx=bricks.getWidgetById('context_data',bricks.app);var d=ctx?ctx.getValue():{};var pid=d.project_id||'';if(!pid){bricks.showError('\u8bf7\u5148\u9009\u62e9\u9879\u76ee');return;}var pw=new bricks.PopupWindow({title:'\u9879\u76ee\u8be6\u60c5',cwidth:42,cheight:30,auto_open:true});bricks.widgetBuild({widgettype:'urlwidget',options:{url:bricks.entire_url('/pipeline_core/projects/index.ui?project_id='+pid),method:'GET'}},pw.content_w).then(function(w){if(w)pw.content_w.add_widget(w);});"
}
]
},
{
"widgettype": "Text",
"widgettype": "Button",
"id": "iteration_label",
"options": {
"text": "🔄 当前迭代:--",
"cfontsize": 0.85,
"color": "#1e40af"
"label": "\ud83d\udd04 \u5f53\u524d\u8fed\u4ee3\uff1a\u52a0\u8f7d\u4e2d...",
"css": "link",
"action": "click"
},
"binds": [
{
"wid": "self",
"event": "click",
"actiontype": "script",
"target": "self",
"script": "var ctx=bricks.getWidgetById('context_data',bricks.app);var d=ctx?ctx.getValue():{};var iid=d.iteration_id||'';var pid=d.project_id||'';if(!iid){bricks.showError('\u8bf7\u5148\u9009\u62e9\u8fed\u4ee3');return;}var pw=new bricks.PopupWindow({title:'\u8fed\u4ee3\u8be6\u60c5',cwidth:42,cheight:30,auto_open:true});bricks.widgetBuild({widgettype:'urlwidget',options:{url:bricks.entire_url('/pipeline_core/iterations/index.ui?project_id='+pid+'&iteration_id='+iid),method:'GET'}},pw.content_w).then(function(w){if(w)pw.content_w.add_widget(w);});"
}
]
},
{
"widgettype": "datawidget",
"id": "context_data",
"options": {
"dataurl": "/pipeline-sdlc/api/cockpit_context.dspy",
"method": "GET",
"datascript": "(function(d){var d=d||{};var pl=bricks.getWidgetById('project_label',bricks.app);var il=bricks.getWidgetById('iteration_label',bricks.app);var pn=d.project_name||'';if(pl){pl.setText(pn?'\\ud83d\\udcc1 \\u5f53\\u524d\\u9879\\u76ee\\uff1a'+pn:'\\ud83d\\udcc1 \\u5f53\\u524d\\u9879\\u76ee\\uff1a--');}if(il){il.setText(d.iteration_name?(d.iteration_name.length>15?d.iteration_name.slice(0,15)+'...':d.iteration_name):'\\ud83d\\udd04 \\u5f53\\u524d\\u8fed\\u4ee3\\uff1a--');il.setText('\\ud83d\\udd04 \\u5f53\\u524d\\u8fed\\u4ee3\\uff1a'+(d.iteration_name||'--'));}return d;})"
}
}
]