refactor: 清理 LOW 问题 — 样式去重、死代码删除、命名修正

- 抽取 buttons.ts 共享按钮样式,消除 3 个组件的重复定义
- store 删除未调用的 canUndo/canRedo 方法
- importFromContent 变量 ext→lower 修正确性
- CSV 导出修复 BOM 重复(exportToCsv 自带 BOM)
- Rust error.rs 添加 allow(dead_code) 消除编译警告

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 08:13:17 +08:00
parent d28861ff9c
commit bdbb399ddc
8 changed files with 27 additions and 45 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
use serde::Serialize; use serde::Serialize;
/// 传给前端的统一错误类型(保留供未来使用,当前命令返回 Result<T, String> /// 传给前端的统一错误类型(保留供未来迁移使用,届时所有命令改为返回 Result<T, AppError>
#[allow(dead_code)]
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct AppError { pub struct AppError {
pub message: String, pub message: String,
+1 -8
View File
@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useAppStore } from '@/store/app-store'; import { useAppStore } from '@/store/app-store';
import { btnClass, btnStyle } from '@/components/ui/buttons';
interface ActionButtonsProps { interface ActionButtonsProps {
onNew: () => void; onNew: () => void;
@@ -24,14 +25,6 @@ export function ActionButtons({
const isAdmin = useAppStore((s) => s.isAdmin); const isAdmin = useAppStore((s) => s.isAdmin);
const disabled = !isAdmin; const disabled = !isAdmin;
const btnClass =
'px-3 py-1 text-sm rounded border transition-colors disabled:opacity-40 disabled:cursor-not-allowed';
const btnStyle = {
backgroundColor: 'var(--app-bg)',
color: 'var(--app-fg)',
borderColor: 'var(--app-border)',
};
return ( return (
<div className="flex gap-1 flex-wrap"> <div className="flex gap-1 flex-wrap">
<button className={btnClass} style={btnStyle} disabled={disabled} onClick={onNew}> <button className={btnClass} style={btnStyle} disabled={disabled} onClick={onNew}>
+12 -19
View File
@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useAppStore } from '@/store/app-store'; import { useAppStore } from '@/store/app-store';
import { btnClass, btnStyle } from '@/components/ui/buttons';
import { SearchInput } from './SearchInput'; import { SearchInput } from './SearchInput';
import { ActionButtons } from './ActionButtons'; import { ActionButtons } from './ActionButtons';
import { UndoRedoButtons } from './UndoRedoButtons'; import { UndoRedoButtons } from './UndoRedoButtons';
@@ -26,14 +27,6 @@ export function ToolBar(props: ToolBarProps) {
const isAdmin = useAppStore((s) => s.isAdmin); const isAdmin = useAppStore((s) => s.isAdmin);
const isModified = useAppStore((s) => s.isModified); const isModified = useAppStore((s) => s.isModified);
const sysBtnClass =
'px-3 py-1 text-sm rounded border transition-colors disabled:opacity-40 disabled:cursor-not-allowed';
const sysBtnStyle = {
backgroundColor: 'var(--app-bg)',
color: 'var(--app-fg)',
borderColor: 'var(--app-border)',
};
return ( return (
<div className="space-y-2 pb-2 border-b" style={{ borderColor: 'var(--app-border)' }}> <div className="space-y-2 pb-2 border-b" style={{ borderColor: 'var(--app-border)' }}>
{/* 第一行: 搜索 + 系统按钮 */} {/* 第一行: 搜索 + 系统按钮 */}
@@ -42,38 +35,38 @@ export function ToolBar(props: ToolBarProps) {
<div className="flex-1" /> <div className="flex-1" />
<UndoRedoButtons /> <UndoRedoButtons />
<button <button
className={sysBtnClass} className={btnClass}
style={sysBtnStyle} style={btnStyle}
disabled={!isAdmin} disabled={!isAdmin}
onClick={props.onImport} onClick={props.onImport}
> >
{t('button.import')} {t('button.import')}
</button> </button>
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onExport}> <button className={btnClass} style={btnStyle} onClick={props.onExport}>
{t('button.export')} {t('button.export')}
</button> </button>
<button <button
className={sysBtnClass} className={btnClass}
style={{ style={{
...sysBtnStyle, ...btnStyle,
backgroundColor: isModified ? '#2563eb' : sysBtnStyle.backgroundColor, backgroundColor: isModified ? '#2563eb' : btnStyle.backgroundColor,
color: isModified ? '#fff' : sysBtnStyle.color, color: isModified ? '#fff' : btnStyle.color,
}} }}
disabled={!isAdmin} disabled={!isAdmin}
onClick={props.onSave} onClick={props.onSave}
> >
{t('button.save')} {t('button.save')}
</button> </button>
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onCancel}> <button className={btnClass} style={btnStyle} onClick={props.onCancel}>
{t('button.cancel')} {t('button.cancel')}
</button> </button>
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onHelp}> <button className={btnClass} style={btnStyle} onClick={props.onHelp}>
{t('button.help')} {t('button.help')}
</button> </button>
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onLanguage}> <button className={btnClass} style={btnStyle} onClick={props.onLanguage}>
{t('button.language')} {t('button.language')}
</button> </button>
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onDarkMode}> <button className={btnClass} style={btnStyle} onClick={props.onDarkMode}>
{t('button.darkMode')} {t('button.darkMode')}
</button> </button>
</div> </div>
+1 -8
View File
@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useAppStore } from '@/store/app-store'; import { useAppStore } from '@/store/app-store';
import { btnClass, btnStyle } from '@/components/ui/buttons';
export function UndoRedoButtons() { export function UndoRedoButtons() {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -8,14 +9,6 @@ export function UndoRedoButtons() {
const undo = useAppStore((s) => s.undo); const undo = useAppStore((s) => s.undo);
const redo = useAppStore((s) => s.redo); const redo = useAppStore((s) => s.redo);
const btnClass =
'px-3 py-1 text-sm rounded border transition-colors disabled:opacity-40 disabled:cursor-not-allowed';
const btnStyle = {
backgroundColor: 'var(--app-bg)',
color: 'var(--app-fg)',
borderColor: 'var(--app-border)',
};
return ( return (
<div className="flex gap-1"> <div className="flex gap-1">
<button <button
+7
View File
@@ -0,0 +1,7 @@
export const btnClass = 'px-3 py-1 text-sm rounded border transition-colors disabled:opacity-40 disabled:cursor-not-allowed';
export const btnStyle: React.CSSProperties = {
backgroundColor: 'var(--app-bg)',
color: 'var(--app-fg)',
borderColor: 'var(--app-border)',
};
+3 -3
View File
@@ -193,10 +193,10 @@ export function importFromContent(
content: string, content: string,
filepath: string, filepath: string,
): ImportResult { ): ImportResult {
const ext = filepath.toLowerCase(); const lower = filepath.toLowerCase();
if (ext.endsWith('.csv')) { if (lower.endsWith('.csv')) {
return importFromCsv(content); return importFromCsv(content);
} else if (ext.endsWith('.json')) { } else if (lower.endsWith('.json')) {
return importFromJson(content); return importFromJson(content);
} else { } else {
// TXT 文件:所有路径放入 system(用户后续可选择目标) // TXT 文件:所有路径放入 system(用户后续可选择目标)
+1 -1
View File
@@ -108,7 +108,7 @@ export function useAppActions(activeTab: TabId, dialogs: DialogState) {
const content = isCsv ? exportToCsv(data) : exportToJson(data); const content = isCsv ? exportToCsv(data) : exportToJson(data);
const mime = isCsv ? 'text/csv' : 'application/json'; const mime = isCsv ? 'text/csv' : 'application/json';
const ext = isCsv ? '.csv' : '.json'; const ext = isCsv ? '.csv' : '.json';
const blob = new Blob([isCsv ? '' : '', content], { type: mime }); const blob = new Blob([content], { type: mime });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
const a = document.createElement('a'); const a = document.createElement('a');
a.href = url; a.href = url;
-5
View File
@@ -39,8 +39,6 @@ interface AppState {
undo: () => void; undo: () => void;
redo: () => void; redo: () => void;
canUndo: () => boolean;
canRedo: () => boolean;
loadPaths: () => Promise<void>; loadPaths: () => Promise<void>;
savePaths: () => Promise<void>; savePaths: () => Promise<void>;
@@ -227,9 +225,6 @@ export const useAppStore = create<AppState>((set, get) => ({
set({ isModified: !(arraysEqual(sysPaths, _savedSys) && arraysEqual(userPaths, _savedUser)) }); set({ isModified: !(arraysEqual(sysPaths, _savedSys) && arraysEqual(userPaths, _savedUser)) });
}, },
canUndo: () => get().undoRedo.canUndo(),
canRedo: () => get().undoRedo.canRedo(),
loadPaths: async () => { loadPaths: async () => {
try { try {
set({ isLoading: true }); set({ isLoading: true });