docs: 更新 CLAUDE.md — web 端 + Docker + 修复说明
- workspace: core+cli+gui → core+cli+gui+web - 新增 Web 服务构建/API 文档 - 新增 Docker 构建说明 - 测试数更新: 69 → 82 - 新增已知坑位 (PNG margin, finder separator, Tauri 导出) - beforeBuildCommand 改为 npm run build - 架构树增加 capabilities/ utils/ Dockerfile/ .dockerignore Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
## 项目概述
|
||||
|
||||
QRGen — 从零手搓的 QR 码生成器,Rust workspace (core + cli + gui),完整实现 ISO/IEC 18004 国际标准。GUI + CLI + Library 三种使用方式。
|
||||
QRGen — 从零手搓的 QR 码生成器,Rust workspace (core + cli + gui + web),完整实现 ISO/IEC 18004 国际标准。GUI + CLI + Web + Library 四种使用方式。
|
||||
|
||||
## 构建命令
|
||||
|
||||
@@ -14,7 +14,7 @@ cd gui/src-frontend && pnpm install && cd ../..
|
||||
cargo check
|
||||
|
||||
# 全部测试
|
||||
cargo test # 69 tests
|
||||
cargo test # 82 tests
|
||||
|
||||
# 仅核心库
|
||||
cargo test -p qr-core
|
||||
@@ -24,6 +24,9 @@ cargo build -p qr-core
|
||||
cargo build --release -p qrgen
|
||||
cargo run -p qrgen -- "Hello World"
|
||||
|
||||
# Web 服务
|
||||
cargo run -p qrgen-web # → http://localhost:3000
|
||||
|
||||
# GUI 开发模式
|
||||
cd gui/src-frontend && pnpm dev # 终端1: Vite 热更新
|
||||
cargo run -p qrgen-gui # 终端2: Tauri 窗口
|
||||
@@ -35,60 +38,74 @@ cd gui/src-frontend && pnpm tsc --noEmit
|
||||
cd gui/src-frontend && pnpm build
|
||||
|
||||
# GUI 完整打包(生成 NSIS 安装包)
|
||||
# 需要先手动构建前端,再运行 tauri build
|
||||
# beforeBuildCommand 用 npm(Tauri CWD 在 src-frontend/,pnpm 不在 PATH)
|
||||
cd gui/src-frontend && pnpm build && cd ..
|
||||
src-frontend/node_modules/.bin/tauri.cmd build
|
||||
|
||||
# Docker 构建(Web 服务)
|
||||
docker build -t qrgen-web -f web/Dockerfile .
|
||||
|
||||
# Rust lint
|
||||
cargo clippy -- -D warnings
|
||||
```
|
||||
|
||||
## 架构
|
||||
|
||||
Cargo workspace 三层,前后端分离,Tauri IPC 通信。
|
||||
Cargo workspace 四层。
|
||||
|
||||
```
|
||||
QRGen/
|
||||
├── core/ # Rust 库 crate(零 Tauri 依赖)
|
||||
│ └── src/
|
||||
│ ├── qr.rs # 顶层 API — QrCode::encode()
|
||||
│ ├── qr.rs # 顶层 API — QrCode::encode(),9 步流水线
|
||||
│ ├── version.rs # 40 版本容量表 + 自动选择
|
||||
│ ├── ecc/
|
||||
│ │ ├── galois.rs # GF(2⁸) 运算 + exp/log 预计算表
|
||||
│ │ └── reed_solomon.rs # RS 纠错码 + 数据交错
|
||||
│ ├── encoder/
|
||||
│ │ ├── mode.rs # 4 种编码模式 (数字/字母/字节/汉字)
|
||||
│ │ ├── mode.rs # 4 种编码模式 (数字/字母/字节/汉字 Shift JIS)
|
||||
│ │ ├── segment.rs # 字符串分析 + 自动分段
|
||||
│ │ └── bitstream.rs # 比特流拼接 + 终止符/填充
|
||||
│ ├── matrix/
|
||||
│ │ ├── grid.rs # 模块矩阵 (含 reserved 保留区)
|
||||
│ │ ├── patterns.rs # 定位/对齐/时序图案 + BCH(15,5) + BCH(18,6)
|
||||
│ │ │ # 含 finder separator 四边预留
|
||||
│ │ ├── placement.rs # 蛇形数据排列
|
||||
│ │ └── mask.rs # 8 种掩码 + 四规则惩罚评分
|
||||
│ └── render/
|
||||
│ ├── png.rs # PNG 输出 (image crate)
|
||||
│ ├── svg.rs # SVG 输出
|
||||
│ ├── png.rs # PNG 输出 (image crate, 直接边界检测 margin)
|
||||
│ ├── svg.rs # SVG 输出 (预分配容量)
|
||||
│ └── ascii.rs # 终端 ASCII (██/ )
|
||||
├── cli/ # CLI 命令行 (依赖 core + clap + anyhow)
|
||||
│ └── src/main.rs # Args { content, -o, -l, -v, -s, -m, --invert }
|
||||
├── gui/ # Tauri 桌面应用 (依赖 core)
|
||||
│ # 含路径遍历防护(拒绝 .. 组件)
|
||||
├── gui/ # Tauri 桌面应用 (依赖 core + tauri-plugin-*)
|
||||
│ ├── capabilities/default.json # ACL 权限 (store/dialog/clipboard/fs)
|
||||
│ ├── src/
|
||||
│ │ ├── main.rs # Windows 子系统入口
|
||||
│ │ └── lib.rs # 5 个 Tauri commands + AppState
|
||||
│ ├── src-frontend/ # React 18 + TypeScript + TailwindCSS
|
||||
│ │ └── src/
|
||||
│ │ ├── App.tsx # 三栏 + 底部输入布局
|
||||
│ │ ├── components/ # ModePanel / QrPreview / ExportPanel / HistoryList
|
||||
│ │ ├── modes/ # TextMode / UrlMode / WifiMode / VCardMode / EmailMode / PhoneMode / SmsMode
|
||||
│ │ ├── hooks/ # useQrEncode (200ms 防抖 + Tauri invoke)
|
||||
│ │ ├── components/ # ModePanel / QrPreview / ExportPanel / HistoryList / ErrorBoundary
|
||||
│ │ ├── modes/ # Text/Url/Wifi/VCard/Email/Phone/Sms
|
||||
│ │ ├── hooks/ # useQrEncode (200ms 防抖, Store 缓存, WiFi 脱敏)
|
||||
│ │ ├── store/ # QrProvider + useReducer
|
||||
│ │ └── types/ # ModeType / QrState / QrAction / ...
|
||||
│ ├── tauri.conf.json # 窗口 900×650 + NSIS 打包配置
|
||||
│ │ ├── types/ # ModeType / QrState / QrAction / HistoryEntry
|
||||
│ │ └── utils/ # qrText.ts — 共享文本构造函数
|
||||
│ ├── tauri.conf.json # 窗口 900×650 + CSP + NSIS 打包
|
||||
│ └── WebView2Loader.dll # WebView2 运行时(打包用)
|
||||
└── Cargo.toml # Workspace 根 + [workspace.package]
|
||||
├── web/ # Web 服务 (依赖 core + axum + tokio)
|
||||
│ ├── Dockerfile # rust-alpine 多阶段构建 → 17.7MB
|
||||
│ ├── src/
|
||||
│ │ ├── main.rs # axum: GET / + GET /api/qr?text=&level=&margin=&size=&fmt=
|
||||
│ │ └── templates/
|
||||
│ │ └── index.html # 内嵌 GUI 风格界面(三栏+7模式+实时预览)
|
||||
├── .dockerignore # 排除 target/ gui/ test/
|
||||
└── Cargo.toml # Workspace: core + cli + gui + web
|
||||
```
|
||||
|
||||
## IPC 接口(Rust → Frontend)
|
||||
## IPC 接口(Rust → GUI Frontend)
|
||||
|
||||
| Command | 参数 | 返回值 | 功能 |
|
||||
|---------|------|--------|------|
|
||||
@@ -98,6 +115,13 @@ QRGen/
|
||||
| `load_history` | — | `Result<Vec<HistoryEntry>, String>` | 加载全部历史记录 |
|
||||
| `clear_history` | — | `Result<(), String>` | 清空历史记录 |
|
||||
|
||||
## Web API
|
||||
|
||||
| Endpoint | 参数 | 返回 |
|
||||
|----------|------|------|
|
||||
| `GET /` | — | HTML 页面(内嵌 7 种编码模式) |
|
||||
| `GET /api/qr` | `text`, `level`(L/M/Q/H), `margin`(1-20), `size`(2-20), `fmt`(svg) | PNG 或 SVG |
|
||||
|
||||
## 前端状态管理
|
||||
|
||||
```
|
||||
@@ -106,7 +130,7 @@ QrState {
|
||||
formData → 各模式表单数据 (Record<string, string>)
|
||||
config → { level: L|M|Q|H, margin: 1-10, moduleSize: 2-20 }
|
||||
preview → { svg, version, size, mask } | null
|
||||
history → HistoryEntry[] (最多 50 条,FIFO)
|
||||
history → HistoryEntry[] (最多 50 条, FIFO, 含 formData 字段用于恢复)
|
||||
loading → boolean
|
||||
}
|
||||
|
||||
@@ -120,7 +144,7 @@ Action: SET_MODE | SET_FORM_DATA | SET_CONFIG | SET_PREVIEW | SET_LOADING
|
||||
|------|-----------|
|
||||
| text | 原始文本 |
|
||||
| url | 原始 URL(失焦自动补全 `https://`) |
|
||||
| wifi | `WIFI:T:<auth>;S:<ssid>;P:<pwd>;;` |
|
||||
| wifi | `WIFI:T:<auth>;S:<ssid>;P:<pwd>;<H:true;>;` |
|
||||
| vcard | `BEGIN:VCARD\nVERSION:3.0\nFN:...\nTEL:...\nEMAIL:...\nORG:...\nADR:...\nEND:VCARD` |
|
||||
| email | `mailto:<addr>?subject=<s>&body=<b>` |
|
||||
| phone | `tel:<number>` |
|
||||
@@ -131,17 +155,24 @@ Action: SET_MODE | SET_FORM_DATA | SET_CONFIG | SET_PREVIEW | SET_LOADING
|
||||
- **Rust 工具链**:`stable-x86_64-pc-windows-gnu`,MinGW-Builds GCC 15.2.0
|
||||
- **MinGW 兼容**:`.cargo/config.toml` 已添加 `-lmcfgthread` 链接标志
|
||||
- **qr-core 纯算法**:除 `image` (PNG) 外无外部依赖,不依赖任何 QR 编码库
|
||||
- **qrcode crate 代码冲突**:如果系统安装了 `qrcode` Rust crate,需注意 QRGen 是从零实现的替代品
|
||||
- **WebView2**:Windows 10+ 自带,打包需 `WebView2Loader.dll`
|
||||
- **前端 beforeBuildCommand**:tauri build 前需确保 `pnpm` 在 PATH
|
||||
- **GUI beforeBuildCommand**:Tauri CWD 在 `gui/src-frontend/`,用 `npm run build`(非 pnpm)
|
||||
- **GUI 导出**:需 `tauri-plugin-fs` + `fs:allow-write-file` + `$HOME/**` scope
|
||||
- **Docker 构建**:`web/Dockerfile` 用 sed 移除 gui 成员避免拉 Tauri 依赖
|
||||
|
||||
## 已知坑位
|
||||
|
||||
- **PNG margin**:不能用 `saturating_sub` 检测 margin——它在 0 处回绕,导致 quiet zone 全黑
|
||||
- **Finder separator**:必须预留四边隔离带(不只是右侧和底部),否则数据模块会破坏 finder 检测
|
||||
- **Tauri 导出**:`tauri-plugin-fs` 需同时在 Cargo.toml、lib.rs `.plugin()` 和 capabilities 三处注册
|
||||
|
||||
## 测试覆盖
|
||||
|
||||
| 层级 | 数量 | 说明 |
|
||||
|------|------|------|
|
||||
| 单元测试 | 54 | Galois 运算、RS 编码、模式编码、掩码评分、格式信息等 |
|
||||
| 集成测试 | 15 | 端到端编码、渲染输出验证、边距、特殊字符、自动版本选择 |
|
||||
| 总计 | 69 | `cargo test` 全部通过 |
|
||||
| 单元测试 | 58 | Galois 运算、RS 编码、模式编码、掩码评分、格式信息等 |
|
||||
| 集成测试 | 24 | 端到端编码、渲染输出验证、边距、特殊字符、自动版本选择、格式信息 roundtrip |
|
||||
| 总计 | 82 | `cargo test` 全部通过 |
|
||||
|
||||
## 版本号升级清单
|
||||
|
||||
|
||||
Reference in New Issue
Block a user