7f3b8b4cc7
- README: 测试数 81、输出格式表 + vCard 10字段、透视矫正、格式扩展 - CHANGELOG: v0.3.0 条目(格式扩展+解码增强+vCard扩展) - ROADMAP: v0.2.0/v0.3.0 移至已交付,更新下一版本规划 - CLAUDE.md: 测试 81→105、perspective.rs 模块、Web fmt 参数
9.8 KiB
9.8 KiB
CLAUDE.md
项目概述
QRGen — 从零手搓的 QR 码生成/解码器,Rust workspace (core + cli + gui + web),完整实现 ISO/IEC 18004 国际标准。GUI + CLI + Web + Library 四种使用方式,支持编码+解码双向闭环。
构建命令
# 安装前端依赖(首次或 package.json 变更后)
cd gui/src-frontend && pnpm install && cd ../..
# 全 workspace 编译检查
cargo check
# 全部测试
cargo test # 82 tests
# 仅核心库
cargo test -p qr-core
cargo build -p qr-core
# CLI 构建
cargo build --release -p qrgen
cargo run -p qrgen -- "Hello World"
# Web 服务
cargo run -p qrgen-web # → http://localhost:3000
# CLI 解码
cargo run -p qrgen -- --decode test.png
# GUI 开发模式
cd gui/src-frontend && pnpm dev # 终端1: Vite 热更新
cargo run -p qrgen-gui # 终端2: Tauri 窗口
# GUI 前端类型检查
cd gui/src-frontend && pnpm tsc --noEmit
# GUI 前端构建
cd gui/src-frontend && pnpm build
# GUI 完整打包(生成 NSIS 安装包)
# 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
# 前端格式
cd gui/src-frontend && pnpm format # prettier 格式化
cd gui/src-frontend && pnpm format:check # prettier 检查
# 前端 lint
cd gui/src-frontend && pnpm lint # eslint
# 前端测试
cd gui/src-frontend && pnpm test # vitest (12 tests)
cd gui/src-frontend && pnpm test:coverage # vitest + 覆盖率
架构
Cargo workspace 四层。
QRGen/
├── core/ # Rust 库 crate(零 Tauri 依赖)
│ └── src/
│ ├── qr.rs # 顶层 API — QrCode::encode(),9 步流水线
│ ├── version.rs # 40 版本容量表 + 自动选择
│ ├── ecc/
│ │ ├── galois.rs # GF(2⁸) 运算 + exp/log 预计算表 + poly_eval
│ │ └── reed_solomon.rs # RS 纠错码 + 数据交错
│ ├── encoder/
│ │ ├── mode.rs # 4 种编码模式 (数字/字母/字节/汉字 Shift JIS)
│ │ ├── segment.rs # 字符串分析 + 自动分段
│ │ └── bitstream.rs # 比特流拼接 + 终止符/填充
│ ├── decoder/ # QR 解码器(从零手写)
│ │ ├── mod.rs # 顶层 API — decode_image() + decode_matrix()
│ │ ├── bch.rs # BCH(15,5)+BCH(18,6) 查表解码
│ │ ├── format.rs # 格式信息 + 版本信息读取
│ │ ├── extract.rs # 逆向蛇形排列提取码字
│ │ ├── deinterleave.rs # 逆向 RS 数据交错
│ │ ├── rs_decode.rs # RS 纠错流水线
│ │ ├── mode_decode.rs # 逆向 4 种编码模式
│ │ ├── detect.rs # 定位图案检测 + 采样网格
│ │ ├── perspective.rs # 透视矫正(旋转+仿射变换)
│ │ └── image.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, 直接边界检测 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 + 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 / ErrorBoundary
│ │ ├── modes/ # Text/Url/Wifi/VCard/Email/Phone/Sms
│ │ ├── hooks/ # useQrEncode (200ms 防抖, Store 缓存, WiFi 脱敏)
│ │ ├── store/ # QrProvider + useReducer
│ │ ├── types/ # ModeType / QrState / QrAction / HistoryEntry
│ │ └── utils/ # qrText.ts — 共享文本构造函数
│ ├── tauri.conf.json # 窗口 900×650 + CSP + NSIS 打包
│ └── WebView2Loader.dll # WebView2 运行时(打包用)
├── 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 → GUI Frontend)
| Command | 参数 | 返回值 | 功能 |
|---|---|---|---|
encode_qr |
text: String, level: String, margin: u8 |
Result<QrResponse, String> |
编码文本为 QR,返回 SVG + 版本/尺寸/掩码 |
export_png |
text: String, level: String, margin: u8, module_size: u8 |
Result<Vec<u8>, String> |
编码并导出 PNG 字节 |
decode_qr |
image_bytes: Vec<u8> |
Result<String, String> |
解码图片为文本 |
save_history |
entry: HistoryEntry |
Result<(), String> |
添加历史记录(最多 50 条) |
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(png/bmp/jpeg/webp/svg) |
PNG/BMP/JPEG/WebP/SVG |
POST /api/decode |
multipart file (PNG/JPEG/WebP) |
JSON {text, version, level, mask, errors_corrected} |
前端状态管理
QrState {
mode → 当前编码模式 (text/url/wifi/vcard/email/phone/sms)
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, 含 formData 字段用于恢复)
loading → boolean
}
Action: SET_MODE | SET_FORM_DATA | SET_CONFIG | SET_PREVIEW | SET_LOADING
| SET_HISTORY | ADD_HISTORY | REMOVE_HISTORY | RESET
编码模式文本格式
| 模式 | QR 内容格式 |
|---|---|
| text | 原始文本 |
| url | 原始 URL(失焦自动补全 https://) |
| wifi | WIFI:T:<auth>;S:<ssid>;P:<pwd>;<H:true;>; |
| vcard | BEGIN:VCARD\nVERSION:3.0\nFN:...\nTEL:...\nEMAIL:...\nORG:...\nADR:...\nEND:VCARD |
mailto:<addr>?subject=<s>&body=<b> |
|
| phone | tel:<number> |
| sms | smsto:<number>:<message> |
关键约束
- Rust 工具链:
stable-x86_64-pc-windows-gnu,MinGW-Builds GCC 15.2.0 - MinGW 兼容:
.cargo/config.toml已添加-lmcfgthread链接标志 - qr-core 纯算法:除
image(PNG) 外无外部依赖,不依赖任何 QR 编码库 - WebView2:Windows 10+ 自带,打包需
WebView2Loader.dll - 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 三处注册
测试覆盖
| 层级 | 数量 | 说明 |
|---|---|---|
| 单元测试 | 81 | Galois 运算、RS 编解码、模式编解码、掩码评分、格式/版本信息 roundtrip、BCH 容错、蛇形提取、vCard 扩展等 |
| 集成测试 | 24 | 端到端编码、渲染输出验证、边距、特殊字符、自动版本选择、格式信息 roundtrip |
| 总计 | 105 | cargo test 全部通过 |
版本号升级清单
| 文件 | 字段 | 说明 |
|---|---|---|
Cargo.toml |
[workspace.package] version |
Rust 全量自动继承 |
gui/tauri.conf.json |
version |
打包版本号 |
gui/tauri.conf.json |
窗口 title |
窗口标题栏 |
Release 操作:
git tag vX.Y.Z && git push --tagstea release create --login cloud --repo Serendipity/QRGen --tag vX.Y.Z