换开发机继续开发。新机器只需要拉仓库 + 自备工具链 + 单独拷贝两个机密文件, 服务器/聚石塔/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:交接文档入口更新
16 KiB
开发交接 —— 换一台开发机继续做(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 小程序
- 淘宝 IDE 导入仓库里的
taobao/(mini.project.json的appid留空,以 IDE 账号为准) - 确认 IDE 当前小程序是 35486228(
1me 肌肤状态检测) config.js保持transport: 'cloud'/cloudType: 'tower'/cloudEnv: 'test'- 顶部「预览」→ 手机淘宝扫码(模拟器不支持
cloud.application.httpRequest) - 启动页右上角有三个开发版入口(
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. 这一轮的关键结论(踩过的坑,别重复踩)
- 云网关签名算法:真实请求不带
sign_method,缺省等价于MD5(secret + content + secret)(content= 排序后的key+value拼接 + 原始 body 字节)。之前按MD5(content + secret)实现,是 10 月底那个「signature mismatch」的真因。改在 h5/lib/taobao-auth.js。 - 淘宝的 scope 是带前缀的
scope.camera/scope.album;传裸名camera返回{"errorCode":"5022","errorMessage":"Scope:camera信息不存在"}。 <camera>组件在真机上会让整页崩溃,且my.canIUse('camera')返回yes是假阳性。当前默认走系统相机(config.nativeCamera = false)。怀疑原因是相机里嵌了微信专有的<cover-view>,已改成兄弟节点 + 普通 view 覆盖,并加了pages/camtest冒烟页——这个还没在真机验证,是新机器的第一件事。- 网关限制:单请求 10 秒 / 128KB。所以
skin-analyze必须 202 + 1 秒轮询(最长 90 秒),不能同步等旷视。 - 旷视 Face++:正式 key 有并发窗口,必须串行 + 4 秒间隔;60 秒超时,失败/5xx/并发超限重试 1 次;返回值含
face_maps,4000px 素材时约 3.2MB(真实链路客户端压到 1280,约 200–300KB)。 /api/taobao/reports详情带 3 张 base64 照片,历史报告页有超时风险(网关大响应未验证)。- 会话/任务全在内存:SAE 只能单副本;
juzi-taobao重启后登录态与进行中的任务都会丢。 - 没有任何清理策略:每次检测在磁盘留 10–12MB,长期必须换 OSS。
- 转发必须字节级透传:签名覆盖原始 body 和 query,Java 一旦重新序列化 JSON 就会 401。
- 生产那台 Node 是旧代码,没有
/api/taobao/*;我们另外起/home/ubuntu/juzi-tb(18081)跑新代码,用 nginx/tb/分流。 - 图片资源走
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 + Mavenapplication-local.yml与credentials.env已从老机器拷来taobao20/20、backend-java11/11、node h5/test/taobao-auth.jsPASS- IDE 打开
taobao/并确认 AppKey 是 35486228 - 真机预览能看到图片(说明资产域名通)
- 真机点「权限诊断」→
authorize(scope.camera)=ok - 真机点「相机组件测试」→ 记录结果,决定
nativeCamera开关 - 能
ssh ubuntu@1me.xajuzi.com,systemctl is-active juzi-taobao为 active
给接手者的第一句话:先按第 1 节把机器装好、把两个机密文件拷过来,跑通三套测试;然后去真机验 camtest——那是唯一还悬着的技术问题,也决定拍照页最终形态。