feat: 最新动态列支持图片展示 — 纯文字/纯图片/图文混合三种模式

后端: ProductResponse 新增 latest_record_has_images
前端: 📷图标 + 纯图片时显示"图片记录" + Tooltip标注[含图片]
This commit is contained in:
2026-08-12 16:01:24 +08:00
parent 92c388190c
commit e511952ea0
4 changed files with 14 additions and 7 deletions

View File

@ -58,6 +58,7 @@ class ProductResponse(BaseModel):
# 🔧 最新动态 — 该产品活跃任务的最新记录
latest_record_time: datetime | None = None
latest_record_content: str | None = None
latest_record_has_images: bool = False
model_config = {"from_attributes": True}

View File

@ -472,7 +472,7 @@ async def get_all_products(
)
).subquery()
ranked = (
select(TR.task_id, TR.remark, TR.created_at, Task.product_id,
select(TR.task_id, TR.remark, TR.images, TR.created_at, Task.product_id,
sa_func.row_number().over(
partition_by=Task.product_id,
order_by=TR.created_at.desc()
@ -481,11 +481,12 @@ async def get_all_products(
.where(Task.id.in_(select(wip_pending_ids.c.id)))
).subquery()
rec_result = await db.execute(
select(ranked.c.product_id, ranked.c.created_at, ranked.c.remark)
select(ranked.c.product_id, ranked.c.created_at, ranked.c.remark, ranked.c.images)
.where(ranked.c.rn == 1)
)
for row in rec_result:
latest_record_map[row[0]] = (row[1], row[2])
has_img = bool(row[3] and row[3] != "[]" and row[3] != "null")
latest_record_map[row[0]] = (row[1], row[2], has_img)
return [
ProductResponse(
@ -513,8 +514,9 @@ async def get_all_products(
overall_status=overall_names.get(p.id) or p.overall_status,
status=p.status,
created_at=p.created_at,
latest_record_time=latest_record_map.get(p.id, (None, None))[0],
latest_record_content=latest_record_map.get(p.id, (None, None))[1],
latest_record_time=latest_record_map.get(p.id, (None, None, False))[0],
latest_record_content=latest_record_map.get(p.id, (None, None, False))[1],
latest_record_has_images=latest_record_map.get(p.id, (None, None, False))[2],
)
for p in products
]

View File

@ -403,10 +403,13 @@ export default function AdminTasksPage() {
{/* 最新动态 */}
<div className="col-span-2 text-xs">
{p.latest_record_time ? (
<Tooltip title={p.latest_record_content || ""}>
<Tooltip title={(p.latest_record_content || "") + (p.latest_record_has_images ? " [含图片]" : "")}>
<div className="cursor-default">
<div className="text-[10px] text-gray-400">{new Date(p.latest_record_time).toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}</div>
<div className="mt-0.5 truncate text-[11px] text-gray-600">{p.latest_record_content || "—"}</div>
<div className="mt-0.5 flex items-center gap-1 truncate text-[11px] text-gray-600">
{p.latest_record_has_images && <span className="shrink-0">📷</span>}
<span className="truncate">{p.latest_record_content || (p.latest_record_has_images ? "图片记录" : "—")}</span>
</div>
</div>
</Tooltip>
) : <span className="text-gray-300">—</span>}

View File

@ -20,6 +20,7 @@ export interface ProductResponse {
created_at: string;
latest_record_time: string | null;
latest_record_content: string | null;
latest_record_has_images: boolean;
}
/** MOM 物料选项 */