fix: 效能分析flow时间筛选改为设备级(该时间有活动即入选),任务完整返回不切片

This commit is contained in:
2026-09-03 16:27:04 +08:00
parent fe495ad707
commit cd5a904a16

View File

@ -342,25 +342,10 @@ async def get_flow_compare(
if not product_rows: if not product_rows:
return FlowResponse(devices=[], series=[]) return FlowResponse(devices=[], series=[])
devices = [
FlowDevice(
product_sn=r[1], external_serial=r[2],
material_name=r[3] or "", spec_model=r[4] or "",
lead_time=0.0,
started_at="",
)
for r in product_rows
]
# 显式传入身份证时按输入顺序排列
if product_sns:
order = {sn: i for i, sn in enumerate(product_sns)}
devices.sort(key=lambda d: order.get(d.product_sn, len(order)))
id_to_sn = {r[0]: r[1] for r in product_rows} id_to_sn = {r[0]: r[1] for r in product_rows}
sn_to_index = {d.product_sn: i for i, d in enumerate(devices)}
product_ids = [r[0] for r in product_rows] product_ids = [r[0] for r in product_rows]
# ── 这些设备的全部任务(含工序名,用于区间图) ── # ── 候选设备的全部任务(含工序名,用于区间图) ──
task_rows = (await db.execute( task_rows = (await db.execute(
select( select(
Task.product_id, Task.assignee_id, Task.task_name, Task.product_id, Task.assignee_id, Task.task_name,
@ -374,25 +359,57 @@ async def get_flow_compare(
) )
)).all() )).all()
# ── 解析为区间记录,并计算每台设备的 T0最早与 max_end最晚 ── # ── 设备级时间筛选 ──
# 语义:时间筛选 = "在该时间有活动的设备",而非"把任务切片只保留该时间"。
# 设备一旦入选,其任务必须完整返回(完整生命周期),绝不因设备在筛选中无新动作
# 而把它的历史任务清空。
if since is not None or until is not None:
active_pids: set = set()
for row in task_rows:
pid = row[0]
start = _to_bj(row[3] or row[4])
end = _to_bj(row[5]) if row[5] else now
if start is None:
continue
if since is not None and end < since:
continue
if until is not None and start > until:
continue
active_pids.add(pid)
product_rows = [r for r in product_rows if r[0] in active_pids]
if not product_rows:
return FlowResponse(devices=[], series=[])
# 显式传入身份证时按输入顺序排列
if product_sns:
order = {sn: i for i, sn in enumerate(product_sns)}
product_rows.sort(key=lambda r: order.get(r[1], len(order)))
devices = [
FlowDevice(
product_sn=r[1], external_serial=r[2],
material_name=r[3] or "", spec_model=r[4] or "",
lead_time=0.0,
started_at="",
)
for r in product_rows
]
sn_to_index = {d.product_sn: i for i, d in enumerate(devices)}
kept_ids = {r[0] for r in product_rows}
# ── 解析为区间记录(完整生命周期,不再按时间切片) ──
intervals: list[dict] = [] intervals: list[dict] = []
t0_by_device: dict[int, datetime] = {} t0_by_device: dict[int, datetime] = {}
max_end_by_device: dict[int, datetime] = {} max_end_by_device: dict[int, datetime] = {}
for row in task_rows: for row in task_rows:
pid, assignee_id, task_name, received_at, created_at, completed_at, task_type = row pid, assignee_id, task_name, received_at, created_at, completed_at, task_type = row
sn = id_to_sn.get(pid) if pid not in kept_ids:
if sn is None or sn not in sn_to_index:
continue continue
sn = id_to_sn[pid]
idx = sn_to_index[sn] idx = sn_to_index[sn]
start = _to_bj(received_at or created_at) start = _to_bj(received_at or created_at)
end = _to_bj(completed_at) if completed_at else now end = _to_bj(completed_at) if completed_at else now
if start is None: if start is None:
continue continue
# 时间筛选:任务区间与 [since, until] 有交集
if since is not None and end is not None and end < since:
continue
if until is not None and start is not None and start > until:
continue
is_main = 0 if task_type == "SPAWN" else 1 is_main = 0 if task_type == "SPAWN" else 1
intervals.append({ intervals.append({
"idx": idx, "idx": idx,