diff --git a/gui/capabilities/default.json b/gui/capabilities/default.json index 5c12982..e9b1e11 100644 --- a/gui/capabilities/default.json +++ b/gui/capabilities/default.json @@ -11,6 +11,10 @@ { "identifier": "fs:allow-write-file", "allow": [{ "path": "$HOME/**" }] + }, + { + "identifier": "fs:allow-read-file", + "allow": [{ "path": "$HOME/**" }, { "path": "$TEMP/**" }] } ] } diff --git a/gui/gen/schemas/capabilities.json b/gui/gen/schemas/capabilities.json index cef8b88..e0b158f 100644 --- a/gui/gen/schemas/capabilities.json +++ b/gui/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"QRGen 默认权限","local":true,"windows":["main"],"permissions":["core:default","store:default","dialog:default","clipboard-manager:default",{"identifier":"fs:allow-write-file","allow":[{"path":"$HOME/**"}]}]}} \ No newline at end of file +{"default":{"identifier":"default","description":"QRGen 默认权限","local":true,"windows":["main"],"permissions":["core:default","store:default","dialog:default","clipboard-manager:default",{"identifier":"fs:allow-write-file","allow":[{"path":"$HOME/**"}]},{"identifier":"fs:allow-read-file","allow":[{"path":"$HOME/**"},{"path":"$TEMP/**"}]}]}} \ No newline at end of file diff --git a/gui/src-frontend/src/components/ExportPanel.tsx b/gui/src-frontend/src/components/ExportPanel.tsx index 57b8547..3ad3172 100644 --- a/gui/src-frontend/src/components/ExportPanel.tsx +++ b/gui/src-frontend/src/components/ExportPanel.tsx @@ -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(null); + const [decodedText, setDecodedText] = useState(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 + + {/* 解码区 */} +
+
+ 解码 +
+ + {decodedText && ( +
+ {decodedText} +
+ )} +
); } diff --git a/gui/src/lib.rs b/gui/src/lib.rs index 12bc750..c6ca74e 100644 --- a/gui/src/lib.rs +++ b/gui/src/lib.rs @@ -104,6 +104,12 @@ fn load_history(state: tauri::State) -> Result, Stri Ok(history.clone()) } +/// 解码 QR 码图片,返回文本内容 +#[tauri::command] +fn decode_qr(image_bytes: Vec) -> Result { + qr_core::decoder::decode_image(&image_bytes).map(|r| r.text) +} + /// 清空历史记录 #[tauri::command] fn clear_history(state: tauri::State) -> Result<(), String> { @@ -125,6 +131,7 @@ pub fn run() { .invoke_handler(tauri::generate_handler![ encode_qr, export_png, + decode_qr, save_history, load_history, clear_history,