Files
juzi/docs/HANDOFF-2026-11-02.md
T
xsl 43a5373233 docs: add development-machine handoff and server deploy configs
换开发机继续开发。新机器只需要拉仓库 + 自备工具链 + 单独拷贝两个机密文件,
服务器/聚石塔/SAE 全部沿用,不需要重建。

- docs/HANDOFF-2026-11-02.md:开发机交接(环境、仓库地图、三套测试、
  本地怎么跑、云端资源清单、上线方式、11 条关键结论、9 项待办、故障对照表)
- deploy/:服务器侧配置入库(原先只存在于机器上)
  - systemd/juzi-taobao.service(18081,独立数据目录与凭据文件)
  - nginx/tb-location.conf(/tb/ 反代 + 只放行聚石塔 NAT EIP)
  - add-tb-nginx.sh(幂等插入,先备份,nginx -t 通过才 reload)
  - README.md(重建与回滚步骤)
- tools/env-java.ps1:优先用仓库内便携工具链,缺失时回退 JAVA_HOME/PATH,
  换机器不用再下便携 JDK/Maven
- README.md:交接文档入口更新
2026-11-01 23:34:26 +08:00

16 KiB
Raw Blame History

开发交接 —— 换一台开发机继续做(2026-11-02)

写给:在新 Windows 机器上接手的人(或未来的 agent) 不涉及:服务器 / 聚石塔 / SAE 都不用重建,云端资源全部现成可用 上一份:HANDOFF-2026-11-01.md(那一轮只到「链路打通 + Java MVP」,UI 和真机测肤是这一轮做的)


0. 一句话状态

真机全链路已跑通:淘宝小程序 → 云网关(AppKey 35486228)→ 聚石塔云应用 1me-net → 私网 CLB → SAE nnn(只做透传)→ 聚石塔 NAT 出网(EIP 47.92.113.176)→ https://1me.xajuzi.com/tb/ → 现有 H5 的 Node 服务 → 旷视 Face++,三视图拍摄后报告正常返回。

小程序五个页面的 UI 已按 H5 重做(像素级对齐,见下)。剩下的是相机组件验证和一批工程化工作,清单在第 8 节。


1. 新机器准备

1.1 必装

工具 版本 用途
Git 任意近期版本 拉代码
Node.js 18+(推荐 20/22) taobao/ 测试、h5/ 本地跑、零依赖
JDK 17 backend-java/ 编译与测试
Maven 3.9.x 同上
淘宝小程序开发者工具 最新 真机预览(模拟器不支持云应用 SDK)
PowerShell 7(可选) 7.x 仓库里的脚本按 pwsh 语法写

1.2 拉代码

git clone https://git.xiangsilian.com/xsl/juzi.git
cd juzi

远端证书有效期到 2027-01-29;凭据失效时重新配置 Git 凭据管理器。

1.3 小程序依赖(必做,否则真机报 Cannot find module)

cd taobao
npm ci

@tbmp/mp-cloud-sdk 固定 1.5.10,只有这一个运行期依赖。

1.4 工具链

仓库自带 tools/env-java.ps1,查找顺序:仓库内便携工具链 → 环境变量 → PATH。

Set-ExecutionPolicy -Scope Process Bypass
. .\tools\env-java.ps1      # 输出 JAVA_HOME / MAVEN_HOME / java -version
  • 用系统安装的 JDK 17 + Maven 即可,不需要再下便携版
  • 想复原老机器的布局:把 JDK 放 tools/jdk17/、Maven 放 tools/maven/apache-maven-3.9.9/(这两个目录 gitignore)

1.5 必须单独拷贝的机密文件(不在 git 里)

文件 内容 没有会怎样
backend-java/src/main/resources/application-local.yml 淘宝 AppKey/AppSecret + mode: forward + forward-base JAR 里没有 AppKey/Secret,/session 一定 401
reference/facepp-skinanalyze/credentials.env 旷视 FACEPP_API_KEY/SECRET h5/server.js 启动即 exit(1)
SSH 私钥 免密登录 ubuntu@1me.xajuzi.com 无法部署 Node 侧 / 看日志
# 从老机器拷(示例)
scp <老机器>:D:/juzi/backend-java/src/main/resources/application-local.yml .\backend-java\src\main\resources\
scp <老机器>:D:/juzi/reference/facepp-skinanalyze/credentials.env .\reference\facepp-skinanalyze\

新机器要能 ssh 服务器的话:ssh-keygen -t ed25519 后把公钥追加到服务器 ~/.ssh/authorized_keys。

老机器若已不可用:AppSecret / 旷视 key 找项目负责人索取,或在开放平台重置(重置后记得同步更新服务器 /etc/juzi/taobao.env 与 JAR)。

1.6 淘宝 IDE 的一个已知坑(Windows)

老机器上 IDE 曾因 wmic 缺失打不开,用 tools/fix-taobao-ide-wmic.ps1 生成过一个 shim(C:\Users\<你>\.local\bin\wmic.cmd)。新机器如果 IDE 报 install miniapp extension fail: ... wmic ...,跑这个脚本。


2. 仓库地图

juzi/
├── taobao/                    淘宝小程序(当前主战场)
│   ├── config.js              ★ 环境/传输配置(cloud+tower+test、assetBase)
│   ├── app.acss               ★ 全局设计 token(对齐 H5 的 .btn-primary/.card/.chev/.popup)
│   ├── pages/
│   │   ├── splash/            启动页(登录、隐私弹窗、开发版入口)
│   │   ├── profile/           档案填写(出生/性别/地区/肤质轮播)
│   │   ├── camera/            拍照页(蒙版取景 or 系统相机兜底)
│   │   ├── report/            报告页(环形分、7 视角、叠加层、标记点)
│   │   ├── history/           历史报告
│   │   ├── mvp/               连通性调试页(ping/whoami/echo)
│   │   └── camtest/           ★ 相机组件冒烟页(只放 <camera>,判断组件是否可用)
│   ├── utils/
│   │   ├── transport.js       云网关/direct 两种传输 + 信封解包
│   │   ├── api.js             9 个接口封装(challenge/session/me/photo/skin-analyze/…)
│   │   ├── permissions.js     ★ 权限(scope 前缀、诊断 diagnose())
│   │   ├── image.js           1280 长边 + JPEG q0.88 压缩
│   │   ├── voice.js           语音播报(异常静默)
│   │   └── report-model.js    payload → 报告页 data
│   └── test/                  20 个 node:test 用例
├── h5/                        ★ 真正的测肤后端(Node,零依赖)
│   ├── server.js              入口:Face++ 调用、评分、报告、admin
│   ├── lib/taobao-*.js        ★ 淘宝云网关路由/验签/会话(关键算法在这里)
│   ├── js/skin-score.js       评分引擎(6 类 → 3 维,4:3:3 加权)
│   └── test/                  一堆独立测试脚本(没有统一 runner)
├── backend-java/              SAE 上的透传层(Spring Boot 3.5.6 / Java 17)
│   ├── src/main/java/com/juzi/mvp/api/
│   │   ├── TaobaoForwardController.java   ★ mode=forward 时字节级透传
│   │   ├── TaobaoEnvelope.java            客户端要的 data.ok + data.http_status
│   │   ├── TaobaoAuthController.java      native 模式的登录接口(当前未启用)
│   │   └── TaobaoSessionService.java      challenge + Bearer token
│   └── src/main/java/com/juzi/mvp/gateway/TaobaoSignatureVerifier.java  验签算法
├── deploy/                    ★ 服务器侧配置(systemd / nginx / 安装脚本)
├── docs/                      交接与实施文档(本文件所在)
└── tools/                     构建与素材脚本

3. 三套测试

# 1) 小程序:20 个用例
cd taobao ; npm test

# 2) Java:11 个用例(含验签向量的回归测试)
cd backend-java ; mvn test

# 3) H5 单测(独立脚本,逐个跑)
node h5/test/taobao-auth.js        # 网关签名,必须 PASS

改动提交前请保证:taobao 20/20 + backend-java 11/11。老机器最后一次全绿是在 fed5293。

taobao/test/frontend.test.cjs 会用 vm 真跑页面 JS,页面 data 字段改名要同步改测试。


4. 本地怎么跑

4.1 H5 后端(Node,测肤真正的实现)

cd h5
$env:PORT=8099 ; $env:HOST='127.0.0.1' ; $env:JUZI_ENTRY_MODE='state'
$env:JUZI_DATA_ROOT='..\temp\h5-data'
node server.js
# http://127.0.0.1:8099/api/health → {"ok":true}

启动时缺旷视 key 会直接退出。只想调 UI/接口时给假值即可(真实检测会失败,但路由可用):

$env:SKIN_API_KEY='dummy' ; $env:SKIN_API_SECRET='dummy'

4.2 Java(SAE 那一层)

. .\tools\env-java.ps1
cd backend-java
mvn spring-boot:run          # 或 mvn -DskipTests package 后 java -jar target\*.jar
curl.exe -X POST -H "Content-Type: application/json" -d "{}" http://127.0.0.1:8080/api/taobao/ping
  • 默认 mode: native(Java 自己实现登录,便于单独调接口)
  • 部署用的 application-local.yml 里写的是 mode: forward
  • 本地想看透传:$env:TAOBAO_MODE='forward' + $env:TAOBAO_FORWARD_BASE='http://127.0.0.1:8099'

4.3 小程序

  1. 淘宝 IDE 导入仓库里的 taobao/(mini.project.json 的 appid 留空,以 IDE 账号为准)
  2. 确认 IDE 当前小程序是 35486228(1me 肌肤状态检测)
  3. config.js 保持 transport: 'cloud' / cloudType: 'tower' / cloudEnv: 'test'
  4. 顶部「预览」→ 手机淘宝扫码(模拟器不支持 cloud.application.httpRequest)
  5. 启动页右上角有三个开发版入口(environment !== 'production' 时才显示):
入口 作用
权限诊断 打印 my.canIUse、getSetting 的 authSetting、authorize 的原始返回(真机上唯一能看到这些的地方)
相机组件测试 整页只有一个 <camera>,用来判断组件是否可用
SAE MVP 连通性 ping/whoami/echo,看 transport:"gateway"、server:"java"

5. 云端资源(只读,无需重建)

资源 值
开放平台应用 1me 肌肤状态检测,AppKey 35486228
旧应用(废弃) 1me肌肤检测 35479221 —— 不要再用它的 Secret
聚石塔云应用 1me-net,ID 62829,默认应用
私网 CLB lb-k2j324dwux1svaf2akwqx / 192.168.65.185:80
SAE 应用 nnn,cn-zhangjiakou:my-namespace
代码包 taobao-mvp-backend-0.0.4-forward.jar(环境变量全空,配置都在包里)
VPC / vSwitch vpc-8vb5mcvenp8jwa1roqcsa / vsw-8vbna5zb2rq03gaeiymch(可用区 A)
NAT 出口 EIP 47.92.113.176(nginx /tb/ 白名单按它放行)
服务器 ubuntu@1me.xajuzi.com,Node v20.20.2
生产 H5 https://1me.xajuzi.com/state/ → juzi-h5.service(8080)
红书渠道 https://1me.xajuzi.com/rednote/ → juzi-rednote.service(8081)
淘宝专用 https://1me.xajuzi.com/tb/ → juzi-taobao.service(18081)

6. 改完怎么上线

6.1 小程序

IDE 编译 → 预览(自测)→ 「上传」发版本。不需要碰服务器。

6.2 Java(SAE)

. .\tools\env-java.ps1 ; cd backend-java
mvn clean package          # 测试会自动跑
# 产物 target\taobao-mvp-backend-0.0.4-forward.jar

SAE 控制台 → nnn → 部署应用 → 代码包部署 → 上传 JAR(版本号要和上次不同,否则会被当成同一个版本)→ 环境变量保持全空。

6.3 Node(/tb 实例)

见 deploy/README.md 第 1 节。核心三步:

tar -czf temp/juzi-h5.tgz --exclude=h5/data --exclude=h5/test -C . h5
scp temp/juzi-h5.tgz ubuntu@1me.xajuzi.com:/tmp/
ssh ubuntu@1me.xajuzi.com "tar -xzf /tmp/juzi-h5.tgz -C /home/ubuntu/juzi-tb && sudo systemctl restart juzi-taobao"

⚠️ 不要动 /home/ubuntu/juzi(生产 H5)和 /home/ubuntu/juzi-rednote。我们那份是独立拷贝 /home/ubuntu/juzi-tb。


7. 这一轮的关键结论(踩过的坑,别重复踩)

  1. 云网关签名算法:真实请求不带 sign_method,缺省等价于 MD5(secret + content + secret)(content = 排序后的 key+value 拼接 + 原始 body 字节)。之前按 MD5(content + secret) 实现,是 10 月底那个「signature mismatch」的真因。改在 h5/lib/taobao-auth.js。
  2. 淘宝的 scope 是带前缀的 scope.camera / scope.album;传裸名 camera 返回 {"errorCode":"5022","errorMessage":"Scope:camera信息不存在"}。
  3. <camera> 组件在真机上会让整页崩溃,且 my.canIUse('camera') 返回 yes 是假阳性。当前默认走系统相机(config.nativeCamera = false)。怀疑原因是相机里嵌了微信专有的 <cover-view>,已改成兄弟节点 + 普通 view 覆盖,并加了 pages/camtest 冒烟页——这个还没在真机验证,是新机器的第一件事。
  4. 网关限制:单请求 10 秒 / 128KB。所以 skin-analyze 必须 202 + 1 秒轮询(最长 90 秒),不能同步等旷视。
  5. 旷视 Face++:正式 key 有并发窗口,必须串行 + 4 秒间隔;60 秒超时,失败/5xx/并发超限重试 1 次;返回值含 face_maps,4000px 素材时约 3.2MB(真实链路客户端压到 1280,约 200–300KB)。
  6. /api/taobao/reports 详情带 3 张 base64 照片,历史报告页有超时风险(网关大响应未验证)。
  7. 会话/任务全在内存:SAE 只能单副本;juzi-taobao 重启后登录态与进行中的任务都会丢。
  8. 没有任何清理策略:每次检测在磁盘留 10–12MB,长期必须换 OSS。
  9. 转发必须字节级透传:签名覆盖原始 body 和 query,Java 一旦重新序列化 JSON 就会 401。
  10. 生产那台 Node 是旧代码,没有 /api/taobao/*;我们另外起 /home/ubuntu/juzi-tb(18081)跑新代码,用 nginx /tb/ 分流。
  11. 图片资源走 https://1me.xajuzi.com/state/assets/(config.assetBase)。之前是 127.0.0.1:18180,真机上全部加载失败。

8. 待办(建议顺序)

# 事项 说明
1 真机验证 pages/camtest 能出实时画面 → 把 config.nativeCamera 改 true,拍照页立刻有蒙版取景;仍然崩 → 维持系统相机
2 /reports 详情瘦身 现在透传 3 张 base64 原图(约 0.5MB+),改缩略图或 OSS URL
3 存储工程化 照片/原始 JSON/记录 → OSS + RDS;现在全在容器/单机磁盘,无清理
4 旷视请求裁剪 return_maps 请求 10 层但报告只用 6 层,可少传 4 层省带宽与落盘
5 WebP 转码(可选) 实测:6 层图 WebP q80 省 54%,叠 50% 缩放省 84%;先真机验证 <image> 支持 WebP data URL
6 密钥治理 application-local.yml / /etc/juzi/taobao.env 里的 AppSecret、JAR 内嵌 Secret → 改 KMS/保密字典,并重置一次 AppSecret
7 Java 端可选迁移 mode=native 的登录接口已写好并测过(4 个用例),可把 auth 从 Node 搬到 Java;测肤仍留在 Node
8 仓库收拾 sdk-java-35479221/、三个 .pptx、tools/build_taobao_proposal_*.py 仍未跟踪,建议加 ignore 或删除
9 启用签名校验(Java 侧) 当前 forward 模式下由 Node 验签;若切 native 或要 /ping 也验签,把 verify-sign 打开即可(算法已修复)

9. 故障对照表

现象 原因 处理
真机 cloud init failed IDE 当前 app 不是 35486228 / 云应用没设默认 确认 IDE 账号与 AppKey
淘宝身份校验失败,请重新授权登录 云网关签名不匹配 检查服务器 /etc/juzi/taobao.env 的 AppSecret;算法见第 7 节第 1 条
请先配置淘宝云应用和 HTTPS 服务地址 cloudType 不是 tower 或 transport 不是 cloud 看 config.js
页面一片灰没有图 assetBase 指向 127.0.0.1 应为 https://1me.xajuzi.com/state/assets/
点拍照整页崩(「系统遇到一点问题」) <camera> 组件 保持 nativeCamera: false,用系统相机/相册
报告页白屏 payload 为空或 report-model 抛错 看启动页「SAE MVP 连通性」是否 server:"java"
SAE 侧 上游 403 容器出口 IP 不在 nginx /tb/ 白名单 curl -s https://myip.ipip.net 取新 IP,改 nginx 后 reload
Cannot find module '@tbmp/mp-cloud-sdk' 没装依赖 / IDE 没构建 npm npm ci,IDE「工具 → 构建 npm」
Java 打包报找不到 application-local.yml 机密文件没拷过来 见 1.5

10. 交接检查清单

  • npm ci(taobao)跑过
  • tools/env-java.ps1 能加载出 JDK17 + Maven
  • application-local.yml 与 credentials.env 已从老机器拷来
  • taobao 20/20、backend-java 11/11、node h5/test/taobao-auth.js PASS
  • IDE 打开 taobao/ 并确认 AppKey 是 35486228
  • 真机预览能看到图片(说明资产域名通)
  • 真机点「权限诊断」→ authorize(scope.camera)=ok
  • 真机点「相机组件测试」→ 记录结果,决定 nativeCamera 开关
  • 能 ssh ubuntu@1me.xajuzi.com,systemctl is-active juzi-taobao 为 active

给接手者的第一句话:先按第 1 节把机器装好、把两个机密文件拷过来,跑通三套测试;然后去真机验 camtest——那是唯一还悬着的技术问题,也决定拍照页最终形态。