Skip to content

Commit e594c22

Browse files
Optimize P0-P2 stability, performance, and packaging (#58)
* docs: add p0-p2 optimization execution design Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * docs: refine p0-p2 optimization acceptance criteria Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * docs: split large component optimization items Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * docs: add p0-p2 optimization implementation plan Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * chore: ignore local worktree directory Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * ci: align go workflow version Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * ci: fix backend smoke health check Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * ci: use npm ci for release builds Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: limit reference image upload size Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: summarize provider response logs Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: add backend server timeouts Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: tighten worker timeout handling Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * perf: virtualize template market grid Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * perf: gate image url diagnostics Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * perf: narrow zustand subscriptions Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * perf: slim persisted history cache Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * chore: align web frontend version strategy Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: correct nginx upgrade headers Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: improve docker health checks Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * refactor: consolidate provider config api Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * refactor: split template market components Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * refactor: split reference image upload logic Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * refactor: split settings modal sections Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * chore: clarify react query usage Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * perf: lazy load desktop locales Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: tighten tauri asset security Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: restore template market unified scrolling Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * chore: bump version to 2.8.4 Also adds a local Tauri packaging script that builds the sidecar and skips updater signing for developer machines without release secrets. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * docs: document local packaging and template scrolling Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: consolidate reference image validation Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: tighten tauri runtime typing Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: type prompt optimization errors Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: expand review callback handlers Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: name template grid layout constants Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * ci: prebuild smoke test server Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: avoid dynamic locale loader indexing Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: normalize validated reference paths Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: use typed drag image cache field Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: avoid clipboard item index access Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: harden template grid callbacks Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * docs: document drag cache guardrails Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: mark validated ref path open safe Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: type text input target result Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: wrap template modal callbacks Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: clarify editable paste target guard Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: inline editable paste target guard Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: inline editable paste condition Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * fix: avoid html constructors in paste guard Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent 5e32fa8 commit e594c22

49 files changed

Lines changed: 3057 additions & 710 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/pr-check.yml

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
- name: Setup Go
3434
uses: actions/setup-go@v5
3535
with:
36-
go-version: '1.21'
36+
go-version-file: './backend/go.mod'
3737
cache-dependency-path: './backend/go.sum'
3838

3939
# Go 代码格式检查
@@ -127,7 +127,7 @@ jobs:
127127
npm run build
128128
129129
# ========================================
130-
# Job 3: 烟雾测试(可选)
130+
# Job 3: 烟雾测试
131131
# ========================================
132132
smoke-test:
133133
name: Smoke Test
@@ -142,7 +142,7 @@ jobs:
142142
- name: Setup Go
143143
uses: actions/setup-go@v5
144144
with:
145-
go-version: '1.21'
145+
go-version-file: './backend/go.mod'
146146

147147
# 启动后端并验证健康检查
148148
- name: Start backend and health check
@@ -154,9 +154,14 @@ jobs:
154154
cp .env.example .env
155155
fi
156156
157+
# 先编译,避免首次 go run 下载/编译依赖占用健康检查等待时间
158+
echo "编译后端服务..."
159+
go build -o /tmp/banana-pro-server ./cmd/server/main.go
160+
157161
# 启动后端(后台运行)
158162
echo "启动后端服务..."
159-
go run cmd/server/main.go &
163+
LOG_FILE=/tmp/banana-pro-server.log
164+
DISABLE_STDIN_MONITOR=1 /tmp/banana-pro-server > "$LOG_FILE" 2>&1 &
160165
SERVER_PID=$!
161166
162167
# 等待后端启动(最多30秒)
@@ -169,10 +174,15 @@ jobs:
169174
exit 1
170175
fi
171176
172-
# 检查健康检查接口(假设有 /health 或 /api/health)
173-
if curl -sf http://localhost:8080/health > /dev/null 2>&1 || \
174-
curl -sf http://localhost:8080/api/health > /dev/null 2>&1; then
175-
echo "✅ 后端启动成功(${i}秒)"
177+
HEALTH_PORT=$(grep -m1 -oE 'SERVER_PORT=[0-9]+' "$LOG_FILE" | cut -d= -f2 || true)
178+
if [ -z "$HEALTH_PORT" ]; then
179+
sleep 1
180+
continue
181+
fi
182+
183+
# 检查标准健康检查接口
184+
if curl -sf "http://localhost:${HEALTH_PORT}/api/v1/health" > /dev/null 2>&1; then
185+
echo "✅ 后端启动成功(${i}秒,端口 ${HEALTH_PORT})"
176186
177187
# 测试其他关键接口(可选)
178188
# curl -sf http://localhost:8080/api/status
@@ -187,17 +197,17 @@ jobs:
187197
188198
# 超时
189199
echo "❌ 后端启动超时(${MAX_WAIT}秒)"
200+
cat "$LOG_FILE" || true
190201
kill $SERVER_PID 2>/dev/null || true
191202
exit 1
192-
continue-on-error: true
193203
194204
# ========================================
195205
# Job 4: PR 总结(可选)
196206
# ========================================
197207
pr-summary:
198208
name: PR Summary
199209
runs-on: ubuntu-latest
200-
needs: [backend-check, frontend-check]
210+
needs: [backend-check, frontend-check, smoke-test]
201211
if: always()
202212

203213
steps:
@@ -224,7 +234,7 @@ jobs:
224234
| **前端检查** (React) | ${statusEmoji[frontend] || '❓'} ${frontend} |
225235
| **烟雾测试** | ${statusEmoji[smoke] || '❓'} ${smoke} |
226236
227-
${backend === 'success' && frontend === 'success' ? '### ✅ 所有检查通过,可以合并!' : '### ⚠️ 请修复上述问题后再合并'}
237+
${backend === 'success' && frontend === 'success' && smoke === 'success' ? '### ✅ 所有检查通过,可以合并!' : '### ⚠️ 请修复上述问题后再合并'}
228238
229239
---
230240
*由 GitHub Actions 自动生成*

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: 安装 Go 环境
1919
uses: actions/setup-go@v5
2020
with:
21-
go-version: '1.21'
21+
go-version-file: './backend/go.mod'
2222
cache-dependency-path: './backend/go.sum'
2323

2424
- name: 后端代码检查
@@ -119,7 +119,7 @@ jobs:
119119
- name: 安装 Go 环境
120120
uses: actions/setup-go@v5
121121
with:
122-
go-version: '1.21'
122+
go-version-file: './backend/go.mod'
123123
cache-dependency-path: './backend/go.sum'
124124

125125
- name: 生成 Release Notes
@@ -148,7 +148,7 @@ jobs:
148148
fi
149149
150150
- name: 安装前端依赖
151-
run: npm install
151+
run: npm ci
152152
working-directory: ./desktop
153153

154154
- name: 导入 Apple 签名证书 (macOS)

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,4 @@ templates_nano_banana_pro.json
109109
TEMPLATE_MARKET_PLAN.md
110110
.sisyphus/
111111
.codex/
112+
.worktrees/

CLAUDE.md

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
```bash
1818
# 后端
1919
cd backend && go run cmd/server/main.go # 启动后端 (默认 :8080)
20+
curl http://localhost:8080/api/v1/health # 标准健康检查接口
2021
make build # 编译
2122
make run # 运行
2223

@@ -27,13 +28,15 @@ cd desktop && npm install && npm run tauri dev
2728
cd frontend && npm install && npm run dev
2829

2930
# 打包发布
30-
cd desktop && npm run tauri build # 本地构建桌面安装包
31+
cd desktop && npm run tauri:build:local # 本地构建桌面安装包(先生成 Go sidecar,跳过 updater 签名)
3132

3233
# Docker 部署 (Web 版)
3334
docker compose -p banana-pro up -d
3435

3536
# 发布流程
3637
git tag v2.8.0 && git push origin v2.8.0 # 触发 GitHub Actions 自动构建
38+
# Release CI
39+
cd desktop && npm ci # 发布构建使用 lockfile 严格安装依赖
3740
```
3841

3942
## 项目结构
@@ -60,7 +63,7 @@ backend/ # Go 后端 (Sidecar)
6063
6164
desktop/ # Tauri 桌面端
6265
├── src/
63-
│ ├── components/ # 37 React 组件
66+
│ ├── components/ # 38 React 组件
6467
│ ├── store/ # 8 个 Zustand Store (configStore migration v19)
6568
│ ├── hooks/ # 6 个自定义 Hook
6669
│ ├── services/ # 8 个 API 服务文件
@@ -72,7 +75,7 @@ desktop/ # Tauri 桌面端
7275
│ └── capabilities/ # Tauri 权限声明
7376
└── package.json
7477
75-
frontend/ # 独立 Web 前端 (v2.5.2, 非 Tauri)
78+
frontend/ # 独立 Web 前端 (非 Tauri,Docker 构建入口;版本跟随 desktop/package.json)
7679
```
7780

7881
## 技术栈
@@ -103,10 +106,14 @@ frontend/ # 独立 Web 前端 (v2.5.2, 非 Tauri)
103106

104107
1. **asset:// 协议**:桌面端注册原生资源协议,绕过 HTTP 栈加载本地图片,速度提升 300%
105108
2. **Sidecar 模式**:Go 后端作为 Tauri sidecar 运行,Tauri 退出时自动清理进程
106-
3. **Worker 池**:6 workers + 100-slot 队列,per-provider 超时,panic 自动恢复
109+
3. **Worker 池**:6 workers + 100-slot 队列,per-provider 超时,provider 调用在 worker goroutine 内执行并带 panic 自动恢复
107110
4. **IPC 优化**:前后端只传文件路径,二进制数据通过 asset:// 协议直读
108111
5. **Prompt 优化**:singleflight 去重 + 10min 缓存,支持 text/json 两种输出模式
109-
6. **模板市场**:内嵌 JSON + 远程 GitHub Raw + 本地缓存三层策略,24h 自动刷新
112+
6. **模板市场**:内嵌 JSON + 远程 GitHub Raw + 本地缓存三层策略,24h 自动刷新;桌面端模板网格使用 `react-window` 虚拟化渲染,避免 935+ 模板一次性挂载
113+
7. **服务端连接超时**:Go HTTP Server 使用 5s ReadHeaderTimeout、30s ReadTimeout、120s IdleTimeout;WriteTimeout 保持 0,避免截断任务状态 SSE 长连接
114+
8. **Docker Nginx 长连接代理**:Web 版 Nginx 在 `http` 上下文使用 `$http_upgrade``$connection_upgrade``map`,API 代理只设置一个 `Connection $connection_upgrade`,兼容普通 HTTP 请求和 WebSocket/SSE 升级场景
115+
9. **桌面端语言包加载**`desktop/src/i18n/index.ts` 只在启动资源中内置默认 `zh-CN``en-US` / `ja-JP` / `ko-KR` 通过动态 import 在切换语言前按需加载,避免启动时打包并解析全部 locale JSON
116+
10. **Tauri asset/CSP 边界**:桌面端 `asset://` 仅允许应用数据、应用配置、应用缓存和临时目录范围,禁止回退到 `$HOME/**`;CSP 只放行本地应用资源、localhost API/SSE、`asset/blob/data/http(s)` 图片与必要的 Vite/Tauri 内联样式
110117

111118
## 代码风格
112119

@@ -120,34 +127,55 @@ frontend/ # 独立 Web 前端 (v2.5.2, 非 Tauri)
120127
### React 前端
121128
- 函数组件 + Hooks,无 Class 组件
122129
- Zustand 状态管理,`configStore` 管理 provider 配置和迁移
123-
- API 调用集中在 `services/` 目录
130+
- API 调用集中在 `services/` 目录,组件通过 service 函数 + Zustand/本地 state 管理请求结果;当前不使用 React Query,重新引入前必须先确定查询缓存边界和迁移入口
124131
- i18n 使用 `react-i18next`,翻译文件在 `i18n/locales/`
125132
- Tailwind CSS 样式
126133

127134
### 通用
128135
- 中文注释解释「为什么」而非「做什么」
129136
- 提交信息格式:`feat:`, `fix:`, `chore:`, `docs:`
130-
- 版本号统一在 `Cargo.toml`, `tauri.conf.json`, `package.json`, `Cargo.lock`, `package-lock.json`
137+
- 桌面发布版本号统一在 `Cargo.toml`, `tauri.conf.json`, `desktop/package.json`, `Cargo.lock`, `desktop/package-lock.json`
138+
- Docker Web 版仍构建 `frontend/``frontend/package.json``frontend/package-lock.json` 的根版本必须跟随 `desktop/package.json`,避免 Web 镜像与当前应用版本元数据脱节
131139

132140
## 注意事项 & 易错点
133141

134-
1. **端口冲突**:Go sidecar 监听 `127.0.0.1:8080`,确保无其他进程占用。调试时检查 `lsof -i :8080`
142+
1. **端口冲突**:Go sidecar 监听 `127.0.0.1:8080`标准健康检查接口为 `GET /api/v1/health`确保无其他进程占用。调试时检查 `lsof -i :8080`
135143
2. **模型名称**`openai-image` provider 默认模型是 `gpt-image-2`(v2.8.0 更新),不支持 `quality` 参数
136-
3. **版本同步**发布前确保 5 个文件的版本号一致(见上方「通用」部分)
144+
3. **版本同步**发布前确保桌面版本文件一致,并同步 `frontend/package.json` / `frontend/package-lock.json` 根版本;Dockerfile 当前构建的是 `frontend/`,不要让 Web 镜像保留旧版本号
137145
4. **Tauri 权限**:新功能涉及文件系统/网络访问时需更新 `capabilities/default.json`
138146
5. **Docker vs Desktop**:后端通过 `platform/runtime.go` 检测运行环境,Docker 监听 `0.0.0.0`,Tauri 监听 `127.0.0.1`
139147
6. **configStore 迁移**:前端配置存储在 localStorage,版本迁移在 `configStore.ts``migrations` 中处理,当前版本 v19
140148
7. **图片存储路径**:桌面端默认 `~/Library/Application Support/com.banana.pro/` (macOS),`%APPDATA%/com.banana.pro/` (Windows)
149+
8. **参考图边界**:后端必须同时限制 multipart `refImages` 与桌面端本地 `refPaths`,最多 10 张、单张最多 20MB、总计最多 80MB;本地路径读取必须先 `os.Open`,对已打开文件执行 `file.Stat` 并校验普通文件/大小/总量,再通过有界读取与关闭 helper 读取,禁止回退到裸 `os.ReadFile`
150+
9. **Provider 诊断日志**:OpenAI、Gemini、OpenAI Image 的响应日志和错误返回默认只能记录状态、耗时、请求 ID、响应长度和有界脱敏预览,禁止输出完整响应体、未脱敏错误体或完整 base64 图片数据
151+
10. **HTTP Server 超时**:新增或修改后端 server 构造时必须保留 `ReadHeaderTimeout=5s``ReadTimeout=30s``IdleTimeout=120s`;不要给全局 `WriteTimeout` 设置短超时,因为 `/api/v1/tasks/:task_id/stream` 依赖 SSE 长连接保活
152+
11. **Worker Provider 超时**:新增或修改 provider 时必须把传入的 `context.Context` 继续传递给 HTTP 请求/长耗时操作并及时返回;Worker 不再为 `Generate` 额外派生 goroutine,超时后会在 provider 返回时记录 `生成超时(...)`,provider panic 会转换为任务失败;provider 内部如需 `io.Pipe`/multipart writer goroutine,也必须监听同一个 context 并在取消时关闭管道
153+
12. **模板市场渲染**`desktop/src/components/TemplateMarket/TemplateMarketDrawer.tsx` 的模板列表必须保持响应式虚拟网格(2/3/4 列),只渲染可见 `TemplateCard`;模板市场内容区必须保持单一纵向滚动容器,筛选器随模板列表一起滚走;虚拟网格只渲染可见卡片,不得把筛选器固定在虚拟列表外部;列数和断点只能通过文件顶部 `TEMPLATE_GRID_COLUMNS` / `TEMPLATE_GRID_BREAKPOINTS` 常量调整,不要在计算函数里散落魔法数字;修改搜索、筛选、预览或应用逻辑时不得回退为 `filteredTemplates.map(...)` 全量渲染
154+
13. **图片 URL 诊断日志**`desktop/src/services/api.ts``getImageUrl` 属于批量图片渲染热路径,URL 转换/回退日志必须通过 `getDiagnosticVerbose()` 或等价诊断开关门控;默认不得在控制台输出每张图片的 URL 生成日志
155+
14. **Zustand 订阅范围**:桌面端组件不得直接调用 `useConfigStore()``useGenerateStore()``useToastStore()` 等整仓订阅;只读取单字段时使用 selector,读取多个字段/action 时使用 `useShallow` 包裹对象 selector,避免无关状态变化触发重渲染,同时不得改变 store state shape 或 persistence 行为
156+
15. **历史缓存持久化**`desktop/src/store/historyStore.ts``history-cache` localStorage 只允许保存轻量、有界的历史列表快照(当前最多 20 条)和分页元信息;持久化与旧缓存合并必须剥离 `url` / `thumbnailUrl` 等派生展示 URL,避免缓存膨胀,并确保 `hasMore` / `page` 仍能从下一页继续加载
157+
16. **Nginx Upgrade 头**:修改 `docker/nginx.conf``/api/` 代理时不得同时设置多个 `proxy_set_header Connection`;必须保留 `proxy_http_version 1.1``Upgrade $http_upgrade``Connection $connection_upgrade`、现有 300s 读写超时,以及 `http``map $http_upgrade $connection_upgrade`,避免普通 API 请求被错误标记为 upgrade 或覆盖升级头
158+
17. **Docker 健康检查覆盖范围**:Dockerfile 与 `docker-compose.yml` 的主容器健康检查必须保持一致,并通过 Nginx 同时验证前端入口 `/` 和后端 API `GET /api/v1/health`;不要只检查直连后端 `:8080`,否则无法发现 Nginx/静态前端不可用的问题
159+
18. **Provider 配置 API 入口**:桌面端 `ProviderConfig` 类型和 `updateProviderConfig` 实现由 `desktop/src/services/providerApi.ts` 统一维护;`configApi.ts` 只能为兼容旧调用重导出这些符号或保留独立的旧接口包装,禁止再次复制 provider 配置类型或 `/providers/config` 更新逻辑
160+
19. **模板市场组件边界**`TemplateMarketDrawer.tsx` 负责抽屉生命周期、数据加载、过滤状态、预览和应用模板;搜索框、筛选 chip、分类筛选和刷新/数量栏由 `desktop/src/components/TemplateMarket/TemplateMarketFilters.tsx` 维护。继续拆分模板市场时一次只抽一个清晰职责,不得改变现有 Tailwind 样式、虚拟网格、搜索/筛选、预览或应用行为
161+
20. **参考图上传逻辑边界**`ReferenceImageUpload.tsx` 负责参考图区域 UI、点击/拖拽添加、压缩、持久化、预览和排序;剪贴板图片提取、Tauri 剪贴板兜底、全局 paste 捕获由同目录 `useReferenceImagePaste.ts` 维护。修改粘贴能力时优先调整该 hook,并保持现有 add/delete/drag/paste 行为和 Tailwind 样式不变
162+
- 参考图拖拽的临时 Blob 缓存只能通过 `window.__BANANA_DRAG_IMAGE_DATA__` 这个固定字段读写,并配合 `isCachedDragImageData` 运行时守卫;不要重新使用 `window[symbol]` 或其他动态全局索引,避免静态扫描误判对象注入
163+
21. **设置弹窗字段组边界**`SettingsModal.tsx` 继续负责标签页状态、provider 切换、保存、测试连接和跨 section 草稿状态;provider 连接字段(Base URL、API Key、显隐按钮、云雾推荐入口和警告/提示插槽)由 `desktop/src/components/Settings/ProviderConnectionFields.tsx` 维护。继续拆分设置弹窗时一次只抽一个清晰 section 或 field group,并保持现有保存/测试/切换行为和 Tailwind 样式不变
164+
22. **桌面端数据请求策略**:桌面端当前没有 `useQuery` / `useMutation` 调用,也不挂载 `QueryClientProvider`;所有请求仍从 `desktop/src/services/` 的显式 API helper 发起,再由 Zustand store 或组件本地 state 保存结果。未来如要引入 React Query,必须从具体 service 调用的最小迁移点开始,并在同一变更中说明缓存 key、失效策略和与 Zustand 的职责边界,禁止只添加全局 Provider 或空依赖
165+
23. **桌面端 i18n 语言包**:新增或修改桌面端语言切换逻辑时,必须通过 `changeAppLanguage` 先加载目标语言资源再调用 i18next 切换;不要在 `desktop/src/i18n/index.ts` 静态 import 所有 locale JSON。默认语言 `zh-CN` 随启动加载,`en-US``ja-JP``ko-KR` 保持可用并在首次切换时懒加载,加载期间继续显示当前语言以减少闪烁
166+
24. **Tauri asset/CSP 安全边界**`desktop/src-tauri/tauri.conf.json``assetProtocol.scope` 必须保持在 `$APPDATA/**``$APPCONFIG/**``$APPCACHE/**``$TEMP/**` 等应用/临时目录内,禁止重新加入 `$HOME/**`。CSP 不得设回 `null`;新增图片、Worker、网络或内联资源需求时,只能按实际来源最小化追加 `img-src` / `connect-src` / `worker-src` / `style-src`,并确认 `desktop/src/services/api.ts``convertFileSrc(..., 'asset')` 仍能加载 `storage/` 生成图。
141167

142168
## 测试
143169

144170
项目当前无自动化测试套件。验证方式:
145171
- `cd desktop && npm run tauri dev` 启动桌面端手动测试
146-
- `cd backend && go run cmd/server/main.go` 启动后端,用 curl 测试 API
147-
- Docker: `docker compose up -d` 后访问 `http://localhost:8090`
172+
- `cd backend && go run cmd/server/main.go` 启动后端,用 `curl http://localhost:8080/api/v1/health` 测试健康检查
173+
- Docker: `docker compose up -d` 后访问 `http://localhost:8090`;容器健康检查会通过 Nginx 同时探测 `/``/api/v1/health`
148174

149175
## CI/CD
150176

151177
- **release.yml**: 推送 `v*` tag 触发,构建 macOS ARM/Universal + Windows x64,生成 latest.json + .sig 签名
152-
- **pr-check.yml**: PR 触发,运行后端 `go vet` + 前端 `npm run build` 检查
178+
- **pr-check.yml**: PR 触发,运行后端 `go vet` + 前端 `npm run build` 检查;Smoke Test 先 `go build` 后端二进制,再以 `DISABLE_STDIN_MONITOR=1` 启动并读取 `SERVER_PORT` 调用 `/api/v1/health`,避免首次 `go run` 下载/编译依赖导致 30 秒健康检查窗口超时,也兼容端口自动递增
179+
- CI 的 Go 版本统一通过 `backend/go.mod``go` 指令读取,不在 workflow 中写死版本号
180+
- Release 构建在 `desktop/package-lock.json` 存在时使用 `npm ci`,保证依赖安装严格跟随 lockfile
153181
- GitHub Secrets 需配置:`TAURI_SIGNING_PRIVATE_KEY`, `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ VOLUME ["/app/storage"]
100100
# 暴露端口
101101
EXPOSE 80
102102

103-
# 健康检查
103+
# 健康检查:同时覆盖 Nginx/前端入口和经 Nginx 代理的后端 API
104104
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
105-
CMD wget -q --spider http://localhost:8080/api/v1/health || wget -q --spider http://localhost:80/api/v1/health || exit 1
105+
CMD wget -q -T 3 -t 1 --spider http://localhost/ && wget -q -T 3 -t 1 --spider http://localhost/api/v1/health || exit 1
106106

107107
# 启动脚本:同时运行 Nginx 和后端服务
108108
CMD sh -c "mkdir -p /app/storage/local && nginx && cd /app && ./server"

0 commit comments

Comments
 (0)