@ -1,6 +1,6 @@
---
---
name: aml-local-refresh
name: aml-local-refresh
description: Refresh the AML local dev stack - git pull AML_Backend, restore the newest AML-local-dev-*.bak into the mssql container as AbpAML, rebuild the httpapi-host image, and restart the API bypassing db-migrator. Use when asked to 更新/还原/重建/重启本地后端环境, "拉最新代码并还原数据库", "restore the latest bak", or when local portal endpoints 500 after the backend moved on.
description: Refresh the AML local dev stack - git pull AML_Backend (and AML_Frontend) , restore the newest AML-local-dev-*.bak into the mssql container as AbpAML, rebuild the httpapi-host image, and restart the API bypassing db-migrator. Also covers running AML_Frontend against that local backend (npm run start:local, login admin, on the Mac or on FG-W11-ICON-DEV via a reverse SSH tunnel). Use when asked to 更新/还原/重建/重启本地后端环境, "拉最新代码并还原数据库", "restore the latest bak", 前端连本地后端/本地登录, 在 Windows 那台跑 AML 前端 , or when local portal endpoints 500 after the backend moved on.
---
---
# AML 本地环境刷新(拉代码 + 还原库 + 重启服务)
# AML 本地环境刷新(拉代码 + 还原库 + 重启服务)
@ -41,6 +41,28 @@ cd /Users/dev/projects/AML/AML_Backend && git status -sb | head -5 && git pull
- `failed to get/store: -25308` 是 macOS keychain 的噪音,不影响 pull。
- `failed to get/store: -25308` 是 macOS keychain 的噪音,不影响 pull。
- 拉完看一眼新迁移:`ls src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations/Migrations/*.cs | grep -v Designer | tail -8`,留着第 4 步核对。
- 拉完看一眼新迁移:`ls src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations/Migrations/*.cs | grep -v Designer | tail -8`,留着第 4 步核对。
### 1b. 同步拉前端代码( AML_Frontend)
后端功能(批量操作、电话区号之类)通常前后端成对提交,只更后端会让前端对不上。前端不在 docker 栈里,这一步**只拉代码**:
```bash
cd /Users/dev/projects/AML/AML_Frontend & & git status -sb | head -5
OLD=$(git rev-parse HEAD) & & git pull --ff-only
git log -1 --format='%h %s'
git diff --name-only $OLD HEAD -- package.json # 有输出 = 依赖变了
```
- 分支是 ** `main` **(不是 dev) 。`origin/dev` 的内容平时会合进 `main` ;拿不准就跑 `git rev-list --count origin/main..origin/dev` ,是 0 就说明 main 已经是最新。工作区有改动同样先问用户。
- `package-lock.json` 被 gitignore 了,所以只能看 `package.json` 有没有变。
- 依赖变了就装一次。系统 Node 是 v24, Angular 11 不支持,所以前端一律通过 **fnm 用 Node 14( x64, 跑在 Rosetta 上)** : `AML_Frontend/.node-version` 写的是 `14` (只在本地,已加进 `.git/info/exclude` )。非交互 shell 里不会自动切版本,要显式写:
```bash
fnm exec --using 14 -- npm install --legacy-peer-deps
fnm exec --using 14 -- npm run build:dev # 可选验证,约 2 分钟
```
`watchpack-chokidar2/fsevents` 的 `gyp ERR!` 是可选依赖编译失败, npm 会跳过, exit 0 就算成功。
### 2. 起基础设施 + 停 host
### 2. 起基础设施 + 停 host
```bash
```bash
@ -133,6 +155,87 @@ curl -s -X POST http://localhost:44331/api/amlPortal/plan/portal/GetPlanList
- host 起不来先看日志: Release 构建只写文件,`docker logs` 是空的 → `docker cp aml-httpapi-host:/app/Logs ./Logs` 。
- host 起不来先看日志: Release 构建只写文件,`docker logs` 是空的 → `docker cp aml-httpapi-host:/app/Logs ./Logs` 。
- exit 214 / `ABP-LIC-0008` = ABP 授权令牌缺失,见 `readme.md` 第 3 节。
- exit 214 / `ABP-LIC-0008` = ABP 授权令牌缺失,见 `readme.md` 第 3 节。
## 前端联调( AML_Frontend 连本地后端)
**登录账号**:宿主层管理员 `admin` ,租户**留空( Host) **。
- 还原 `.bak` 的库(本 skill 的正常流程):密码 ** `1qaz@WSX` **。
- 用 db-migrator 种子新建的库:密码 `1q2w3E*` ( ABP 默认, readme 里也记了这个)。
库里还有几十个租户下也叫 `admin` 的账号,那些是真实客户的,别拿来试。
### 关键约束: issuer 必须是 `http://localhost:44331`
- 后端的 `AuthServer__Authority` / `App__SelfUrl` 固定是 `http://localhost:44331` 。IdentityServer 的 issuer 跟着**请求的主机名**走:用 IP 访问时,发现文档里的 issuer 会变成 `http://192.168.x.x:44331` ,签出来的 token 会被 API 拒掉( 401) 。所以**无论前端跑在哪台机器上,浏览器都必须通过 `localhost:44331` 访问后端**。
- 前端默认的 `environment.ts` 写的是 `https://localhost:44331` ,而本地 host 只提供 http, 所以用默认配置连本地后端是登录不了的。要用 ** `npm run start:local` **: angular.json 里的 `local` 配置会把它换成 `src/environments/environment.local.ts` ,全部指向 http。
- 后端这边已经就绪, 不用改: CORS 放行了 `http://localhost:4200` , `FX_App` client 允许 `password` 授权、不需要 secret、回调地址里有 `http://localhost:4200` 。前端的 `loginMode = 'password'` 用的就是密码模式。
- 排查顺序:先看 `http://localhost:44331/.well-known/openid-configuration` 里的 issuer, 再用 `Origin: http://localhost:4200` 对 `/connect/token` 发一个 OPTIONS 预检(期望 204) , 最后看浏览器 Network 里 `/connect/token` 的响应。
### 在 Mac 上跑
```bash
cd /Users/dev/projects/AML/AML_Frontend
fnm exec --using 14 -- npm run start:local # 编译约 2 分钟,浏览器打开 http://localhost:4200
```
验证配置是否生效:`curl -s http://localhost:4200/main.js | grep -o "issuer: *'[^']* '"`,应该输出 `http://localhost:44331` 。
### 在 FG-W11-ICON-DEV( Windows) 上跑
用户有些测试要在那台机器上做。操作远程机器走 `remote-dev-box` skill( 先 `boxes.sh locate -H FG-W11-ICON-DEV` , IP 会变)。现状:
| 项 | 值 |
|---|---|
| 代码 | `C:/Projects/AML_Frontend` , **不是 git 仓库**,是从 Mac 推过去的快照 |
| Node | 便携版 `C:/Tools/node-v14.21.3-win-x64` (系统里的 Node 22 不动) |
| 启动脚本 | `C:/Tools/start-aml-frontend.cmd` (设好了 PATH 和 4 GB 堆上限,用户双击就能起) |
| 日志 | `C:/Tools/aml-frontend-serve.log` |
**1. 后端:由 Mac 起反向隧道**,让 Windows 上的 `localhost:44331` 通到 Mac 的 docker host:
```bash
ssh -fNT -o ControlPath=none -o ExitOnForwardFailure=yes -R 44331:127.0.0.1:44331 FG-W11-ICON-DEV
```
- 这条 auto mode 不让 Claude 跑,**要请用户自己在提示符里用 `!` 运行**,并提醒他们**整行粘贴**:之前在 `-R` 后面断行,结果报了 `option requires an argument -- R` 。
- `ControlPath=none` 不能省:`~/.ssh/config` 里给这台机器开了 `ControlMaster auto` + `ControlPersist 10m` ,不关的话,转发会挂在 run.sh 的复用连接上, 10 分钟就断。
- Mac 睡眠、断网或重启后隧道会断,重跑即可。关闭:`pkill -f "R 44331"`。
- 验证(在 Windows 上):`Invoke-WebRequest -UseBasicParsing http://localhost:44331/.well-known/openid-configuration`, issuer 应该是 `http://localhost:44331` 。
**2. 更新代码**( Mac 上的前端有新提交,或 start:local 相关文件改了时):把 git 跟踪的文件和未跟踪的新文件一起打包推过去,不带 node_modules:
```bash
cd /Users/dev/projects/AML/AML_Frontend
git ls-files -co --exclude-standard -z | COPYFILE_DISABLE=1 tar --null -T - -czf "$SCRATCH/aml-frontend-src.tgz"
$S/cp.sh push -H FG-W11-ICON-DEV "$SCRATCH/aml-frontend-src.tgz" 'C:/Tools/aml-frontend-src.tgz'
# 远端: tar -xzf C:/Tools/aml-frontend-src.tgz -C C:/Projects/AML_Frontend ,然后删掉 tgz
```
覆盖解压不会删除文件。如果上游删了文件, 要先清掉旧目录( node_modules 可以留着)。
**3. 装依赖**(首次安装,或 package.json 变了):
```powershell
$env:Path = 'C:/Tools/node-v14.21.3-win-x64;' + $env:Path
Set-Location C:/Projects/AML_Frontend
npm install --legacy-peer-deps --no-audit --no-fund --prefer-offline --maxsockets=6 --fetch-retries=5 *> C:/Tools/aml-npm-install.log
```
- 要用 `run_in_background` 跑,首次安装约 17 分钟。
- npm 6 在这台机器上**会假死**:进程还在、和 registry 的连接也还在,但 npm 缓存大小、CPU 时间、日志行数几分钟都不动。所以跑的过程中要隔几分钟查一次这三样,卡住就 `Stop-Process` 掉重跑。已经下载的包都在缓存里,重跑会接着用。看到 `node_modules/.staging` 里的目录数在涨,说明正在解压。
**4. 启动**: SSH 起的进程在 session 0, 用户看不到, 所以要用一次性计划任务在桌面会话里起:
```powershell
schtasks /Create /TN TmpAmlFrontend /TR '"C:\Tools\start-aml-frontend.cmd"' /SC ONCE /ST 23:59 /IT /F
schtasks /Run /TN TmpAmlFrontend
Start-Sleep 8; schtasks /Delete /TN TmpAmlFrontend /F
```
- ** `NODE_OPTIONS=--max_old_space_size=4096` 必须设**( 已经写在启动脚本里) 。Node 14 默认堆上限约 2 GB, 首次编译完会紧接着再构建一轮, 这时会 `JavaScript heap out of memory` , ng serve 直接退出。
- 首次编译约 4– 5 分钟。dev server ** 构建期间会挂住请求**, `Invoke-WebRequest` 看起来像超时,不是端口问题。日志最后一行如果还是 `Generating browser application bundles...` ,就继续等。
- 验证:日志里有 `Compiled successfully` ,且之后没有 `FATAL` / `npm ERR` ; `http://127.0.0.1:4200/` 返回 200; `main.js` 里的 issuer 是 `http://localhost:44331` 。起来一分钟后再查一次,前面那次 OOM 就是在第二轮构建时才崩的。
- 用户在那台机器的浏览器里打开 `http://localhost:4200` 登录。关掉桌面上那个「AML Frontend (start:local)」窗口就停了。
## 报告给用户
## 报告给用户
刷新完说清楚四件事:拉到的 commit、用的 .bak 文件名、库里的数量(表 / Plans / Editions / Tenants) 、以及冒烟结果。
刷新完说清楚五件事:后端拉到的 commit、前端拉到的 commit( 及 package.json 是否变了) 、用的 .bak 文件名、库里的数量(表 / Plans / Editions / Tenants) 、以及冒烟结果。