Files
QRGen/CLAUDE.md
T
Serendipity 797a41ea50 docs: 更新全部 markdown 文档 — 加入解码器内容
- README: 解码功能说明 + CLI/Web/GUI 解码示例 + 项目结构树 + 规格表
- CHANGELOG: 解码器条目(9 模块 + 三端入口 + RS/BCH 算法)
- ROADMAP: 解码移至已交付 + 前端工程化 + RS 纠错解码
- CLAUDE.md: 解码器架构 + Web API decode 端点 + IPC 接口
2026-06-19 20:45:22 +08:00

9.7 KiB
Raw Blame History

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 用 npmTauri 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         # 定位图案检测 + 采样网格
│       │   └── 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(svg) PNG 或 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
email mailto:<addr>?subject=<s>&body=<b>
phone tel:<number>
sms smsto:<number>:<message>

关键约束

  • Rust 工具链stable-x86_64-pc-windows-gnuMinGW-Builds GCC 15.2.0
  • MinGW 兼容.cargo/config.toml 已添加 -lmcfgthread 链接标志
  • qr-core 纯算法:除 image (PNG) 外无外部依赖,不依赖任何 QR 编码库
  • WebView2Windows 10+ 自带,打包需 WebView2Loader.dll
  • GUI beforeBuildCommandTauri 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 三处注册

测试覆盖

层级 数量 说明
单元测试 72 Galois 运算、RS 编解码、模式编解码、掩码评分、格式/版本信息 roundtrip、BCH 容错、蛇形提取等
集成测试 24 端到端编码、渲染输出验证、边距、特殊字符、自动版本选择、格式信息 roundtrip
总计 96 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 --tags
  • tea release create --login cloud --repo Serendipity/QRGen --tag vX.Y.Z