From 0b3b7376e41715972032ed70d0ccf32b05f8a9a2 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sat, 1 Aug 2026 10:27:07 +0800 Subject: [PATCH] feat: add task_tree and pipeline_options APIs for SDLC dashboard --- wwwroot/api/pipeline_options.dspy | 18 ++++++++++ wwwroot/api/task_tree.dspy | 59 +++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 wwwroot/api/pipeline_options.dspy create mode 100644 wwwroot/api/task_tree.dspy diff --git a/wwwroot/api/pipeline_options.dspy b/wwwroot/api/pipeline_options.dspy new file mode 100644 index 0000000..9056f75 --- /dev/null +++ b/wwwroot/api/pipeline_options.dspy @@ -0,0 +1,18 @@ +try: + async with get_sor_context(request._run_ns, 'pipeline') as sor: + sql = ''' + SELECT id, name, pipeline_type, status + FROM pipelines + WHERE status = 'published' + ORDER BY name + ''' + recs = await sor.sqlExe(sql, {}) + rows = [] + for r in recs: + rows.append({ + 'value': r.id, + 'text': '{} [{}]'.format(r.name, r.pipeline_type or ''), + }) + return json.dumps(rows, ensure_ascii=False) +except Exception as e: + return json.dumps([], ensure_ascii=False) diff --git a/wwwroot/api/task_tree.dspy b/wwwroot/api/task_tree.dspy new file mode 100644 index 0000000..10b7eac --- /dev/null +++ b/wwwroot/api/task_tree.dspy @@ -0,0 +1,59 @@ +tenant_id = (await get_userorgid()) or '0' +task_id = params_kw.get('task_id', '') +parent_id = params_kw.get('id', None) + +if not task_id: + return json.dumps({"success": False, "message": "缺少task_id"}, ensure_ascii=False) + +state_icons = { + 'completed': '\u2705', + 'running': '\ud83d\udfe1', + 'failed': '\u274c', + 'waiting': '\u26a0\ufe0f', + 'pending': '\u2b1c', + 'paused': '\u23f8\ufe0f', + 'cancelled': '\ud83d\uded1', + 'skipped': '\u23ed\ufe0f', + 'rejected': '\ud83d\udeab', +} + +try: + result = await pipeline_detail(tenant_id, task_id) + data = json.loads(result) + if not data.get('success'): + return json.dumps([], ensure_ascii=False) + + steps = data.get('task', {}).get('steps', []) + tree_nodes = [] + for step in steps: + step_name = step.get('step_name', '') + display_name = step.get('display_name', step_name) + state = step.get('state', 'pending') + step_config_str = step.get('step_config', '{}') + + parent_step = '' + try: + cfg = json.loads(step_config_str) if isinstance(step_config_str, str) else step_config_str + parent_step = cfg.get('parent_step', '') or '' + except: + pass + + icon = state_icons.get(state, '\u2b1c') + label = '{} {} ({})'.format(icon, display_name, state) + + tree_nodes.append({ + 'id': step_name, + 'parent_step': parent_step, + 'label': label, + 'state': state, + 'step_type': step.get('step_type', ''), + }) + + if parent_id is not None: + tree_nodes = [n for n in tree_nodes if n['parent_step'] == parent_id] + else: + pass + + return json.dumps(tree_nodes, ensure_ascii=False) +except Exception as e: + return json.dumps([], ensure_ascii=False)