fix: 留言板区分业务序列号与系统追溯码
语义修正: Product.serial_number = 16位HEX系统追溯码(如000000000000000D) Product.external_serial = 业务产品序列号(如25022) 后端: - ProductMessageItem 新增 external_serial 字段 - search_product_messages 关联查询 Product.external_serial - 关键词搜索也支持按 external_serial 匹配 前端显示: 样品升降台V1J · 序列号: 25022 ← 醒目 追溯码: 000000000000000D ← 10px浅灰小字
This commit is contained in:
@ -37,10 +37,11 @@ class WipTask(BaseModel):
|
|||||||
class ProductMessageItem(BaseModel):
|
class ProductMessageItem(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
content: str
|
content: str
|
||||||
operator_name: str # 留言人中文姓名
|
operator_name: str # 留言人中文姓名
|
||||||
product_sn: str # 16位SN
|
product_sn: str # 16位HEX系统追溯码
|
||||||
material_name: str # 物料名称
|
external_serial: str | None # 业务产品序列号(如 25022)
|
||||||
created_at: str # ISO时间字符串
|
material_name: str # 物料名称
|
||||||
|
created_at: str # ISO时间字符串
|
||||||
|
|
||||||
|
|
||||||
class ProductMessageList(BaseModel):
|
class ProductMessageList(BaseModel):
|
||||||
@ -194,9 +195,9 @@ async def search_product_messages(
|
|||||||
from app.models.product import Product
|
from app.models.product import Product
|
||||||
from app.core.time_utils import BEIJING_TZ
|
from app.core.time_utils import BEIJING_TZ
|
||||||
|
|
||||||
# 基础查询
|
# 基础查询 — 同时取出 16位追溯码 + 业务序列号
|
||||||
stmt = (
|
stmt = (
|
||||||
select(ProductMessage, Product.serial_number, Product.material_name)
|
select(ProductMessage, Product.serial_number, Product.material_name, Product.external_serial)
|
||||||
.join(Product, ProductMessage.product_id == Product.id)
|
.join(Product, ProductMessage.product_id == Product.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -205,6 +206,7 @@ async def search_product_messages(
|
|||||||
kw = f"%{keyword.strip()}%"
|
kw = f"%{keyword.strip()}%"
|
||||||
stmt = stmt.where(or_(
|
stmt = stmt.where(or_(
|
||||||
Product.serial_number.ilike(kw),
|
Product.serial_number.ilike(kw),
|
||||||
|
Product.external_serial.ilike(kw),
|
||||||
Product.material_name.ilike(kw),
|
Product.material_name.ilike(kw),
|
||||||
ProductMessage.operator_id.ilike(kw),
|
ProductMessage.operator_id.ilike(kw),
|
||||||
ProductMessage.content.ilike(kw),
|
ProductMessage.content.ilike(kw),
|
||||||
@ -227,7 +229,7 @@ async def search_product_messages(
|
|||||||
name_map = get_display_names(raw_ids)
|
name_map = get_display_names(raw_ids)
|
||||||
|
|
||||||
items: list[ProductMessageItem] = []
|
items: list[ProductMessageItem] = []
|
||||||
for msg, sn, mat_name in rows:
|
for msg, sn, mat_name, ext_sn in rows:
|
||||||
t = msg.created_at
|
t = msg.created_at
|
||||||
if t:
|
if t:
|
||||||
if t.tzinfo is None:
|
if t.tzinfo is None:
|
||||||
@ -243,6 +245,7 @@ async def search_product_messages(
|
|||||||
content=msg.content,
|
content=msg.content,
|
||||||
operator_name=name_map.get(msg.operator_id, msg.operator_id),
|
operator_name=name_map.get(msg.operator_id, msg.operator_id),
|
||||||
product_sn=sn or "",
|
product_sn=sn or "",
|
||||||
|
external_serial=ext_sn or None,
|
||||||
material_name=mat_name or "",
|
material_name=mat_name or "",
|
||||||
created_at=time_str,
|
created_at=time_str,
|
||||||
))
|
))
|
||||||
|
|||||||
@ -127,11 +127,15 @@ function MsgRow({ m }: { m: ProductMessageItem }) {
|
|||||||
<span className="shrink-0 text-xs text-gray-400">{t}</span>
|
<span className="shrink-0 text-xs text-gray-400">{t}</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-2 text-sm leading-relaxed text-gray-600">{m.content}</p>
|
<p className="mb-2 text-sm leading-relaxed text-gray-600">{m.content}</p>
|
||||||
<div className="flex items-center gap-1 text-xs text-gray-500">
|
<div className="flex flex-col gap-0.5">
|
||||||
{m.material_name && (
|
{m.material_name && (
|
||||||
<span className="font-medium text-gray-700">{m.material_name}</span>
|
<span className="text-xs">
|
||||||
|
<span className="font-semibold text-gray-700">{m.material_name}</span>
|
||||||
|
<span className="text-gray-400"> · 序列号: </span>
|
||||||
|
<span className="font-medium text-gray-600">{m.external_serial || "未录入"}</span>
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
<span className="font-mono text-gray-400">(SN: {m.product_sn})</span>
|
<span className="text-[10px] text-gray-300 font-mono">追溯码: {m.product_sn}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export interface ProductMessageItem {
|
|||||||
content: string;
|
content: string;
|
||||||
operator_name: string;
|
operator_name: string;
|
||||||
product_sn: string;
|
product_sn: string;
|
||||||
|
external_serial: string | null;
|
||||||
material_name: string;
|
material_name: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user