feat: PM任务分解与编排——父子关系(parent_id)+依赖串行(depends_on)+任务树分层
This commit is contained in:
parent
f022b304d6
commit
c0cb3148a1
@ -83,7 +83,7 @@ async with DBPools().sqlorContext(dbname) as sor:
|
|||||||
|
|
||||||
# 一次查所有任务 + 所有迭代(任务数不大,Python 分组避免 SQL JSON 函数坑)
|
# 一次查所有任务 + 所有迭代(任务数不大,Python 分组避免 SQL JSON 函数坑)
|
||||||
all_tasks = await sor.sqlExe(
|
all_tasks = await sor.sqlExe(
|
||||||
"SELECT id, title, role, state, params FROM pipeline_tasks WHERE tenant_id=${p}$ ORDER BY created_at ASC",
|
"SELECT id, title, role, state, params, parent_id FROM pipeline_tasks WHERE tenant_id=${p}$ ORDER BY created_at ASC",
|
||||||
{"p": pid}) or []
|
{"p": pid}) or []
|
||||||
iters = await sor.sqlExe(
|
iters = await sor.sqlExe(
|
||||||
"SELECT id, iteration_name, status FROM sd_iterations WHERE project_id=${p}$ ORDER BY created_at ASC",
|
"SELECT id, iteration_name, status FROM sd_iterations WHERE project_id=${p}$ ORDER BY created_at ASC",
|
||||||
@ -162,7 +162,7 @@ async with DBPools().sqlorContext(dbname) as sor:
|
|||||||
})
|
})
|
||||||
return json.dumps(nodes, ensure_ascii=False)
|
return json.dumps(nodes, ensure_ascii=False)
|
||||||
|
|
||||||
# 任务列表
|
# 任务列表(只列顶层任务:parent_id 为空的;子任务挂在父任务下展开,避免平铺重复)
|
||||||
nodes = []
|
nodes = []
|
||||||
for t in iter_tasks:
|
for t in iter_tasks:
|
||||||
r = (getattr(t, 'role', '') or '').strip()
|
r = (getattr(t, 'role', '') or '').strip()
|
||||||
@ -174,15 +174,37 @@ async with DBPools().sqlorContext(dbname) as sor:
|
|||||||
tid = getattr(t, 'id', '')
|
tid = getattr(t, 'id', '')
|
||||||
title = getattr(t, 'title', '') or ''
|
title = getattr(t, 'title', '') or ''
|
||||||
state = getattr(t, 'state', '') or ''
|
state = getattr(t, 'state', '') or ''
|
||||||
|
parent = (getattr(t, 'parent_id', '') or '').strip()
|
||||||
|
if parent:
|
||||||
|
continue # 子任务不在阶段平铺,挂在父任务下展示
|
||||||
if not tid or not title:
|
if not tid or not title:
|
||||||
continue
|
continue
|
||||||
icon = _state_icons.get(state, '⬜')
|
icon = _state_icons.get(state, '⬜')
|
||||||
zh = _state_zh.get(state, state)
|
zh = _state_zh.get(state, state)
|
||||||
|
has_child = any((getattr(c, 'parent_id', '') or '').strip() == tid for c in all_tasks)
|
||||||
nodes.append({
|
nodes.append({
|
||||||
"id": tid,
|
"id": tid,
|
||||||
"label": "{} [{}] {}".format(icon, zh, title),
|
"label": "{} [{}] {}".format(icon, zh, title),
|
||||||
"is_leaf": True,
|
"is_leaf": not has_child,
|
||||||
})
|
})
|
||||||
return json.dumps(nodes, ensure_ascii=False)
|
return json.dumps(nodes, ensure_ascii=False)
|
||||||
|
|
||||||
return json.dumps([], ensure_ascii=False)
|
# 子任务层:裸任务ID → 返回该任务的子任务(parent_id == 该ID),递归支持多级分解
|
||||||
|
nodes = []
|
||||||
|
for t in all_tasks:
|
||||||
|
if (getattr(t, 'parent_id', '') or '').strip() != node_id:
|
||||||
|
continue
|
||||||
|
tid = getattr(t, 'id', '')
|
||||||
|
title = getattr(t, 'title', '') or ''
|
||||||
|
state = getattr(t, 'state', '') or ''
|
||||||
|
if not tid or not title:
|
||||||
|
continue
|
||||||
|
icon = _state_icons.get(state, '⬜')
|
||||||
|
zh = _state_zh.get(state, state)
|
||||||
|
has_child = any((getattr(c, 'parent_id', '') or '').strip() == tid for c in all_tasks)
|
||||||
|
nodes.append({
|
||||||
|
"id": tid,
|
||||||
|
"label": "{} [{}] {}".format(icon, zh, title),
|
||||||
|
"is_leaf": not has_child,
|
||||||
|
})
|
||||||
|
return json.dumps(nodes, ensure_ascii=False)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user