Enhance form recognition, optimize UI, and unify components (#19)
- **docs**: 完善组件注释、README 目录结构及 AGENTS.md 文档。 - **refactor**: - 提取通用 `PageHeader`、`Button`、`DashboardCard` 及 `ErrorBoundary` 组件。 - 重构消息通信机制,采用 `@webext-core/messaging` 实现类型安全。 - 将全局通知系统重构为 `SnackbarProvider` (后合并至 `GlobalSnackbar`)。 - 迁移样式系统至 MUI 主题,移除冗余 CSS。 - 优化路由配置,支持独立标签页模式及页面懒加载。 - 移除未使用文件、URL 工具及表单映射相关功能。 - **feat**: - 新增配置导出功能(JSON)及状态提示。 - 新增侧边栏状态变化通知机制。 - 新增文本统计及 JWT 解析工具。 - 优化二维码生成与解析逻辑,换用更轻量的 `qrious` 和 `qr-scanner`。 - 增强高亮器功能,支持闪烁效果及 Shadow DOM 穿透。 - **style**: 优化仪表盘响应式网格布局及 UI 细节。 - **fix**: 修复 `useStorageState` 依赖缺失及路由初始化性能问题。 - **test**: 更新单元测试以覆盖新增的工具函数及功能特性。
This commit is contained in:
+21
-38
@@ -1,4 +1,4 @@
|
||||
import jsQR from 'jsqr';
|
||||
import QrScanner from 'qr-scanner';
|
||||
|
||||
export interface QrCodeParseResult {
|
||||
success: boolean;
|
||||
@@ -6,49 +6,32 @@ export interface QrCodeParseResult {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export async function parseQrCodeFromFile(
|
||||
file: File,
|
||||
timeout: number = 10000,
|
||||
): Promise<QrCodeParseResult> {
|
||||
/**
|
||||
* 从文件中解析二维码
|
||||
* 使用 qr-scanner 替代 jsqr 以减小体积并提高性能
|
||||
*/
|
||||
export async function parseQrCodeFromFile(file: File): Promise<QrCodeParseResult> {
|
||||
try {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
if (!ctx) {
|
||||
return { success: false, error: '无法创建 canvas 上下文' };
|
||||
}
|
||||
|
||||
const image = new Image();
|
||||
image.src = URL.createObjectURL(file);
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
reject(new Error('图片加载超时'));
|
||||
}, timeout);
|
||||
|
||||
image.onload = () => {
|
||||
clearTimeout(timeoutId);
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
ctx.drawImage(image, 0, 0);
|
||||
resolve();
|
||||
};
|
||||
|
||||
image.onerror = () => {
|
||||
clearTimeout(timeoutId);
|
||||
reject(new Error('图片加载失败'));
|
||||
};
|
||||
// qr-scanner 的 scanImage 方法支持直接传入 File 对象
|
||||
// 它会自动处理图片加载、Canvas 绘制和解析过程
|
||||
// 并且在支持的浏览器中会优先使用原生的 BarcodeDetector API
|
||||
const result = await QrScanner.scanImage(file, {
|
||||
returnDetailedScanResult: true,
|
||||
});
|
||||
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const code = jsQR(imageData.data, imageData.width, imageData.height);
|
||||
|
||||
if (code) {
|
||||
return { success: true, data: code.data };
|
||||
if (result && result.data) {
|
||||
return { success: true, data: result.data };
|
||||
} else {
|
||||
return { success: false, error: '未检测到二维码' };
|
||||
}
|
||||
} catch (err) {
|
||||
return { success: false, error: err instanceof Error ? err.message : '解析失败' };
|
||||
// qr-scanner 在未发现二维码时会抛出 "No QR code found"
|
||||
const errorMsg =
|
||||
err === 'No QR code found'
|
||||
? '未检测到二维码'
|
||||
: err instanceof Error
|
||||
? err.message
|
||||
: String(err);
|
||||
return { success: false, error: errorMsg };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user