= ({
buttonStyles.icon,
isCurrent
? "text-gray-400 cursor-not-allowed"
- : "text-gray-500 hover:text-red-500 hover:bg-red-100 dark:text-gray-400 dark:hover:text-red-400 dark:hover:bg-red-500/10"
+ : "text-gray-500 hover:text-red-500 hover:bg-red-100 dark:text-gray-400 dark:hover:text-red-400 dark:hover:bg-red-500/10",
)}
title="删除供应商"
>
diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx
index 3e74e78..af63f1c 100644
--- a/src/components/SettingsModal.tsx
+++ b/src/components/SettingsModal.tsx
@@ -141,7 +141,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
// 如果未知或为空,回退到 releases 首页
if (!targetVersion || targetVersion === "未知") {
await window.api.openExternal(
- "https://github.com/farion1231/cc-switch/releases"
+ "https://github.com/farion1231/cc-switch/releases",
);
return;
}
@@ -149,7 +149,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
? targetVersion
: `v${targetVersion}`;
await window.api.openExternal(
- `https://github.com/farion1231/cc-switch/releases/tag/${tag}`
+ `https://github.com/farion1231/cc-switch/releases/tag/${tag}`,
);
} catch (error) {
console.error("打开更新日志失败:", error);
diff --git a/src/components/UpdateBadge.tsx b/src/components/UpdateBadge.tsx
index 21fa340..e0333fa 100644
--- a/src/components/UpdateBadge.tsx
+++ b/src/components/UpdateBadge.tsx
@@ -8,12 +8,12 @@ interface UpdateBadgeProps {
export function UpdateBadge({ className = "", onClick }: UpdateBadgeProps) {
const { hasUpdate, updateInfo, isDismissed, dismissUpdate } = useUpdate();
-
+
// 如果没有更新或已关闭,不显示
if (!hasUpdate || isDismissed || !updateInfo) {
return null;
}
-
+
return (
void;
-
+
// 操作方法
checkUpdate: () => Promise;
resetDismiss: () => void;
@@ -31,7 +38,7 @@ export function UpdateProvider({ children }: { children: React.ReactNode }) {
const [isChecking, setIsChecking] = useState(false);
const [error, setError] = useState(null);
const [isDismissed, setIsDismissed] = useState(false);
-
+
// 从 localStorage 读取已关闭的版本
useEffect(() => {
const current = updateInfo?.availableVersion;
@@ -50,7 +57,7 @@ export function UpdateProvider({ children }: { children: React.ReactNode }) {
setIsDismissed(dismissedVersion === current);
}, [updateInfo?.availableVersion]);
-
+
const isCheckingRef = useRef(false);
const checkUpdate = useCallback(async () => {
@@ -96,7 +103,7 @@ export function UpdateProvider({ children }: { children: React.ReactNode }) {
isCheckingRef.current = false;
}
}, []);
-
+
const dismissUpdate = useCallback(() => {
setIsDismissed(true);
if (updateInfo?.availableVersion) {
@@ -105,13 +112,13 @@ export function UpdateProvider({ children }: { children: React.ReactNode }) {
localStorage.removeItem(LEGACY_DISMISSED_KEY);
}
}, [updateInfo?.availableVersion]);
-
+
const resetDismiss = useCallback(() => {
setIsDismissed(false);
localStorage.removeItem(DISMISSED_VERSION_KEY);
localStorage.removeItem(LEGACY_DISMISSED_KEY);
}, []);
-
+
// 应用启动时自动检查更新
useEffect(() => {
// 延迟1秒后检查,避免影响启动体验
@@ -121,7 +128,7 @@ export function UpdateProvider({ children }: { children: React.ReactNode }) {
return () => clearTimeout(timer);
}, [checkUpdate]);
-
+
const value: UpdateContextValue = {
hasUpdate,
updateInfo,
@@ -133,11 +140,9 @@ export function UpdateProvider({ children }: { children: React.ReactNode }) {
checkUpdate,
resetDismiss,
};
-
+
return (
-
- {children}
-
+ {children}
);
}
diff --git a/src/hooks/useDarkMode.ts b/src/hooks/useDarkMode.ts
index 80db257..affe45b 100644
--- a/src/hooks/useDarkMode.ts
+++ b/src/hooks/useDarkMode.ts
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect } from "react";
export function useDarkMode() {
// 初始设为 false,挂载后在 useEffect 中加载真实值
@@ -7,49 +7,51 @@ export function useDarkMode() {
// 组件挂载后加载初始值(兼容 Tauri 环境)
useEffect(() => {
- if (typeof window === 'undefined') return;
-
+ if (typeof window === "undefined") return;
+
try {
// 尝试读取已保存的偏好
- const saved = localStorage.getItem('darkMode');
+ const saved = localStorage.getItem("darkMode");
if (saved !== null) {
- const savedBool = saved === 'true';
+ const savedBool = saved === "true";
setIsDarkMode(savedBool);
- console.log('[DarkMode] Loaded from localStorage:', savedBool);
+ console.log("[DarkMode] Loaded from localStorage:", savedBool);
} else {
// 回退到系统偏好
- const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
+ const prefersDark =
+ window.matchMedia &&
+ window.matchMedia("(prefers-color-scheme: dark)").matches;
setIsDarkMode(prefersDark);
- console.log('[DarkMode] Using system preference:', prefersDark);
+ console.log("[DarkMode] Using system preference:", prefersDark);
}
} catch (error) {
- console.error('[DarkMode] Error loading preference:', error);
+ console.error("[DarkMode] Error loading preference:", error);
setIsDarkMode(false);
}
-
+
setIsInitialized(true);
}, []); // 仅在首次挂载时运行
// 将 dark 类应用到文档根节点
useEffect(() => {
if (!isInitialized) return;
-
+
// 添加短暂延迟以确保 Tauri 中 DOM 已就绪
const timer = setTimeout(() => {
try {
if (isDarkMode) {
- document.documentElement.classList.add('dark');
- console.log('[DarkMode] Added dark class to document');
+ document.documentElement.classList.add("dark");
+ console.log("[DarkMode] Added dark class to document");
} else {
- document.documentElement.classList.remove('dark');
- console.log('[DarkMode] Removed dark class from document');
+ document.documentElement.classList.remove("dark");
+ console.log("[DarkMode] Removed dark class from document");
}
-
+
// 检查类名是否已成功应用
- const hasClass = document.documentElement.classList.contains('dark');
- console.log('[DarkMode] Document has dark class:', hasClass);
+ const hasClass = document.documentElement.classList.contains("dark");
+ console.log("[DarkMode] Document has dark class:", hasClass);
} catch (error) {
- console.error('[DarkMode] Error applying dark class:', error);
+ console.error("[DarkMode] Error applying dark class:", error);
}
}, 0);
@@ -59,19 +61,19 @@ export function useDarkMode() {
// 将偏好保存到 localStorage
useEffect(() => {
if (!isInitialized) return;
-
+
try {
- localStorage.setItem('darkMode', isDarkMode.toString());
- console.log('[DarkMode] Saved to localStorage:', isDarkMode);
+ localStorage.setItem("darkMode", isDarkMode.toString());
+ console.log("[DarkMode] Saved to localStorage:", isDarkMode);
} catch (error) {
- console.error('[DarkMode] Error saving preference:', error);
+ console.error("[DarkMode] Error saving preference:", error);
}
}, [isDarkMode, isInitialized]);
const toggleDarkMode = () => {
- setIsDarkMode(prev => {
+ setIsDarkMode((prev) => {
const newValue = !prev;
- console.log('[DarkMode] Toggling from', prev, 'to', newValue);
+ console.log("[DarkMode] Toggling from", prev, "to", newValue);
return newValue;
});
};
diff --git a/src/index.css b/src/index.css
index f49d0d2..f1c8027 100644
--- a/src/index.css
+++ b/src/index.css
@@ -21,7 +21,9 @@ body {
}
/* 暗色模式下启用暗色原生控件/滚动条配色 */
-html.dark { color-scheme: dark; }
+html.dark {
+ color-scheme: dark;
+}
/* 滚动条样式 */
::-webkit-scrollbar {
diff --git a/src/lib/styles.ts b/src/lib/styles.ts
index 952f3bc..075fe78 100644
--- a/src/lib/styles.ts
+++ b/src/lib/styles.ts
@@ -5,20 +5,24 @@
// 按钮样式
export const buttonStyles = {
// 主按钮:蓝底白字
- primary: "px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 transition-colors text-sm font-medium",
-
+ primary:
+ "px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 transition-colors text-sm font-medium",
+
// 次按钮:灰背景,深色文本
- secondary: "px-4 py-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200 rounded-lg transition-colors text-sm font-medium",
-
+ secondary:
+ "px-4 py-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200 rounded-lg transition-colors text-sm font-medium",
+
// 危险按钮:用于不可撤销/破坏性操作
- danger: "px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-600 dark:hover:bg-red-700 transition-colors text-sm font-medium",
-
+ danger:
+ "px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 dark:bg-red-600 dark:hover:bg-red-700 transition-colors text-sm font-medium",
+
// 幽灵按钮:无背景,仅悬浮反馈
- ghost: "px-4 py-2 text-gray-500 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors text-sm font-medium",
-
+ ghost:
+ "px-4 py-2 text-gray-500 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors text-sm font-medium",
+
// 图标按钮:小尺寸,仅图标
icon: "p-1.5 text-gray-500 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-800 rounded-md transition-colors",
-
+
// 禁用态:可与其他样式组合
disabled: "opacity-50 cursor-not-allowed pointer-events-none",
} as const;
@@ -27,42 +31,49 @@ export const buttonStyles = {
export const cardStyles = {
// 基础卡片容器
base: "bg-white rounded-lg border border-gray-200 p-4 dark:bg-gray-900 dark:border-gray-700",
-
+
// 带悬浮效果的卡片
- interactive: "bg-white rounded-lg border border-gray-200 p-4 hover:border-gray-300 hover:shadow-sm dark:bg-gray-900 dark:border-gray-700 dark:hover:border-gray-600 transition-all duration-200",
-
+ interactive:
+ "bg-white rounded-lg border border-gray-200 p-4 hover:border-gray-300 hover:shadow-sm dark:bg-gray-900 dark:border-gray-700 dark:hover:border-gray-600 transition-all duration-200",
+
// 选中/激活态卡片
- selected: "bg-white rounded-lg border border-blue-500 ring-1 ring-blue-500/20 bg-blue-500/5 p-4 dark:bg-gray-900 dark:border-blue-400 dark:ring-blue-400/20 dark:bg-blue-400/10",
+ selected:
+ "bg-white rounded-lg border border-blue-500 ring-1 ring-blue-500/20 bg-blue-500/5 p-4 dark:bg-gray-900 dark:border-blue-400 dark:ring-blue-400/20 dark:bg-blue-400/10",
} as const;
// 输入控件样式
export const inputStyles = {
// 文本输入框
text: "w-full px-3 py-2 border border-gray-200 rounded-lg focus:border-blue-500 focus:ring-1 focus:ring-blue-500/20 outline-none dark:bg-gray-900 dark:border-gray-700 dark:text-gray-100 dark:focus:border-blue-400 dark:focus:ring-blue-400/20 transition-colors",
-
+
// 下拉选择框
- select: "w-full px-3 py-2 border border-gray-200 rounded-lg focus:border-blue-500 focus:ring-1 focus:ring-blue-500/20 outline-none bg-white dark:bg-gray-900 dark:border-gray-700 dark:text-gray-100 dark:focus:border-blue-400 dark:focus:ring-blue-400/20 transition-colors",
-
+ select:
+ "w-full px-3 py-2 border border-gray-200 rounded-lg focus:border-blue-500 focus:ring-1 focus:ring-blue-500/20 outline-none bg-white dark:bg-gray-900 dark:border-gray-700 dark:text-gray-100 dark:focus:border-blue-400 dark:focus:ring-blue-400/20 transition-colors",
+
// 复选框
- checkbox: "w-4 h-4 text-blue-500 rounded focus:ring-blue-500/20 border-gray-300 dark:border-gray-600 dark:bg-gray-800",
+ checkbox:
+ "w-4 h-4 text-blue-500 rounded focus:ring-blue-500/20 border-gray-300 dark:border-gray-600 dark:bg-gray-800",
} as const;
// 徽标(Badge)样式
export const badgeStyles = {
// 成功徽标
- success: "inline-flex items-center gap-1 px-2 py-1 bg-green-500/10 text-green-500 rounded-md text-xs font-medium",
-
+ success:
+ "inline-flex items-center gap-1 px-2 py-1 bg-green-500/10 text-green-500 rounded-md text-xs font-medium",
+
// 信息徽标
info: "inline-flex items-center gap-1 px-2 py-1 bg-blue-500/10 text-blue-500 rounded-md text-xs font-medium",
-
+
// 警告徽标
- warning: "inline-flex items-center gap-1 px-2 py-1 bg-amber-500/10 text-amber-500 rounded-md text-xs font-medium",
-
+ warning:
+ "inline-flex items-center gap-1 px-2 py-1 bg-amber-500/10 text-amber-500 rounded-md text-xs font-medium",
+
// 错误徽标
- error: "inline-flex items-center gap-1 px-2 py-1 bg-red-500/10 text-red-500 rounded-md text-xs font-medium",
+ error:
+ "inline-flex items-center gap-1 px-2 py-1 bg-red-500/10 text-red-500 rounded-md text-xs font-medium",
} as const;
// 组合类名的工具函数
export function cn(...classes: (string | undefined | false)[]) {
- return classes.filter(Boolean).join(' ');
+ return classes.filter(Boolean).join(" ");
}