feat: GUI 端新增解码功能 — 选择图片解码 QR 码
- 新增 decode_qr Tauri command(接收图片字节,返回解码文本) - ExportPanel 新增「选择图片解码」按钮 + 解码结果展示 - fs:allow-read-file 权限,支持 /c/Users/33644 和 C:\Users\33644\AppData\Local\Temp 路径
This commit is contained in:
@@ -2,8 +2,8 @@ import { useState } from 'react';
|
||||
import { useQrState } from '../store/qrContext';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
import { save } from '@tauri-apps/plugin-dialog';
|
||||
import { writeFile } from '@tauri-apps/plugin-fs';
|
||||
import { open, save } from '@tauri-apps/plugin-dialog';
|
||||
import { readFile, writeFile } from '@tauri-apps/plugin-fs';
|
||||
import type { QrConfig } from '../types';
|
||||
import { buildEncodedText } from '../utils/qrText';
|
||||
|
||||
@@ -11,6 +11,30 @@ export default function ExportPanel() {
|
||||
const { state, dispatch } = useQrState();
|
||||
const [exporting, setExporting] = useState(false);
|
||||
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
||||
const [decodedText, setDecodedText] = useState<string | null>(null);
|
||||
const [decoding, setDecoding] = useState(false);
|
||||
|
||||
const handleDecode = async () => {
|
||||
setDecoding(true);
|
||||
setErrorMsg(null);
|
||||
setDecodedText(null);
|
||||
try {
|
||||
const filePath = await open({
|
||||
filters: [{ name: '图片文件', extensions: ['png', 'jpg', 'jpeg', 'webp', 'bmp'] }],
|
||||
multiple: false,
|
||||
});
|
||||
if (!filePath) {
|
||||
setDecoding(false);
|
||||
return;
|
||||
}
|
||||
const bytes = await readFile(filePath);
|
||||
const text: string = await invoke('decode_qr', { imageBytes: Array.from(bytes) });
|
||||
setDecodedText(text);
|
||||
} catch (e) {
|
||||
setErrorMsg(`解码失败: ${e}`);
|
||||
}
|
||||
setDecoding(false);
|
||||
};
|
||||
|
||||
const handleCopySvg = async () => {
|
||||
if (!state.preview?.svg) return;
|
||||
@@ -139,6 +163,25 @@ export default function ExportPanel() {
|
||||
>
|
||||
导出 SVG
|
||||
</button>
|
||||
|
||||
{/* 解码区 */}
|
||||
<div className="mt-3 pt-3 border-t border-gray-200 dark:border-gray-700">
|
||||
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">
|
||||
解码
|
||||
</div>
|
||||
<button
|
||||
onClick={handleDecode}
|
||||
disabled={decoding}
|
||||
className="w-full py-2 rounded-lg bg-amber-500 text-white text-sm font-medium hover:bg-amber-600 disabled:opacity-40 transition-all"
|
||||
>
|
||||
{decoding ? '解码中...' : '选择图片解码'}
|
||||
</button>
|
||||
{decodedText && (
|
||||
<div className="mt-2 p-2 bg-green-50 dark:bg-green-900/20 rounded-lg text-xs text-green-700 dark:text-green-300 break-all max-h-24 overflow-auto">
|
||||
{decodedText}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user