refactor: 统一中文文案并简化组件结构,提升代码可读性

移除 chrome.i18n 后,将各功能页面、布局与工具模块的 UI 文案改为内联中文;
删除冗余注释与过度抽象(如 ToolCard、StatCard),精简 props 与状态管理;
同步优化 JsonTools、StorageCleaner、Timestamp、TestDataGenerator、Dashboard、
Base64Converter、RightClickRestorer、TextStatistics、TopBar、RouterProvider、
ThemeModeProvider 及生成器库与 utils 工具文件。
This commit is contained in:
雨霖铃
2026-06-27 10:49:36 +08:00
parent f3a9838017
commit d38bafe237
85 changed files with 324 additions and 864 deletions
+2 -6
View File
@@ -1,4 +1,3 @@
import React from 'react';
import { type FeatureConfig } from '@/config/features';
import { cn } from '@/lib/utils';
@@ -8,7 +7,7 @@ interface SearchResultItemProps {
onSelect: (feature: FeatureConfig) => void;
}
const SearchResultItem = React.memo(({ feature, selected, onSelect }: SearchResultItemProps) => {
export default function SearchResultItem({ feature, selected, onSelect }: SearchResultItemProps) {
return (
<li
role="option"
@@ -28,7 +27,4 @@ const SearchResultItem = React.memo(({ feature, selected, onSelect }: SearchResu
</div>
</li>
);
});
SearchResultItem.displayName = 'SearchResultItem';
export default SearchResultItem;
}
-2
View File
@@ -4,8 +4,6 @@ export const SEARCH_HISTORY_DISPLAY = 5;
export const isSearchHistory = (val: unknown): val is string[] =>
Array.isArray(val) && val.every((item) => typeof item === 'string');
/** 根据平台返回搜索框快捷键提示文案 */
export function getSearchShortcutLabel(): string {
if (typeof navigator === 'undefined') return 'Ctrl+K';
return /Mac|iPhone|iPad|iPod/i.test(navigator.userAgent) ? '⌘K' : 'Ctrl+K';
}
+4 -13
View File
@@ -8,18 +8,17 @@ import { useTopBar } from './useTopBar';
export default function TopBar() {
const {
searchQuery,
showResults,
searchResults,
recentFeatures,
selectedIndex,
isDashboard,
ThemeIcon,
themeTitle,
showDropdown,
containerRef,
inputRef,
setSearchQuery,
setShowResults,
setSelectedIndex,
handleSearchQueryChange,
handleSearchFocus,
handleSelectFeature,
handleKeyDown,
cycleThemeMode,
@@ -40,14 +39,6 @@ export default function TopBar() {
},
];
const handleSearchQueryChange = (value: string) => {
setSearchQuery(value);
setShowResults(true);
setSelectedIndex(-1);
};
const showDropdown = showResults && (searchQuery.trim() || recentFeatures.length > 0);
return (
<header className="relative z-50 flex h-14 items-center justify-between border-b border-border bg-background px-4">
<div className="flex w-10 items-center justify-start">
@@ -70,7 +61,7 @@ export default function TopBar() {
inputRef={inputRef}
searchQuery={searchQuery}
onSearchQueryChange={handleSearchQueryChange}
onFocus={() => setShowResults(true)}
onFocus={handleSearchFocus}
onKeyDown={handleKeyDown}
onClear={clearSearch}
/>
+25 -21
View File
@@ -9,18 +9,17 @@ import { isSearchHistory, SEARCH_HISTORY_DISPLAY, SEARCH_HISTORY_LIMIT } from '.
export interface UseTopBarReturn {
searchQuery: string;
showResults: boolean;
searchResults: FeatureConfig[];
recentFeatures: FeatureConfig[];
selectedIndex: number;
isDashboard: boolean;
ThemeIcon: typeof Sun;
themeTitle: string;
showDropdown: boolean;
containerRef: RefObject<HTMLDivElement | null>;
inputRef: RefObject<HTMLInputElement | null>;
setSearchQuery: (value: string) => void;
setShowResults: (value: boolean) => void;
setSelectedIndex: (value: number | ((prev: number) => number)) => void;
handleSearchQueryChange: (value: string) => void;
handleSearchFocus: () => void;
handleSelectFeature: (feature: FeatureConfig) => void;
handleKeyDown: (e: React.KeyboardEvent) => void;
cycleThemeMode: () => void;
@@ -90,7 +89,6 @@ export function useTopBar(): UseTopBarReturn {
}, [searchHistory, searchQuery]);
const saveToHistory = (featureKey: string) => {
if (!featureKey.trim()) return;
setSearchHistory((prev) =>
[featureKey, ...prev.filter((h) => h !== featureKey)].slice(0, SEARCH_HISTORY_LIMIT),
);
@@ -124,18 +122,14 @@ export function useTopBar(): UseTopBarReturn {
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : prev));
} else if (e.key === 'Enter') {
e.preventDefault();
if (selectedIndex >= 0 && selectedIndex < totalItems) {
if (searchQuery.trim()) {
handleSelectFeature(searchResults[selectedIndex]);
} else {
const selected = displayedHistory[selectedIndex];
if (selected) {
handleSelectFeature(selected);
}
}
} else if (searchQuery.trim() && searchResults.length > 0) {
handleSelectFeature(searchResults[0]);
}
const items = searchQuery.trim() ? searchResults : displayedHistory;
const feature =
selectedIndex >= 0 && selectedIndex < totalItems
? items[selectedIndex]
: searchQuery.trim() && searchResults.length > 0
? searchResults[0]
: undefined;
if (feature) handleSelectFeature(feature);
} else if (e.key === 'Escape') {
setShowResults(false);
inputRef.current?.blur();
@@ -147,20 +141,30 @@ export function useTopBar(): UseTopBarReturn {
setSelectedIndex(-1);
};
const handleSearchQueryChange = (value: string) => {
setSearchQuery(value);
setShowResults(true);
setSelectedIndex(-1);
};
const handleSearchFocus = () => setShowResults(true);
const showDropdown =
showResults && (searchQuery.trim().length > 0 || displayedHistory.length > 0);
return {
searchQuery,
showResults,
searchResults,
recentFeatures: displayedHistory,
selectedIndex,
showDropdown,
isDashboard: currentPage === 'dashboard',
ThemeIcon,
themeTitle,
containerRef,
inputRef,
setSearchQuery,
setShowResults,
setSelectedIndex,
handleSearchQueryChange,
handleSearchFocus,
handleSelectFeature,
handleKeyDown,
cycleThemeMode,