feat: 最新动态列支持图片展示 — 纯文字/纯图片/图文混合三种模式
后端: ProductResponse 新增 latest_record_has_images
前端: 📷图标 + 纯图片时显示"图片记录" + Tooltip标注[含图片]
This commit is contained in:
@ -58,6 +58,7 @@ class ProductResponse(BaseModel):
|
|||||||
# 🔧 最新动态 — 该产品活跃任务的最新记录
|
# 🔧 最新动态 — 该产品活跃任务的最新记录
|
||||||
latest_record_time: datetime | None = None
|
latest_record_time: datetime | None = None
|
||||||
latest_record_content: str | None = None
|
latest_record_content: str | None = None
|
||||||
|
latest_record_has_images: bool = False
|
||||||
|
|
||||||
model_config = {"from_attributes": True}
|
model_config = {"from_attributes": True}
|
||||||
|
|
||||||
|
|||||||
@ -472,7 +472,7 @@ async def get_all_products(
|
|||||||
)
|
)
|
||||||
).subquery()
|
).subquery()
|
||||||
ranked = (
|
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(
|
sa_func.row_number().over(
|
||||||
partition_by=Task.product_id,
|
partition_by=Task.product_id,
|
||||||
order_by=TR.created_at.desc()
|
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)))
|
.where(Task.id.in_(select(wip_pending_ids.c.id)))
|
||||||
).subquery()
|
).subquery()
|
||||||
rec_result = await db.execute(
|
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)
|
.where(ranked.c.rn == 1)
|
||||||
)
|
)
|
||||||
for row in rec_result:
|
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 [
|
return [
|
||||||
ProductResponse(
|
ProductResponse(
|
||||||
@ -513,8 +514,9 @@ async def get_all_products(
|
|||||||
overall_status=overall_names.get(p.id) or p.overall_status,
|
overall_status=overall_names.get(p.id) or p.overall_status,
|
||||||
status=p.status,
|
status=p.status,
|
||||||
created_at=p.created_at,
|
created_at=p.created_at,
|
||||||
latest_record_time=latest_record_map.get(p.id, (None, None))[0],
|
latest_record_time=latest_record_map.get(p.id, (None, None, False))[0],
|
||||||
latest_record_content=latest_record_map.get(p.id, (None, None))[1],
|
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
|
for p in products
|
||||||
]
|
]
|
||||||
|
|||||||
@ -403,10 +403,13 @@ export default function AdminTasksPage() {
|
|||||||
{/* 最新动态 */}
|
{/* 最新动态 */}
|
||||||
<div className="col-span-2 text-xs">
|
<div className="col-span-2 text-xs">
|
||||||
{p.latest_record_time ? (
|
{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="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="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>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : <span className="text-gray-300">—</span>}
|
) : <span className="text-gray-300">—</span>}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export interface ProductResponse {
|
|||||||
created_at: string;
|
created_at: string;
|
||||||
latest_record_time: string | null;
|
latest_record_time: string | null;
|
||||||
latest_record_content: string | null;
|
latest_record_content: string | null;
|
||||||
|
latest_record_has_images: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** MOM 物料选项 */
|
/** MOM 物料选项 */
|
||||||
|
|||||||
Reference in New Issue
Block a user