feat(cps): 活动支持编辑(PATCH /activities/{id})

- CpsActivityUpdate schema + repo update_activity(部分更新,非 None 覆盖)
- router 按「合并后最终值」校验平台必填项(同新建口径),写审计 cps.activity.update
- 可改名/平台/对应字段/落地页图/备注/状态

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 22:13:35 +08:00
parent c78cfc838f
commit 4ee6de2548
34 changed files with 288 additions and 76 deletions
+27
View File
@@ -18,6 +18,7 @@ from sqlalchemy import (
JSON,
Boolean,
DateTime,
Float,
ForeignKey,
Index,
Integer,
@@ -101,6 +102,32 @@ class ComparisonRecord(Base):
# 客户端上报的原始 payload(calibration + done.params 全量),未来取数兜底
raw_payload: Mapped[dict | None] = mapped_column(_JSON, nullable=True)
# ===== debug 维度(客户端上报;旧记录 / 未发版客户端为 None)=====
# 设备环境:无障碍比价高度依赖机型/ROM,这是排"某机型跑不通"类问题的头号线索
device_model: Mapped[str | None] = mapped_column(String(64), nullable=True)
device_manufacturer: Mapped[str | None] = mapped_column(String(64), nullable=True)
rom_vendor: Mapped[str | None] = mapped_column(String(32), nullable=True) # vivo/OPPO/Xiaomi/HUAWEI/HONOR/samsung
rom_name: Mapped[str | None] = mapped_column(String(32), nullable=True) # OriginOS/ColorOS/HyperOS/MIUI/EMUI/HarmonyOS...
rom_version: Mapped[int | None] = mapped_column(Integer, nullable=True)
android_version: Mapped[str | None] = mapped_column(String(16), nullable=True) # Build.VERSION.RELEASE
android_sdk: Mapped[int | None] = mapped_column(Integer, nullable=True) # Build.VERSION.SDK_INT
app_version: Mapped[str | None] = mapped_column(String(32), nullable=True) # 我们 app versionName
app_version_code: Mapped[int | None] = mapped_column(Integer, nullable=True)
# 被操控的源平台 App 版本(美团/淘宝/京东),排"平台 App 改版导致 UI 适配失效"用
source_app_version: Mapped[str | None] = mapped_column(String(32), nullable=True)
# 比价时设备定位(影响淘宝 deeplink / 距离匹配)
longitude: Mapped[float | None] = mapped_column(Float, nullable=True)
latitude: Mapped[float | None] = mapped_column(Float, nullable=True)
# ===== 性能 / 过程统计(debug 用)=====
total_ms: Mapped[int | None] = mapped_column(Integer, nullable=True) # 客户端整场比价墙钟耗时
step_count: Mapped[int | None] = mapped_column(Integer, nullable=True) # 客户端 agent loop 总步数
llm_call_count: Mapped[int | None] = mapped_column(Integer, nullable=True) # 本次 LLM 调用次数(server 从 llm_calls 算)
retry_count: Mapped[int | None] = mapped_column(Integer, nullable=True) # LLM 失败重试次数(server 从 llm_calls error 算)
# 每次 LLM 调用明细 [{scene,model,input_messages,output,usage,latency_ms,error}];
# server 收上报后按 trace_id 同机拉 pricebot 落库(见 compare_record 端点)。旧记录/未采集为 None。
llm_calls: Mapped[list | None] = mapped_column(_JSON, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), index=True, nullable=False
)