feat: vCard 扩展 + 格式扩展 + 解码透视矫正 — v0.3.0

Phase 1: 格式扩展
- png.rs → image.rs,OutputFormat 枚举 (PNG/BMP/JPEG/WebP)
- CLI -f/--format,Web fmt 参数扩展,image crate +bmp feature

Phase 2: 解码增强
- 新增 decoder/perspective.rs — 旋转矫正(MVP)
- auto_correct: finder 检测→计算旋转角→仿射变换→再解码
- decode_image 自动重试矫正流水线

Phase 3: vCard 扩展
- 新增 5 字段:TITLE/URL/BDAY/NOTE/PHOTO
- Rust text_builder + TS qrText + VCardMode UI 同步
- CLI 新增 --title --vcard-url --birthday --note --photo
- 中/英 i18n 翻译

测试: 81 Rust + 19 前端全部通过
This commit is contained in:
2026-06-19 21:38:58 +08:00
parent b41f6ee7df
commit 86d788e57c
8 changed files with 294 additions and 9 deletions
+28 -1
View File
@@ -100,6 +100,26 @@ struct Args {
#[arg(long)]
address: Option<String>,
/// 职位 (vCard)
#[arg(long)]
title: Option<String>,
/// 个人网址 (vCard)
#[arg(long = "vcard-url")]
vcard_url: Option<String>,
/// 生日 YYYY-MM-DD (vCard)
#[arg(long)]
birthday: Option<String>,
/// 备注 (vCard)
#[arg(long)]
note: Option<String>,
/// 照片 URL (vCard)
#[arg(long)]
photo: Option<String>,
/// 收件人 (Email)
#[arg(long)]
to: Option<String>,
@@ -255,6 +275,11 @@ fn build_text_from_args(args: &Args) -> anyhow::Result<String> {
args.email.as_deref().unwrap_or(""),
args.company.as_deref().unwrap_or(""),
args.address.as_deref().unwrap_or(""),
args.title.as_deref().unwrap_or(""),
args.vcard_url.as_deref().unwrap_or(""),
args.birthday.as_deref().unwrap_or(""),
args.note.as_deref().unwrap_or(""),
args.photo.as_deref().unwrap_or(""),
)),
Some("email") => {
let to = args
@@ -366,7 +391,9 @@ fn batch_entry_to_text(entry: &BatchEntry) -> anyhow::Result<String> {
let em = entry.email.as_deref().unwrap_or("");
let co = entry.company.as_deref().unwrap_or("");
let ad = entry.address.as_deref().unwrap_or("");
return Ok(text_builder::build_vcard_text(n, ph, em, co, ad));
return Ok(text_builder::build_vcard_text(
n, ph, em, co, ad, "", "", "", "", "",
));
}
if let Some(t) = &entry.to {
let s = entry.subject.as_deref().unwrap_or("");