120 lines
4.4 KiB
Python
120 lines
4.4 KiB
Python
# coding=utf-8
|
||
"""识别记录仓储:本地 SQLite 必写;MySQL 可用时同步写入总库。"""
|
||
import json
|
||
import time
|
||
from datetime import datetime
|
||
|
||
from dao.database import is_server_available, local_session_scope, server_session_scope
|
||
from models.Recognition_records import RecognitionRecord
|
||
|
||
|
||
def _build_summary(dishes):
|
||
names = []
|
||
for d in dishes or []:
|
||
if d.get('is_unknown'):
|
||
sug = d.get('suggested_category') or d.get('suggested_name')
|
||
names.append(f"未知({sug})" if sug else "未知")
|
||
else:
|
||
names.append(d.get('label') or d.get('name') or "未知")
|
||
return "、".join(names)[:500]
|
||
|
||
|
||
def _serialize_dishes(dishes):
|
||
"""本地/总库识别记录保留完整明细;上报管理系统用精简字段另见 result_api。"""
|
||
items = []
|
||
for i, d in enumerate(dishes or [], 1):
|
||
is_unknown = bool(d.get('is_unknown'))
|
||
items.append({
|
||
'index': d.get('index') or i,
|
||
'name': None if is_unknown else (d.get('label') or d.get('name')),
|
||
'score': d.get('score'),
|
||
'is_unknown': is_unknown,
|
||
'suggested_name': d.get('suggested_category') or d.get('suggested_name'),
|
||
'box': d.get('box'),
|
||
'crop_image': d.get('crop_image'),
|
||
'text': d.get('text'),
|
||
})
|
||
return items
|
||
|
||
|
||
class RecognitionRepository:
|
||
def save(
|
||
self,
|
||
source_image,
|
||
dishes,
|
||
labeled_image=None,
|
||
request_id=None,
|
||
base_code=None,
|
||
source_base_id=None,
|
||
capture_time=None,
|
||
):
|
||
"""保存一次识别记录,返回本地记录 dict。"""
|
||
request_id = request_id or f"REQ_{int(time.time() * 1000)}"
|
||
if isinstance(capture_time, str) and capture_time:
|
||
try:
|
||
capture_dt = datetime.strptime(capture_time, '%Y-%m-%d %H:%M:%S')
|
||
except ValueError:
|
||
capture_dt = datetime.now()
|
||
elif isinstance(capture_time, datetime):
|
||
capture_dt = capture_time
|
||
else:
|
||
capture_dt = datetime.now()
|
||
|
||
dish_items = _serialize_dishes(dishes)
|
||
unknown_count = sum(1 for d in dish_items if d.get('is_unknown'))
|
||
summary = _build_summary(dishes)
|
||
result_json = json.dumps(dish_items, ensure_ascii=False)
|
||
|
||
local_id = None
|
||
with local_session_scope() as session:
|
||
row = RecognitionRecord(
|
||
request_id=request_id,
|
||
base_code=base_code,
|
||
source_base_id=source_base_id,
|
||
capture_time=capture_dt,
|
||
source_image=source_image,
|
||
labeled_image=labeled_image,
|
||
dish_count=len(dish_items),
|
||
unknown_count=unknown_count,
|
||
summary=summary,
|
||
result_json=result_json,
|
||
)
|
||
session.add(row)
|
||
session.flush()
|
||
local_id = row.id
|
||
saved = row.to_dict()
|
||
|
||
if is_server_available():
|
||
try:
|
||
with server_session_scope() as session:
|
||
session.add(RecognitionRecord(
|
||
request_id=request_id,
|
||
base_code=base_code,
|
||
source_base_id=source_base_id,
|
||
capture_time=capture_dt,
|
||
source_image=source_image,
|
||
labeled_image=labeled_image,
|
||
dish_count=len(dish_items),
|
||
unknown_count=unknown_count,
|
||
summary=summary,
|
||
result_json=result_json,
|
||
))
|
||
except Exception as exc:
|
||
print(f"[WARN] recognition record mysql save failed: {exc}")
|
||
|
||
print(f"[OK] recognition saved id={local_id} request_id={request_id} dishes={len(dish_items)}")
|
||
return saved
|
||
|
||
def list_recent(self, limit=50, base_code=None):
|
||
with local_session_scope() as session:
|
||
q = session.query(RecognitionRecord).order_by(RecognitionRecord.capture_time.desc())
|
||
if base_code:
|
||
q = q.filter(RecognitionRecord.base_code == base_code)
|
||
rows = q.limit(limit).all()
|
||
return [r.to_dict() for r in rows]
|
||
|
||
def get(self, record_id):
|
||
with local_session_scope() as session:
|
||
row = session.get(RecognitionRecord, record_id)
|
||
return row.to_dict() if row else None
|