mirror of
https://github.com/LHY0125/PathEditor.git
synced 2026-06-28 17:25:54 +08:00
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:
@@ -1,6 +1,7 @@
|
||||
use serde::Serialize;
|
||||
|
||||
/// 传给前端的统一错误类型(保留供未来使用,当前命令返回 Result<T, String>)
|
||||
/// 传给前端的统一错误类型(保留供未来迁移使用,届时所有命令改为返回 Result<T, AppError>)
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct AppError {
|
||||
pub message: String,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { btnClass, btnStyle } from '@/components/ui/buttons';
|
||||
|
||||
interface ActionButtonsProps {
|
||||
onNew: () => void;
|
||||
@@ -24,14 +25,6 @@ export function ActionButtons({
|
||||
const isAdmin = useAppStore((s) => s.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 (
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
<button className={btnClass} style={btnStyle} disabled={disabled} onClick={onNew}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { btnClass, btnStyle } from '@/components/ui/buttons';
|
||||
import { SearchInput } from './SearchInput';
|
||||
import { ActionButtons } from './ActionButtons';
|
||||
import { UndoRedoButtons } from './UndoRedoButtons';
|
||||
@@ -26,14 +27,6 @@ export function ToolBar(props: ToolBarProps) {
|
||||
const isAdmin = useAppStore((s) => s.isAdmin);
|
||||
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 (
|
||||
<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" />
|
||||
<UndoRedoButtons />
|
||||
<button
|
||||
className={sysBtnClass}
|
||||
style={sysBtnStyle}
|
||||
className={btnClass}
|
||||
style={btnStyle}
|
||||
disabled={!isAdmin}
|
||||
onClick={props.onImport}
|
||||
>
|
||||
{t('button.import')}
|
||||
</button>
|
||||
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onExport}>
|
||||
<button className={btnClass} style={btnStyle} onClick={props.onExport}>
|
||||
{t('button.export')}
|
||||
</button>
|
||||
<button
|
||||
className={sysBtnClass}
|
||||
className={btnClass}
|
||||
style={{
|
||||
...sysBtnStyle,
|
||||
backgroundColor: isModified ? '#2563eb' : sysBtnStyle.backgroundColor,
|
||||
color: isModified ? '#fff' : sysBtnStyle.color,
|
||||
...btnStyle,
|
||||
backgroundColor: isModified ? '#2563eb' : btnStyle.backgroundColor,
|
||||
color: isModified ? '#fff' : btnStyle.color,
|
||||
}}
|
||||
disabled={!isAdmin}
|
||||
onClick={props.onSave}
|
||||
>
|
||||
{t('button.save')}
|
||||
</button>
|
||||
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onCancel}>
|
||||
<button className={btnClass} style={btnStyle} onClick={props.onCancel}>
|
||||
{t('button.cancel')}
|
||||
</button>
|
||||
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onHelp}>
|
||||
<button className={btnClass} style={btnStyle} onClick={props.onHelp}>
|
||||
{t('button.help')}
|
||||
</button>
|
||||
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onLanguage}>
|
||||
<button className={btnClass} style={btnStyle} onClick={props.onLanguage}>
|
||||
{t('button.language')}
|
||||
</button>
|
||||
<button className={sysBtnClass} style={sysBtnStyle} onClick={props.onDarkMode}>
|
||||
<button className={btnClass} style={btnStyle} onClick={props.onDarkMode}>
|
||||
{t('button.darkMode')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppStore } from '@/store/app-store';
|
||||
import { btnClass, btnStyle } from '@/components/ui/buttons';
|
||||
|
||||
export function UndoRedoButtons() {
|
||||
const { t } = useTranslation();
|
||||
@@ -8,14 +9,6 @@ export function UndoRedoButtons() {
|
||||
const undo = useAppStore((s) => s.undo);
|
||||
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 (
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
|
||||
@@ -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)',
|
||||
};
|
||||
@@ -193,10 +193,10 @@ export function importFromContent(
|
||||
content: string,
|
||||
filepath: string,
|
||||
): ImportResult {
|
||||
const ext = filepath.toLowerCase();
|
||||
if (ext.endsWith('.csv')) {
|
||||
const lower = filepath.toLowerCase();
|
||||
if (lower.endsWith('.csv')) {
|
||||
return importFromCsv(content);
|
||||
} else if (ext.endsWith('.json')) {
|
||||
} else if (lower.endsWith('.json')) {
|
||||
return importFromJson(content);
|
||||
} else {
|
||||
// TXT 文件:所有路径放入 system(用户后续可选择目标)
|
||||
|
||||
@@ -108,7 +108,7 @@ export function useAppActions(activeTab: TabId, dialogs: DialogState) {
|
||||
const content = isCsv ? exportToCsv(data) : exportToJson(data);
|
||||
const mime = isCsv ? 'text/csv' : 'application/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 a = document.createElement('a');
|
||||
a.href = url;
|
||||
|
||||
@@ -39,8 +39,6 @@ interface AppState {
|
||||
|
||||
undo: () => void;
|
||||
redo: () => void;
|
||||
canUndo: () => boolean;
|
||||
canRedo: () => boolean;
|
||||
|
||||
loadPaths: () => Promise<void>;
|
||||
savePaths: () => Promise<void>;
|
||||
@@ -227,9 +225,6 @@ export const useAppStore = create<AppState>((set, get) => ({
|
||||
set({ isModified: !(arraysEqual(sysPaths, _savedSys) && arraysEqual(userPaths, _savedUser)) });
|
||||
},
|
||||
|
||||
canUndo: () => get().undoRedo.canUndo(),
|
||||
canRedo: () => get().undoRedo.canRedo(),
|
||||
|
||||
loadPaths: async () => {
|
||||
try {
|
||||
set({ isLoading: true });
|
||||
|
||||
Reference in New Issue
Block a user