Files
dealerhub/PROGRESS_PHASE5_FRONTEND_OPS.md

51 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 覆盖