167 lines
7.7 KiB
Plaintext
167 lines
7.7 KiB
Plaintext
# workspace_popup.dspy - 返回 PopupWindow,内含 ResourceBrowser(含打开/删除 tools)
|
||
|
||
import json as _json
|
||
|
||
uid = await get_user()
|
||
if not uid:
|
||
uid = 'user-01'
|
||
|
||
dbname = get_module_dbname('pipeline-sdlc')
|
||
import os
|
||
|
||
session_id = (params_kw or {}).get('session_id', '') or ''
|
||
pipeline_id = (params_kw or {}).get('pipeline_id', '') or ''
|
||
# 查询串:session_id + pipeline_id 一并透传给树/文件/查看/编辑/删除子端点
|
||
# (子端点各自用 get_project_dir_pl 做产线隔离,跨产线项目一律视为无项目)
|
||
_qs = []
|
||
if session_id:
|
||
_qs.append("session_id=" + session_id)
|
||
if pipeline_id:
|
||
_qs.append("pipeline_id=" + pipeline_id)
|
||
_sid_q = ("?" + "&".join(_qs)) if _qs else ""
|
||
_sid_js = _json.dumps(("&" + "&".join(_qs)) if _qs else "")
|
||
|
||
async with DBPools().sqlorContext(dbname) as sor:
|
||
# 产线隔离:传了 pipeline_id 时,会话项目跨产线则视为无项目
|
||
# (商机/投标产线入口不显示开发产线项目的空间)
|
||
project_dir, _ = await get_project_dir_pl(sor, uid, session_id, pipeline_id)
|
||
# 通用会话(pipeline_id=_generic):锁用户专属目录 _general/{uid},
|
||
# 不进入任何项目的工作空间(2026-09-08 用户要求)
|
||
if pipeline_id == '_generic':
|
||
_gd = generic_workspace_dir(uid)
|
||
os.makedirs(_gd, exist_ok=True)
|
||
project_dir = _gd
|
||
space_dir = _gd
|
||
|
||
pname = os.path.basename(project_dir) if project_dir else ''
|
||
|
||
if not project_dir:
|
||
# 2026-09-11 用户要求:没当前项目 → 提示选择或新建项目(给直达按钮,不给死胡同)
|
||
_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}]}
|
||
|
||
resp = {
|
||
"widgettype": "PopupWindow",
|
||
"id": "ws_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": {"otext": "当前会话还没有项目,请先选择或新建项目", "text": "当前会话还没有项目,请先选择或新建项目", "i18n": True,
|
||
"cfontsize": 1, "color": "#64748b"}},
|
||
{"widgettype": "HBox",
|
||
"options": {"width": "100%", "gap": "10px"},
|
||
"subwidgets": [_pbtn("✨ 新建项目", "primary", "new"),
|
||
_pbtn("🔀 切换项目", "small", "switch")]}
|
||
]
|
||
}]
|
||
}
|
||
else:
|
||
view_url = entire_url("/pipeline-sdlc/api/workspace_view.dspy")
|
||
edit_url = entire_url("/pipeline-sdlc/api/workspace_open.dspy")
|
||
delete_url = entire_url("/pipeline-sdlc/api/workspace_delete.dspy") + _sid_q
|
||
|
||
# 查看:txt/md 用 MdWidget 渲染,其他下载查看
|
||
view_script = (
|
||
"if(!bricks.app._ws_sel)return;"
|
||
"var r=await fetch(" + _json.dumps(view_url) + "+'?id='+encodeURIComponent(bricks.app._ws_sel.id)+" + _sid_js + ");"
|
||
"var d=await r.json();"
|
||
"bricks.widgetBuild(d,bricks.app);"
|
||
)
|
||
|
||
# 编辑:文本 vi 编辑、媒体播放、图片预览、其他下载
|
||
edit_script = (
|
||
"if(!bricks.app._ws_sel)return;"
|
||
"var r=await fetch(" + _json.dumps(edit_url) + "+'?id='+encodeURIComponent(bricks.app._ws_sel.id)+" + _sid_js + ");"
|
||
"var d=await r.json();"
|
||
"bricks.widgetBuild(d,bricks.app);"
|
||
)
|
||
|
||
# 删除:删除选中文件并刷新
|
||
delete_script = (
|
||
"if(!bricks.app._ws_sel)return;"
|
||
"var body=new URLSearchParams();"
|
||
"body.append('id',bricks.app._ws_sel.id);"
|
||
"var resp=await fetch(" + _json.dumps(delete_url) + ",{method:'POST',body:body});"
|
||
"var rj=await resp.json();"
|
||
"if(rj.status=='ok'){"
|
||
"bricks.app._ws_sel=null;bricks.app._ws_sel_el=null;"
|
||
"var rb=bricks.getWidgetById('ws_rb',bricks.app);"
|
||
"if(rb){var cid=rb.current_id;rb.current_id=undefined;await rb.render_browser(cid);}"
|
||
"}else{var m=new bricks.Message({title:'删除失败',message:rj.message||'未知错误'});m.open();}"
|
||
)
|
||
|
||
resp = {
|
||
"widgettype": "PopupWindow",
|
||
"options": {
|
||
"title": pname + " - 工作空间",
|
||
"width": "85%",
|
||
"height": "80%",
|
||
"auto_open": True
|
||
},
|
||
"subwidgets": [{
|
||
"widgettype": "ResourceBrowser",
|
||
"id": "ws_rb",
|
||
"options": {
|
||
"tree_options": {
|
||
"widgettype": "Tree",
|
||
"options": {
|
||
"dataurl": entire_url("/pipeline-sdlc/api/workspace_tree.dspy") + _sid_q,
|
||
"textField": "label",
|
||
"idField": "id",
|
||
"cfontsize": 1.0
|
||
}
|
||
},
|
||
"browser_options": {
|
||
"widgettype": "urlwidget",
|
||
"options": {
|
||
"url": entire_url("/pipeline-sdlc/api/workspace_files.dspy") + _sid_q
|
||
},
|
||
"tools": [
|
||
{
|
||
"widgettype": "Button",
|
||
"options": {"label": "查看", "css": "small"},
|
||
"binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self", "script": view_script}]
|
||
},
|
||
{
|
||
"widgettype": "Button",
|
||
"options": {"label": "编辑", "css": "small"},
|
||
"binds": [{"wid": "self", "event": "click", "actiontype": "script", "target": "self", "script": edit_script}]
|
||
},
|
||
{
|
||
"widgettype": "Button",
|
||
"options": {"label": "删除", "css": "small"},
|
||
"binds": [{
|
||
"wid": "self", "event": "click", "actiontype": "script", "target": "self",
|
||
"conform": {
|
||
"title": "删除确认",
|
||
"message": "确认删除选中的文件?",
|
||
"conform": {"label": "删除"},
|
||
"discard": {"label": "取消"}
|
||
},
|
||
"script": delete_script
|
||
}]
|
||
}
|
||
]
|
||
},
|
||
"tree_width": "280px"
|
||
}
|
||
}]
|
||
}
|
||
|
||
return _json.dumps(resp, ensure_ascii=False)
|