Files
shaguabijia-app-server/docs/待办与技术债.md
T
marco 6c7eaa9734 docs: 跟齐 5 月 PR (#4 user/feedback / #5 ad-cooldown / #6 PG / abd8eab meituan 降级)
整轮 doc 跟齐 2026-05 落地但 doc 没补全/没更新的内容. 按 P0~P3 优先级处理.

P0 - 新 API doc + index 更新:
* docs/api/user-profile.md  (新) PATCH /api/v1/user/profile 改昵称
* docs/api/user-avatar.md   (新) POST /api/v1/user/avatar 上传头像(魔数嗅探/旧文件清理)
* docs/api/user-delete.md   (新) DELETE /api/v1/user 注销账号(软删+匿名化)
* docs/api/feedback.md      (新) POST /api/v1/feedback 提交反馈(含截图)
* docs/api/README.md           加 User/Feedback 组 + /media 静态服务段 +
                                修 UserOut "无接口可改恒为 null" 过时描述

P0 - 美团降级 / 现有 doc 校准:
* docs/api/meituan-coupons.md      加 "未配 MT_CPS 凭证降级返空" 说明
* docs/api/meituan-referral-link.md 同上 + 客户端兜底建议
* docs/api/meituan-feed.md         区分两种空结果路径(未配 vs 调用失败) +
                                    /health.mt_cps_configured 排障入口
* docs/integrations/meituan.md     "未配凭证降级" + "feed 静默吞错" 写进集成层
* ad-reward-status.md              PR #5 commit 已自带 doc 更新, 复核无需再改

P1 - 主文档大改:
* docs/后端技术实现.md
  - §1 能力表加 用户资料/外卖比价/钱包/福利/广告/反馈 (从 3 条扩到 9 条)
  - §1 数据模型纠正 "仅 1 张 user 表" -> 现有 10 张 + alembic_version
  - §2 DB 行 PG 主 / SQLite 兜底 + 加 psycopg3 行
  - §3 目录树补 user.py / feedback.py / media.py / repositories/feedback.py /
        scripts 子项 / docs/postgres-migration.md
  - §7 数据模型重写: 10 张业务表速查表 + alembic 合并迁移 f01db5d77dac 始末
  - §8 部署: 加 init_postgres.py 一句话流程 + checklist 加 "DATABASE_URL 切 PG"
        + "psycopg3 已装" + "MEDIA_ROOT 可写"
  - §10 已知问题: 加 美团降级 / agent 不鉴权 / MEDIA_ROOT serve / init_postgres bug /
        alembic 多 head 风险; 删过时 SQLite 行
  - 接口计数 11 -> 38

* docs/待办与技术债.md
  - 已解决追加: PG 切换 / 外卖比价透传 / 用户资料反馈接口 / 美团降级 /
                看广告 4 态冷却
  - 新增 "P2 DB 与 Alembic 治理" 段: alembic 多 head 团队规约 (含本次撞坑实录) +
    init_postgres.py 已知 5 处小 bug + MEDIA_ROOT serve

P2 - PG 迁移文档互指 + 迁移链补完:
* docs/数据库迁移.md
  - 顶部加 postgres-migration.md / 后端技术实现.md 互指
  - §6 迁移链 9 条 -> 12 条 (含 feedback_table / convert_dishes_jsonb /
        merge_pg_jsonb_and_feedback_heads)
  - §7 踩坑里 "多 head" 一行扩成完整故事 + 修复命令 + 团队预防规约
* docs/postgres-migration.md
  - 顶部加 数据库迁移.md / 后端技术实现.md §10 互指

P3 - 上线清单:
* docs/看广告赚金币上线清单.md
  - 设计要点加 PR #5 4 态 CTA + 后端权威派生说明 +
    VIDEO_ROUND_REQUIRED_COUNT/VIDEO_ROUND_COOLDOWN_SECONDS 常量
  - §E 端到端验收加 本轮冷却 / 弹窗 limit note / 跨设备一致 三项

所有最后更新日期同步到 2026-05-31.
2026-05-31 11:05:10 +08:00

11 KiB
Raw Blame History

待办与技术债账本

用途:记"现在先简化、以后要补"的事,和暂不处理的技术债,免得忘。每条标优先级 + 触发背景。做掉的移到末尾「已解决」。 范围:跨栈账本——本仓 shaguabijia-app-server(转发层) + shaguabijia-app-android(无障碍引擎移植) + pricebot-backend(agent 上游,不改)。 大背景:把"后端当大脑、无障碍服务遥控前端操作其它 App"的比价/领券引擎,从 demo app pricebot 移植进正式版傻瓜比价。引擎移植采用「代码全搬、独立子包 …shaguabijia.agent.*、验证分步(先领券后比价)」。 最后更新:2026-05-31


P1 · 鉴权与用户绑定(最该补)

  • 现状agent 系列接口 MVP 阶段全部不鉴权。领券 coupon/step 已落地不鉴权( 已去掉 CurrentUser 依赖);比价 4 个(intent/recognizeprice/stepecom/intent/recognizeecom/step)端点尚未建(见 P2),建时同样先不加鉴权。
  • 代价(为什么记这笔账):不验 JWT → 转发时 server 拿不到 user_id → agent 行为只能绑到 device_id(设备级)采集不到"哪个用户领了/买了什么"的用户级画像。而精准人群画像、私域分群运营是商业模式的核心资产,靠的就是这份用户级行为数据。device_id 仍照传(后端按设备串领券队列够用)。
  • 待补:① agent 接口加 JWT 鉴权;② 建立 device_id ↔ user_id 绑定(登录后上报一次即可);③ 领券/比价记录按 user 维度落库。
  • 连带:补鉴权后,客户端引擎 ApiClient 要接回 JWT(复用 app 现有 AuthInterceptor 思路:注入带鉴权头的 OkHttpClient)。

P2 · 引擎移植 · 后端转发层(本仓)

  • 比价透传端点:仿 coupon_step 纯 body 透传、不加 Pydantic schema(协议归 pricebot 校验,否则它一改字段本仓就得跟着改,白白耦合)。client /api/v1/xxx → 转发 backend /api/xxx(去掉 v1,同 coupon_step)。
    • 外卖 2 个已落地(food MVP2026-05-27)intent/recognize + price/step,在 app/api/v1/compare.py(不鉴权、超时 60s),测试 tests/test_compare_proxy.py,文档 docs/api/compare-*.md
    • 电商 2 个待接:ecom/intent/recognize + ecom/step——放开电商 scene 时在 compare.py 加两行即可。
  • 转发超时已分离(2026-05-27):比价用新增的 PRICEBOT_COMPARE_TIMEOUT_SEC=60(意图识别大上下文 LLM、price/step 每帧 LLM),与领券的 PRICEBOT_REQUEST_TIMEOUT_SEC=30 区分;真实耗时待真机实测再定终值。
  • 生产 server 与 backend 同内网PRICEBOT_BASE_URL 部署时设内网地址。比价是 30~80 步循环,每步多一跳,走公网延迟会累积。
  • nginx body 上限:比价 debug 包带 screenshot(webp base64,几百 KB)。若 debug 联调走线上域名经 nginx,注意 client_max_body_size(release 不带截图、debug 直连本地都无此问题,仅"debug 走域名"才撞)。

P2 · 引擎移植 · 客户端(android 仓)

领券链路相关已完成(详见文末「已解决」):无障碍身份改名、BuildConfig 包名、领券入口、SettingsScreen 权限卡、ApiClient 改址。剩余:

  • 比价悬浮球(外卖)已接(2026-05-27)SUPPORTED_BIZ_PACKAGES 收窄到 3 个外卖源(美团/淘宝闪购/京东外卖);scene 写死 food(getSceneMode 默认改「外卖比价」)。点球 → startTask → Phase1/2 → 比价结果悬浮窗,这条链客户端本就齐(随引擎移植搬入),本次只收窄入口 + 写死场景 + 接通 server。电商放开时再加回 PDD/抖音 + scene 选择。
  • 仿腾讯权限引导:搬来的 AccessibilityGuideActivity/PermissionGuide*/GuideOverlayService 尚未接入口;当前是"跳系统设置页"最简版(SettingsScreen 权限卡 + 领券前检查已用)。体验后续可升级成仿腾讯浮层。
  • 类名可选改名PriceBotService 等用户不可见,保留无妨;想整洁可改 ShaguaAccessibilityService(牵动引用,不急)。

技术债(暂不处理,知情即可)

  • agent 接口公网裸奔:不鉴权 = 任何人可调,烧 pricebot 的 LLM 算力。与美团 3 接口现状同级,记账后随 P1 一起补。
  • 既有债(已记录在别处):美团 referral-linksid 客户端可覆盖刷分佣;logout 占位不吊销 tokenSMS_MOCK=true 全站免密登录;JWT_SECRET_KEY 默认值可伪造 token。详见 后端技术实现.mdapi/

P2 · DB 与 Alembic 治理(2026-05-29 新增)

Alembic 多 head 风险 — 团队流程问题

触发背景:2026-05-29 用 PG 跑 alembic upgrade head 报 "Multiple head revisions are present"。

  • 实习生的 feat/postgres-migration-and-bootstrap-script 分支基于 4d444b7 (已合 PR #4 feedback) 创建,但新迁移 ef96beb47b1edown_revision 挂在 c8d9e0f1a2b3 (ad_reward),跟 PR #4 引入的 d1e2f3a4b5c6 (feedback) 并行成两个 head
  • 根因:跨分支并行开发,PR 合并时没人检查 alembic 迁移链是否线性

临时修复:alembic merge -m "merge pg_jsonb and feedback heads" ef96beb47b1e d1e2f3a4b5c6 生成合并迁移 f01db5d77dac_merge_pg_jsonb_and_feedback_heads.py(已合进 main)。

团队规约(待写进 CONTRIBUTING):

  • 新建包含 alembic 迁移的 PR 前,在分支上跑 alembic heads,确认只有一个 head;有多个就先 rebase 自己的迁移文件的 down_revision
  • review 别人含 alembic 迁移的 PR 时,同样检查 heads 数
  • 合并 main 之后再跑一次 alembic heads 兜底——本次撞到就是 review 没拦住

init_postgres.py 已知小 bug(2026-05-29 review)

scripts/init_postgres.py 是实习生为 PG 切换写的 bootstrap 脚本(建用户/库/写 .env/跑迁移),有 5 处可改进项:

  1. if val: 把空字符串当未设PG_SUPER_PASS="" 不能传(本机 trust 认证想跳过密码就只能给占位字符串)
  2. 用户自定义 APP_DB_PASS@:/ 会破坏 URL → 应 urllib.parse.quote(db_pass, safe='')(自动生成的 secrets.token_urlsafe 是 URL 安全字符,但用户传值不一定)
  3. subprocess 跑 alembic 没显式注 DATABASE_URL → 父 shell 残留旧值会覆盖刚写入 .env 的新值,可能把表建到错的库
  4. 强制 TCP localhost → macOS Homebrew(默认 trust)和 Linux apt(默认 peer)的默认认证模式都不直接走 TCP,新机首次跑大概率失败
  5. 承诺的 JSONB GIN 索引没真加 → commit message 和文档都说"PG 上可建 GIN 索引",但 savings_record.dishes 实际没加;要么补 CREATE INDEX ... USING GIN (dishes),要么把"GIN"措辞从理由里删掉

短期不阻塞使用(熟手按预期参数能跑通),但累积起来会让新人踩坑。低优先级清理。

MEDIA_ROOT 进程内 serve

/media 路径当前由 FastAPI StaticFiles 挂载 serve(头像/反馈截图)。生产建议改 nginx 直 serve MEDIA_ROOT 目录,绕过应用进程减少压力。一行 location /media/ { alias /opt/shaguabijia-app-server/data/media/; } 即可。


阶段 1 领券落地后的遗留(待清理,不阻塞跑通)

  • FloatingButton 死代码:Running 面板已换成 ComposeView 承载 CouponProgressPanel(=复用 AgentFloat)。旧原生面板字段(line1~4View/elapsedView/progressBarView/historyContainerView 等)+ updateStatus(StepStatus) 里保留的那段更新逻辑 + appendActionLine/markCurrentActionDone/markPlatformDone/addCancelButton 全部 no-op,待删。
  • ComparingScreen / CompResultScreen 弃用:领券改走悬浮窗,不再走全屏假动画。Routes.COMPARING / COMP_RESULT 成死路由,连同两个 Screen 文件待删(CouponPromptDialog 已抽到 ui/coupon/,删 ComparingScreen 不影响它)。
  • ApiClient 常量 unused:getBackendUrl() 改用 BuildConfig.BASE_URL 后,DEFAULT_BACKEND_URL/KEY_BACKEND_URL 常量 unused,待清。
  • 领券大数字语义:悬浮窗左侧"已领券"大数字目前接 progress.current(正在领第几张),非"已成功数"。中间帧后端不回传已领明细,要精确需后端在 status.progress 加 completed[](协议文档第四节已留扩展点)。
  • 正式版 versionCode 必须 > 占坑版线上最高:占坑版(shaguabijia-android)与正式版同包名 com.jishisongfu.shaguabijia 原地覆盖。正式版当前 versionCode=1,真机占坑版是 5 → 同签名降级被 Android 拒装,正式版无法覆盖更新线上占坑版用户。上线前 versionCode 要提到 > 线上占坑版最高值。

已解决

  • 领券链路接通(阶段 1):首页「去领取」→ CouponPromptDialog → 权限检查 → startCouponClaim → 循环 /api/v1/coupon/step;Running 悬浮窗换皮(ComposeView 承载 CouponProgressPanel/AgentFloat,OverlayLifecycleOwner 撑 Compose)。
  • coupon/step 去鉴权:去掉 CurrentUser,MVP 不鉴权(device_id 透传)。
  • ApiClient 改址:BuildConfig.BASE_URL + /api/v1/ 前缀。
  • SettingsScreen 权限卡:5 项(无障碍/悬浮窗/录屏<API30/电池/自启动)真实检测 + 点击跳转 + 自启动无法检测态 + onResume 自动刷新 + 刷新按钮;逻辑抽到 PermissionHelper(HomeScreen 领券前检查复用)。
  • 无障碍身份统一傻瓜比价:服务名/图标继承 app;accessibility_service_description/前台通知/GuideCopy/引导 Activity 里的 "PriceBot" 全改「傻瓜比价」;app 图标换成完整 logo1(adaptive 居中+黄边,不裁切)。
  • GuideOverlayService 组件名 bug:批量 sed 改包名误把无障碍服务 ComponentName 的 packageName 改成 …shaguabijia.agent(应是 applicationId …shaguabijia)→ 无障碍开启检测永远 false;改用 PermissionHelper.isAccessibilityEnabled 动态构造。
  • BuildConfig 包名:com.pricebot.app.BuildConfig import 改本 app 包名。
  • SQLite → PostgreSQL 切换(2026-05-29,PR #6 + alembic 合并迁移):新增 scripts/init_postgres.py 一键脚本、psycopg[binary]>=3.1 依赖、savings_record.dishes 列改 JSONB、连接池参数(pool_size=10/overflow=20/recycle=3600)。SQLite 仍可作开发兜底(只改 DATABASE_URL)。详见 postgres-migration.md
  • 外卖比价透传 2 端点(2026-05-27,feat(compare)):/api/v1/intent/recognize + /api/v1/price/stepcompare.py,纯 body 透传到 pricebot-backend,PRICEBOT_COMPARE_TIMEOUT_SEC=60 独立超时。电商 2 个待接(compare.py 加两行即可)。
  • 用户资料 + 帮助反馈接口(2026-05-28,PR #4):PATCH /api/v1/user/profile 改昵称、POST /api/v1/user/avatar 上传头像(魔数嗅探)、DELETE /api/v1/user 注销账号(软删+匿名化)、POST /api/v1/feedback 提交反馈(含截图);新建 feedback 表 + core/media.py + /media 静态服务。
  • 美团 3 端点未配凭证降级(2026-05-28,feat(meituan)):未配 MT_CPS_APP_KEYcoupons/feed/referral-link 直接返空(不再 502),解决新开发机首屏炸的问题。坏副作用:/feed 跟"已配但调用失败"路径在响应上无法区分(都是 200 + 空 items),靠 /healthmt_cps_configured 字段区分。
  • 看广告 4 态 CTA + 本轮冷却(2026-05-29,PR #5):reward-statusround_count + cooldown_until 字段,客户端 CTA 4 态(Normal/Loading/Capped/CoolingDown)+ 弹窗 limit note("本轮看完"/"今日看完")全由后端权威派生,跨设备/重装/杀进程都一致。冷却仅 UX,发奖不受影响。