fix(workspace): 二级URL与office端点透传pipeline_id+_generic分支——通用助手查看/编辑文件报'文件不存在'根因
与 f0c4c10(upload_url) 同族缺陷全量排查修复,共5处:
1. workspace_view.dspy: md_url(file_url)只拼session_id漏pipeline_id→
通用助手(_generic无session_id)下MdWidget二次请求workspace_file.dspy
回退全局项目指针→在别产线空间找文件→弹'文件不存在: projects/调研1/docs/xxx.md'
(2026-09-17实测复现+修复验证)
2. workspace_open.dspy: file_url/ws_url(xterm)/univer_url三处同病灶,统一_fq_s双透传
3. workspace_edit.xterm: 根本不读pipeline_id且用无隔离get_project_dir→
改get_project_dir_pl+_generic锁_general/{uid}(与9个子端点对齐)
4. office_read.dspy/office_save.dspy: 读了pipeline_id但缺_generic分支→
通用助手在线编辑docx报'未指定文件或无工作空间',补齐分支
univer-office前端main.ts配套透传pipeline_id(独立仓库另行部署)
This commit is contained in:
parent
6b326e5563
commit
b02ee5f345
@ -17,6 +17,13 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
# 产线隔离:跨产线项目视为无项目(与弹窗入口一致,防绕过)
|
||||
project_dir, _ = await get_project_dir_pl(sor, uid, session_id, pipeline_id)
|
||||
space_dir, _ = await get_space_dir(sor, uid, session_id)
|
||||
# 通用会话(pipeline_id=_generic):锁用户专属目录 _general/{uid}
|
||||
# (2026-09-17 补齐:此前缺该分支,通用助手在线编辑 docx 报「未指定文件或无工作空间」)
|
||||
if pipeline_id == '_generic':
|
||||
_gd = generic_workspace_dir(uid)
|
||||
os.makedirs(_gd, exist_ok=True)
|
||||
project_dir = _gd
|
||||
space_dir = _gd
|
||||
|
||||
if not file_id or not space_dir:
|
||||
return {"error": "未指定文件或无工作空间", "markdown": ""}
|
||||
|
||||
@ -19,6 +19,13 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
# 产线隔离:跨产线项目视为无项目(与弹窗入口一致,防绕过)
|
||||
project_dir, _ = await get_project_dir_pl(sor, uid, session_id, pipeline_id)
|
||||
space_dir, _ = await get_space_dir(sor, uid, session_id)
|
||||
# 通用会话(pipeline_id=_generic):锁用户专属目录 _general/{uid}
|
||||
# (2026-09-17 补齐:此前缺该分支,通用助手在线编辑 docx 保存失败)
|
||||
if pipeline_id == '_generic':
|
||||
_gd = generic_workspace_dir(uid)
|
||||
os.makedirs(_gd, exist_ok=True)
|
||||
project_dir = _gd
|
||||
space_dir = _gd
|
||||
|
||||
if not file_id or not space_dir:
|
||||
return {"success": False, "error": "未指定文件或无工作空间"}
|
||||
|
||||
@ -56,11 +56,20 @@ audio_exts = ['.mp3', '.wav', '.aac', '.flac', '.m4a', '.ogg']
|
||||
image_exts = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.bmp', '.ico']
|
||||
office_exts = ['.docx'] # 在线编辑(univer-office)。xlsx/ppt 后续接入 Univer sheet/slide 插件
|
||||
|
||||
file_url = entire_url("/pipeline-sdlc/api/workspace_file.dspy") + "?id=" + quote(file_id) + (("&session_id=" + session_id) if session_id else "")
|
||||
# 二级 URL 双透传 session_id + pipeline_id(2026-09-17 根因同 workspace_view/upload):
|
||||
# 通用助手(pipeline_id=_generic、无 session_id)下漏拼 pipeline_id 会让下游端点
|
||||
# (workspace_file/workspace_edit.xterm/univer-office)回退全局项目指针 → 「文件不存在」。
|
||||
_fq = []
|
||||
if session_id:
|
||||
_fq.append("session_id=" + session_id)
|
||||
if pipeline_id:
|
||||
_fq.append("pipeline_id=" + pipeline_id)
|
||||
_fq_s = ("&" + "&".join(_fq)) if _fq else ""
|
||||
file_url = entire_url("/pipeline-sdlc/api/workspace_file.dspy") + "?id=" + quote(file_id) + _fq_s
|
||||
|
||||
# 1. 文本/源码 → Wterm + vi 编辑
|
||||
if ext in text_exts:
|
||||
ws_url = entire_url("/wss/pipeline-sdlc/workspace_edit.xterm") + "?id=" + quote(file_id) + (("&session_id=" + session_id) if session_id else "")
|
||||
ws_url = entire_url("/wss/pipeline-sdlc/workspace_edit.xterm") + "?id=" + quote(file_id) + _fq_s
|
||||
return {
|
||||
"widgettype": "PopupWindow",
|
||||
"options": {"title": name + " (vi 编辑)", "width": "85%", "height": "85%", "auto_open": True, "resizable": True},
|
||||
@ -109,7 +118,7 @@ if ext in image_exts:
|
||||
|
||||
# 4. office 文档 → iframe 嵌入 univer-office 在线编辑
|
||||
if ext in office_exts:
|
||||
univer_url = entire_url("/univer-office/") + "?file=" + quote(file_id) + (("&session_id=" + session_id) if session_id else "")
|
||||
univer_url = entire_url("/univer-office/") + "?file=" + quote(file_id) + _fq_s
|
||||
return {
|
||||
"widgettype": "PopupWindow",
|
||||
"options": {"title": name + " (在线编辑)", "width": "85%", "height": "85%", "auto_open": True, "resizable": True},
|
||||
|
||||
@ -56,7 +56,16 @@ if not os.path.isfile(full_path):
|
||||
name = os.path.basename(full_path)
|
||||
ext = os.path.splitext(name)[1].lower()
|
||||
|
||||
file_url = entire_url("/pipeline-sdlc/api/workspace_file.dspy") + "?id=" + quote(file_id) + (("&session_id=" + session_id) if session_id else "")
|
||||
# 二级 URL 必须与本级同参数(session_id + pipeline_id 双透传,2026-09-17 根因同 upload_url):
|
||||
# 通用助手(pipeline_id=_generic、无 session_id)下漏拼 pipeline_id 会让 workspace_file.dspy
|
||||
# 回退全局项目指针 → 在错误空间找文件 → MdWidget 显示「文件不存在」JSON。
|
||||
_fq = []
|
||||
if session_id:
|
||||
_fq.append("session_id=" + session_id)
|
||||
if pipeline_id:
|
||||
_fq.append("pipeline_id=" + pipeline_id)
|
||||
_fq_s = ("&" + "&".join(_fq)) if _fq else ""
|
||||
file_url = entire_url("/pipeline-sdlc/api/workspace_file.dspy") + "?id=" + quote(file_id) + _fq_s
|
||||
|
||||
# txt/md/json → VScrollPanel 包裹 MdWidget 渲染(可滚动,长文档不截断;json 直接显示正文不下载)
|
||||
md_exts = ['.md', '.txt', '.json']
|
||||
|
||||
@ -17,12 +17,21 @@ if not uid:
|
||||
return r
|
||||
|
||||
session_id = (params_kw or {}).get('session_id', '') or ''
|
||||
pipeline_id = (params_kw or {}).get('pipeline_id', '') or ''
|
||||
|
||||
dbname = get_module_dbname('pipeline-sdlc')
|
||||
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
project_dir, _ = await get_project_dir(sor, uid, session_id)
|
||||
# 产线隔离 + pipeline_id 透传(2026-09-17 修复:此前不读 pipeline_id,
|
||||
# 通用助手 _generic 入口下解析到全局指针的错误项目空间 → 「未指定文件」/编辑错目录)
|
||||
project_dir, _ = await get_project_dir_pl(sor, uid, session_id, pipeline_id)
|
||||
space_dir, _ = await get_space_dir(sor, uid, session_id)
|
||||
# 通用会话(pipeline_id=_generic):锁用户专属目录 _general/{uid}
|
||||
if pipeline_id == '_generic':
|
||||
_gd = generic_workspace_dir(uid)
|
||||
os.makedirs(_gd, exist_ok=True)
|
||||
project_dir = _gd
|
||||
space_dir = _gd
|
||||
|
||||
if not file_id or not space_dir:
|
||||
r = DictObject()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user