chore: 前端工程化 + Git hooks + 对齐 PathEditor 规范
- 新增 .gitattributes(CRLF 统一)+ rust-toolchain.toml - 新增 Prettier + ESLint + markdownlint 配置 - 新增 Husky Git hooks(pre-commit lint-staged + commit-msg commitlint) - 新增 vitest 前端测试(12 tests, utils/qrText.ts) - 新增 @ 路径别名(vite + tsconfig) - 新增 ROADMAP / SUPPORT / CODEOWNERS / FUNDING / dependabot - 更新 .gitignore + .editorconfig - 更新 package.json(新增 lint/format/test 脚本) - 全项目 prettier 格式化 + eslint 通过 - 更新 CLAUDE.md + README.md
This commit is contained in:
@@ -40,7 +40,9 @@ export async function persistHistory(history: HistoryEntry[]): Promise<void> {
|
||||
const store = await getStore();
|
||||
await store.set(HISTORY_KEY, history);
|
||||
await store.save();
|
||||
} catch { /* store 不可用时静默忽略 */ }
|
||||
} catch {
|
||||
/* store 不可用时静默忽略 */
|
||||
}
|
||||
}
|
||||
|
||||
/** 从 store 加载历史记录(应用启动时调用) */
|
||||
@@ -66,46 +68,49 @@ export function useQrEncode() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const encode = useCallback((text: string) => {
|
||||
if (!text.trim()) {
|
||||
dispatch({ type: 'SET_PREVIEW', payload: null });
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({ type: 'SET_LOADING', payload: true });
|
||||
|
||||
if (timerRef.current) clearTimeout(timerRef.current);
|
||||
timerRef.current = setTimeout(async () => {
|
||||
try {
|
||||
const result = await invoke<QrResponse>('encode_qr', {
|
||||
text,
|
||||
level: state.config.level,
|
||||
margin: state.config.margin,
|
||||
});
|
||||
dispatch({ type: 'SET_PREVIEW', payload: result });
|
||||
|
||||
// 保存到历史(内存 + 持久化)
|
||||
const entryId = Date.now().toString();
|
||||
const currentMode = modeRef.current;
|
||||
const entry: HistoryEntry = {
|
||||
id: entryId,
|
||||
mode: currentMode,
|
||||
content: sanitizeContent(currentMode, text),
|
||||
timestamp: Date.now(),
|
||||
formData: { ...state.formData },
|
||||
};
|
||||
dispatch({ type: 'ADD_HISTORY', payload: entry });
|
||||
|
||||
// 从内存状态持久化(避免 store 读写竞态)
|
||||
// 注意: dispatch ADD_HISTORY 是异步的,这里手动计算最新列表
|
||||
// 确保持久化的数据与内存一致
|
||||
persistHistory([entry, ...state.history].slice(0, 50));
|
||||
} catch {
|
||||
// 编码失败时清空预览
|
||||
const encode = useCallback(
|
||||
(text: string) => {
|
||||
if (!text.trim()) {
|
||||
dispatch({ type: 'SET_PREVIEW', payload: null });
|
||||
return;
|
||||
}
|
||||
}, 200);
|
||||
}, [state.config.level, state.config.margin, state.formData, state.history, dispatch]);
|
||||
|
||||
dispatch({ type: 'SET_LOADING', payload: true });
|
||||
|
||||
if (timerRef.current) clearTimeout(timerRef.current);
|
||||
timerRef.current = setTimeout(async () => {
|
||||
try {
|
||||
const result = await invoke<QrResponse>('encode_qr', {
|
||||
text,
|
||||
level: state.config.level,
|
||||
margin: state.config.margin,
|
||||
});
|
||||
dispatch({ type: 'SET_PREVIEW', payload: result });
|
||||
|
||||
// 保存到历史(内存 + 持久化)
|
||||
const entryId = Date.now().toString();
|
||||
const currentMode = modeRef.current;
|
||||
const entry: HistoryEntry = {
|
||||
id: entryId,
|
||||
mode: currentMode,
|
||||
content: sanitizeContent(currentMode, text),
|
||||
timestamp: Date.now(),
|
||||
formData: { ...state.formData },
|
||||
};
|
||||
dispatch({ type: 'ADD_HISTORY', payload: entry });
|
||||
|
||||
// 从内存状态持久化(避免 store 读写竞态)
|
||||
// 注意: dispatch ADD_HISTORY 是异步的,这里手动计算最新列表
|
||||
// 确保持久化的数据与内存一致
|
||||
persistHistory([entry, ...state.history].slice(0, 50));
|
||||
} catch {
|
||||
// 编码失败时清空预览
|
||||
dispatch({ type: 'SET_PREVIEW', payload: null });
|
||||
}
|
||||
}, 200);
|
||||
},
|
||||
[state.config.level, state.config.margin, state.formData, state.history, dispatch],
|
||||
);
|
||||
|
||||
return { encode, persistHistory };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user