fix: 任务树轮次节点显示该轮QC结果(任务已批准≠QC通过,消除误导);组节点标签用最新QC分
This commit is contained in:
parent
ee62a2bbf9
commit
6a4518ef22
@ -151,6 +151,14 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
|
||||
# ── 维度/类型分组 ──
|
||||
if role == 'agent.tender_analyst':
|
||||
# 各维度最新一轮 QC 结果(组节点标签用,消除"任务已批准≠QC通过"误导)
|
||||
latest_qc = {}
|
||||
for rv in await sor.sqlExe(
|
||||
"SELECT qc_type, fit_score, passed, round FROM bid_qc_reviews "
|
||||
"WHERE project_id=${p}$ ORDER BY qc_type, round DESC", {"p": pid}) or []:
|
||||
qt = getattr(rv, 'qc_type', '') or ''
|
||||
if qt not in latest_qc:
|
||||
latest_qc[qt] = rv
|
||||
groups = {}
|
||||
for t in role_tasks:
|
||||
key = (_params_of(t).get('analysis_dim') or '').strip() or '__legacy__'
|
||||
@ -181,10 +189,16 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
})
|
||||
else:
|
||||
final_state = getattr(ts[-1], 'state', '') or ''
|
||||
lq = latest_qc.get(key)
|
||||
if lq:
|
||||
lq_passed = str(getattr(lq, 'passed', '0')) == '1'
|
||||
tail = "QC %.1f 分 %s" % (float(getattr(lq, 'fit_score', 0) or 0),
|
||||
'通过' if lq_passed else '未通过')
|
||||
else:
|
||||
tail = "任务" + _state_zh.get(final_state, final_state)
|
||||
nodes.append({
|
||||
"id": "grp:" + role + ":" + key,
|
||||
"label": "{}({} 轮)最新[{}]".format(label, len(ts),
|
||||
_state_zh.get(final_state, final_state)),
|
||||
"label": "{}({} 轮)最新[{}]".format(label, len(ts), tail),
|
||||
"is_leaf": False,
|
||||
})
|
||||
return json.dumps(nodes, ensure_ascii=False)
|
||||
@ -277,6 +291,10 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
# 维度→QC类型映射(用于给 analyst 轮次挂该轮 QC 结果)
|
||||
DIM_QC = {'scoring': 'scoring_items', 'quals': 'qualifications',
|
||||
'reqs_outline': 'doc_requirements', 'cost_benefit': 'cost_benefit'}
|
||||
|
||||
if role == 'agent.qc':
|
||||
# QC 组:按审核记录轮次升序展开(同一任务多轮复审各占一行)
|
||||
revs = await sor.sqlExe(
|
||||
@ -313,7 +331,8 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
"is_leaf": not (del_cnt.get(getattr(t, 'id', ''), 0) > 0)})
|
||||
return json.dumps(nodes, ensure_ascii=False)
|
||||
|
||||
# analyst 组:按任务创建序(=轮次升序)展开
|
||||
# analyst 组:按任务创建序展开,轮次号与QC结果取自审核记录
|
||||
# (匹配规则:审核记录的 created_at 落在 [本任务updated_at, 下一任务created_at) 区间)
|
||||
ts = []
|
||||
for t in all_tasks:
|
||||
if (getattr(t, 'role', '') or '').strip() != role:
|
||||
@ -324,15 +343,45 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
if k == key:
|
||||
ts.append(t)
|
||||
ts.sort(key=lambda x: str(getattr(x, 'created_at', '') or ''))
|
||||
|
||||
qc_type = DIM_QC.get(key, '')
|
||||
rev_by_round = {}
|
||||
if qc_type:
|
||||
for rv in await sor.sqlExe(
|
||||
"SELECT round, fit_score, passed, created_at FROM bid_qc_reviews "
|
||||
"WHERE project_id=${p}$ AND qc_type=${k}$ ORDER BY round ASC",
|
||||
{"p": pid, "k": qc_type}) or []:
|
||||
rev_by_round[int(getattr(rv, 'round', 0) or 0)] = rv
|
||||
|
||||
nodes = []
|
||||
used_rounds = set()
|
||||
for i, t in enumerate(ts):
|
||||
tid = getattr(t, 'id', '')
|
||||
st = getattr(t, 'state', '') or ''
|
||||
upd = str(getattr(t, 'updated_at', '') or '')[5:16]
|
||||
t_upd = str(getattr(t, 'updated_at', '') or '')
|
||||
nxt_created = str(getattr(ts[i + 1], 'created_at', '') or '9999') if i + 1 < len(ts) else '9999'
|
||||
matched = None
|
||||
for rnd, rv in rev_by_round.items():
|
||||
if rnd in used_rounds:
|
||||
continue
|
||||
rv_t = str(getattr(rv, 'created_at', '') or '')
|
||||
if t_upd and rv_t >= t_upd and rv_t < nxt_created:
|
||||
matched = (rnd, rv)
|
||||
break
|
||||
if matched:
|
||||
rnd, rv = matched
|
||||
used_rounds.add(rnd)
|
||||
passed = str(getattr(rv, 'passed', '0')) == '1'
|
||||
sc = float(getattr(rv, 'fit_score', 0) or 0)
|
||||
qc_label = "→ QC %.1f 分 %s" % (sc, '通过' if passed else '未通过')
|
||||
else:
|
||||
rnd = i + 1
|
||||
qc_label = '→ 未审核/审核记录未关联'
|
||||
upd = t_upd[5:16]
|
||||
nodes.append({
|
||||
"id": tid,
|
||||
"label": "第%d轮 %s [%s] %s" % (i + 1, _state_icons.get(st, '\u2b1c'),
|
||||
_state_zh.get(st, st), upd),
|
||||
"label": "第%d轮 %s [任务%s] %s %s" % (
|
||||
rnd, _state_icons.get(st, '\u2b1c'), _state_zh.get(st, st), qc_label, upd),
|
||||
"is_leaf": not (step_cnt.get(tid, 0) > 0 or del_cnt.get(tid, 0) > 0),
|
||||
})
|
||||
return json.dumps(nodes, ensure_ascii=False)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user