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
@@ -47,7 +47,12 @@
"phone": "Phone",
"email": "Email",
"company": "Company",
"address": "Address"
"title": "Title",
"address": "Address",
"url": "URL",
"birthday": "Birthday",
"note": "Note",
"photo": "Photo URL"
},
"email": {
"to": "To",
@@ -47,7 +47,12 @@
"phone": "电话",
"email": "邮箱",
"company": "公司",
"address": "地址"
"title": "职位",
"address": "地址",
"url": "网址",
"birthday": "生日",
"note": "备注",
"photo": "照片URL"
},
"email": {
"to": "收件人",
+5
View File
@@ -8,7 +8,12 @@ const FIELDS = [
{ key: 'phone', i18n: 'vcard.phone' },
{ key: 'email', i18n: 'vcard.email' },
{ key: 'company', i18n: 'vcard.company' },
{ key: 'title', i18n: 'vcard.title' },
{ key: 'address', i18n: 'vcard.address' },
{ key: 'vcardUrl', i18n: 'vcard.url' },
{ key: 'birthday', i18n: 'vcard.birthday' },
{ key: 'note', i18n: 'vcard.note' },
{ key: 'photo', i18n: 'vcard.photo' },
];
export default function VCardMode() {
+14 -2
View File
@@ -14,14 +14,26 @@ export function buildWifiText(formData: Record<string, string>): string {
return `WIFI:T:${encryption};S:${ssid};P:${password};${hidden};`;
}
/** 构造 vCard 字符串 */
/** 构造 vCard 3.0 字符串(含扩展字段) */
export function buildVCardText(formData: Record<string, string>): string {
const name = formData.name || '';
const phone = formData.phone || '';
const email = formData.email || '';
const company = formData.company || '';
const address = formData.address || '';
return `BEGIN:VCARD\nVERSION:3.0\nFN:${name}\nTEL:${phone}\nEMAIL:${email}\nORG:${company}\nADR:${address}\nEND:VCARD`;
const title = formData.title || '';
const url = formData.vcardUrl || '';
const birthday = formData.birthday || '';
const note = formData.note || '';
const photo = formData.photo || '';
let s = `BEGIN:VCARD\nVERSION:3.0\nFN:${name}\nTEL:${phone}\nEMAIL:${email}\nORG:${company}`;
if (title) s += `\nTITLE:${title}`;
if (address) s += `\nADR:${address}`;
if (url) s += `\nURL:${url}`;
if (birthday) s += `\nBDAY:${birthday}`;
if (note) s += `\nNOTE:${note}`;
if (photo) s += `\nPHOTO:${photo}`;
return s + '\nEND:VCARD';
}
/** 构造 mailto 链接 */