From b0273a4f9cf4534e201d67fd2772302581e3c510 Mon Sep 17 00:00:00 2001 From: ymq Date: Mon, 24 Aug 2026 17:56:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(workspace):=20=E6=96=B0=E5=A2=9E=20get=5Fs?= =?UTF-8?q?pace=5Fdir/get=5Fproject=5Fdir/get=5Fproject=5Fapps=5Fmodules/r?= =?UTF-8?q?esolve=5Fworkspace=5Fpath=20=E5=B9=B6=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E5=88=B0=20dspy=20=E7=8E=AF=E5=A2=83=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=B7=A5=E4=BD=9C=E7=A9=BA=E9=97=B4=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=A1=B9=E7=9B=AE=E7=9B=AE=E5=BD=95+apps/mod?= =?UTF-8?q?ules=20=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pipeline_service/workspace.py | 91 +++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/pipeline_service/workspace.py b/pipeline_service/workspace.py index b77fb87..993a370 100644 --- a/pipeline_service/workspace.py +++ b/pipeline_service/workspace.py @@ -155,6 +155,92 @@ async def get_workspace_dir(sor, uid, session_id=''): return build_workspace_path(workspace_base, org_id, space, pname, pid), workspace_base +async def get_space_dir(sor, uid, session_id=''): + """返回机构工作空间层 {space}/(projects/apps/modules 三目录所在)。 + + 新结构:项目目录迁到 {space}/projects/{项目名}/,与 apps/、modules/ 平级。 + workspace_dir 仍是旧结构 {space}/{项目名},space = 其父目录。 + """ + ws_dir, workspace_base = await get_workspace_dir(sor, uid, session_id) + if not ws_dir: + return '', workspace_base + return os.path.dirname(ws_dir.rstrip('/')), workspace_base + + +async def get_project_dir(sor, uid, session_id=''): + """返回项目目录 {space}/projects/{项目名}/(新结构,docs/env/spec.json/deliverables 所在)。""" + space_dir, workspace_base = await get_space_dir(sor, uid, session_id) + if not space_dir: + return '', workspace_base + pid = await get_session_project_id(sor, uid, session_id) + dname = '' + if pid: + try: + r = await sor.sqlExe( + "SELECT directory_name, name FROM sd_projects WHERE id=${p}$ LIMIT 1", + {"p": pid}) + if r: + dname = getattr(r[0], 'directory_name', '') or getattr(r[0], 'name', '') or '' + except Exception: + pass + if not dname: + ws_dir, _ = await get_workspace_dir(sor, uid, session_id) + dname = os.path.basename(ws_dir.rstrip('/')) + return os.path.join(space_dir, 'projects', dname), workspace_base + + +async def get_project_apps_modules(sor, uid, session_id=''): + """读项目目录下 {应用名}_spec.json,返回 (apps, modules)。 + + apps = 各 spec.json 的 app 字段;modules = referenced_modules + generated_modules 去重。 + """ + import json as _json + project_dir, _ = await get_project_dir(sor, uid, session_id) + if not project_dir or not os.path.isdir(project_dir): + return [], [] + apps = [] + modules = set() + try: + for f in sorted(os.listdir(project_dir)): + if not f.endswith('_spec.json'): + continue + fp = os.path.join(project_dir, f) + try: + with open(fp, 'r', encoding='utf-8') as fh: + data = _json.loads(fh.read()) + except Exception: + continue + if not isinstance(data, dict): + continue + app = (data.get('app') or '').strip() + if app: + apps.append(app) + for m in (data.get('referenced_modules') or []) + (data.get('generated_modules') or []): + if isinstance(m, str) and m.strip(): + modules.add(m.strip()) + except Exception: + pass + return sorted(set(apps)), sorted(modules) + + +def resolve_workspace_path(project_dir, space_dir, node_id): + """把工作空间节点 ID 解析成绝对路径。 + + - '@apps/xxx' → space_dir/apps/xxx(项目用到的应用) + - '@modules/xxx' → space_dir/modules/xxx(项目用到的模块) + - '__root__' / 空 → project_dir(项目目录根) + - 其他 → project_dir/xxx(项目目录内的相对路径) + """ + node_id = (node_id or '').strip() + if node_id.startswith('@apps/'): + return os.path.join(space_dir, 'apps', node_id[len('@apps/'):]) + if node_id.startswith('@modules/'): + return os.path.join(space_dir, 'modules', node_id[len('@modules/'):]) + if not node_id or node_id == '__root__': + return project_dir + return os.path.join(project_dir, node_id) + + async def get_workspace_path(sor, user_id, session_id=''): """获取用户当前项目的工作空间路径(无项目时返回 None)。""" ws, _ = await get_workspace_dir(sor, user_id, session_id) @@ -314,7 +400,12 @@ def load_workspace(): g.get_workspace_base = get_workspace_base g.get_workspace_dir = get_workspace_dir g.get_workspace_path = get_workspace_path + g.get_space_dir = get_space_dir + g.get_project_dir = get_project_dir + g.get_project_apps_modules = get_project_apps_modules g.build_workspace_path = build_workspace_path + g.build_space_path = build_space_path + g.resolve_workspace_path = resolve_workspace_path g.GENERAL_SPACE = GENERAL_SPACE g.build_tree_items = build_tree_items g.build_file_widgets = build_file_widgets