Files
dealerhub/PROGRESS_PHASE5_FRONTEND_OPS.md
T

4.9 KiB
Raw Blame History

dealerhub · 三项后续落地报告(真实渠道对接 / 调度任务 / Vue3 前端)

目标:完成 PROGRESS_PHASE4 遗留三项:① 抖音/1688 电商适配器真实对接(平台签名 + Token 刷新); ② Dramatiq + Redis 预警/拉单定时调度(服务器 worker 常驻);③ Vue3 前端并同源部署。


一、真实电商适配器(apps/channel)

1. 平台签名(apps/channel/signing.py,含金标准测试向量)

  • 抖店开放平台:参数按 key 升序拼 k1v1k2v2...,首尾拼 app_secret,MD5 大写
  • 1688 Ocean 协议:HMAC-SHA256(secret, 排序拼接串) 大写十六进制;URL 路径段参与签名(/param2/1/{api}/{appKey} + _aop_timestamp/_aop_signature)

2. 真实拉单与归一化(apps/channel/adapters.py)

  • DouyinChannelAdapter.fetch_orders:POST openapi-fxg.jinritemai.com/order/searchList(method/app_key/access_token/param_json/timestamp/v/sign),金额分→元,买家/收货人/明细(external_sku_id 优先映射商品编码)全部归一化
  • Alibaba1688Adapter.fetch_orders:GET gw.open.1688.com/.../com.alibaba.trade/alibaba.trade.getBuyerOrderList,baseInfo+productItems 归一化(行金额反算单价)
  • Token 自动刷新:ensure_fresh_token 在 token 临期(<1 天)自动调 /oauth2/refresh_token(抖店)与 /system/oauth2/refreshToken(1688)并落库
  • push_stock:抖店 product.stockNum/update;1688 未接入如实返回 False
  • Mock 回退:未配置 app_key 的店铺自动回退模拟数据(开发零依赖);HTTP 缝隙 _http_post/_http_get 便于单测注入
  • 测试:tests/test_channel_adapters.py 9 例(签名金标准向量、真实调用归一化、Token 刷新、Mock 回退、1688 参数构造、归一化结果端到端转销售单)

二、Dramatiq + Redis 调度(worker 常驻容器)

1. 架构

  • config/broker.py:TASK_BROKER=redis(默认)→ RedisBroker(REDIS_URL);stub → StubBroker(测试);核心修复:apps/core/apps.py ready() 启动即安装全局 broker——dramatiq 默认 get_broker() 惰性创建"无 url 的 localhost RedisBroker"且不读 REDIS_URL,必须在任何 actor import 剝始化
  • config/dramatiq.py:worker 入口(dramatiq config.dramatiq),先 django.setup(),再注册 actors + @cron 周期任务
  • Actors:apps/notify/tasks.py(单租户/全租户预警扫描)、apps/channel/tasks.py(单店铺/全店铺自动拉单)
  • 周期任务(dramatiq-crontab):0 8 * * * 全租户预警扫描;0 2 * * * 有凭证店铺自动拉单
  • docker-compose.yml 新增 worker 服务(同镜像,dramatiq 命令,接入 pg-shared + dsp-net 复用无密码 redis dsp-redis:6379/2;healthcheck 覆盖为 kill -0 1——镜像内 curl:8000 检查对 worker 无意义)

2. 测试与线上验证

  • tests/test_tasks.py 5 例:actor 注册、StubBroker 入队断言、直接调用同步执行验证预警/拉单结果
  • 线上(192.168.5.7):backend/worker 双容器 healthy;从 backend send() 预警扫描与渠道拉单任务,worker 日志确认两条任务均被消费执行

三、Vue3 前端(frontend/,同源部署)

1. 技术栈与结构

  • Vite 5 + Vue 3.5 + Vue Router 4(hash 模式)+ Pinia + Element Plus + Axios
  • base: '/static/':构建产物由 Django whitenoise 同源托管,/ 由 config/urls.py:spa_index 返回 index.html
  • 12 个页面:登录、经营大盘(KPI+销售/客户排行)、商品、库存、销售单、采购单、记账凭证(嵌套分录制单+借贷平衡实时提示+过账/作废)、应收、应付、财务报表(科目余额表试算平衡/资产负债表恒等/利润表/明细账 四标签页)、电商渠道(店铺接入+拉单+订单列表)、消息预警(扫描+已读)、开放平台(API Key 签发,明文仅展示一次)
  • Axios 拦截器统一注入 JWT + X-Tenant-Id,401 自动跳登录

2. 构建与部署验证

  • npm run build 成功(本地 Node 22);dist 上传服务器 → backend/frontend_dist/ → Dockerfile COPY frontend_dist/ /app/frontend_dist/ 打进镜像
  • Playwright 真实浏览器验证(http://192.168.5.7:18050/):登录 alice → 大盘 KPI(销售额 336/采购 640/库存估值 416)与双排行榜渲染 → 凭证页 9 张自动凭证列表 → 财务报表页"✓ 试算平衡"+ 科目余额表(合计借=贷 900/900、期末 732/732)截图确认

四、验证汇总

  • 本地 pytest:103 passed(含新增 9 适配器 + 5 调度任务用例)
  • 线上容器:backend + worker 双 healthy;任务队列端到端(enqueue → worker 消费)实测通过;SPA/静态资源/ping 全 200
  • 关键踩坑记录:① dramatiq 默认 broker 不读 REDIS_URL,须在 app.ready() 安装;② worker 入口模块必须先 django.setup() 再注册模型 actor;③ 镜像内 HEALTHCHECK 会被同镜像 worker 继承(curl 8000 永远失败),需 compose 覆盖