mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-13 07:00:00 +08:00
- Redis 页面重构为工作台样式,统一左右面板、工具条和详情区层级 - 接入 light/dark/透明模式主题参数,修复 Redis 页面与全局主题不一致问题 - 新增文件夹递归勾选、全选全部、分组全选/取消全选能力 - 支持 Redis Key 右键菜单重命名并同步更新树节点、选中态和详情面板 - 修复 type=none 时读取失败问题,过期或已删除 Key 自动提示并移出列表 - 接管 Redis Tree 展开箭头渲染,修复 switcher 命中区错位和悬浮白线问题 - 统一工具、代理、主题、关于、筛选、新建组和新建连接等弹层主题 - refs #231
130 lines
5.8 KiB
TypeScript
130 lines
5.8 KiB
TypeScript
type RedisWorkbenchThemeInput = {
|
|
darkMode: boolean;
|
|
opacity: number;
|
|
blur: number;
|
|
};
|
|
|
|
type RedisWorkbenchTheme = {
|
|
isDark: boolean;
|
|
appBg: string;
|
|
panelBg: string;
|
|
panelBgStrong: string;
|
|
panelBgSubtle: string;
|
|
panelBorder: string;
|
|
panelInset: string;
|
|
toolbarPrimaryBg: string;
|
|
contentEmptyBg: string;
|
|
textPrimary: string;
|
|
textSecondary: string;
|
|
textMuted: string;
|
|
accent: string;
|
|
accentSoft: string;
|
|
accentBorder: string;
|
|
actionSecondaryBg: string;
|
|
actionSecondaryBorder: string;
|
|
actionDangerBg: string;
|
|
actionDangerBorder: string;
|
|
actionDangerText: string;
|
|
statusTagBg: string;
|
|
statusTagBorder: string;
|
|
statusTagMutedBg: string;
|
|
statusTagMutedBorder: string;
|
|
treeHoverBg: string;
|
|
treeSelectedBg: string;
|
|
treeSelectedBorder: string;
|
|
divider: string;
|
|
shadow: string;
|
|
backdropFilter: string;
|
|
};
|
|
|
|
const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));
|
|
|
|
export const buildRedisWorkbenchTheme = ({
|
|
darkMode,
|
|
opacity,
|
|
blur,
|
|
}: RedisWorkbenchThemeInput): RedisWorkbenchTheme => {
|
|
const normalizedOpacity = clamp(opacity, 0.1, 1);
|
|
const normalizedBlur = Math.max(0, Math.round(blur));
|
|
const isTranslucent = normalizedOpacity < 0.999 || normalizedBlur > 0;
|
|
|
|
if (darkMode) {
|
|
const appTopAlpha = isTranslucent ? Math.max(0.08, Math.min(0.22, normalizedOpacity * 0.16)) : 0.92;
|
|
const appBottomAlpha = isTranslucent ? Math.max(0.12, Math.min(0.28, normalizedOpacity * 0.22)) : 0.96;
|
|
const panelAlpha = isTranslucent ? Math.max(0.06, Math.min(0.16, normalizedOpacity * 0.1)) : 0.34;
|
|
const strongAlpha = isTranslucent ? Math.max(0.1, Math.min(0.22, normalizedOpacity * 0.16)) : 0.42;
|
|
const subtleAlpha = isTranslucent ? Math.max(0.03, Math.min(0.08, normalizedOpacity * 0.05)) : 0.08;
|
|
return {
|
|
isDark: true,
|
|
appBg: `linear-gradient(180deg, rgba(15, 15, 17, ${appTopAlpha}) 0%, rgba(11, 11, 13, ${appBottomAlpha}) 100%)`,
|
|
panelBg: `rgba(24, 24, 28, ${panelAlpha})`,
|
|
panelBgStrong: `rgba(31, 31, 36, ${strongAlpha})`,
|
|
panelBgSubtle: `rgba(255, 255, 255, ${subtleAlpha})`,
|
|
panelBorder: `1px solid rgba(255, 255, 255, ${isTranslucent ? Math.max(0.12, Math.min(0.24, normalizedOpacity * 0.2)) : 0.08})`,
|
|
panelInset: `inset 0 1px 0 rgba(255,255,255,${isTranslucent ? Math.max(0.05, Math.min(0.12, normalizedOpacity * 0.1)) : 0.04})`,
|
|
toolbarPrimaryBg: `linear-gradient(135deg, rgba(246,196,83,0.22) 0%, rgba(246,196,83,0.12) 100%)`,
|
|
contentEmptyBg: `linear-gradient(180deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0.015) 100%)`,
|
|
textPrimary: 'rgba(245, 247, 251, 0.96)',
|
|
textSecondary: 'rgba(218, 224, 235, 0.82)',
|
|
textMuted: 'rgba(168, 177, 194, 0.72)',
|
|
accent: '#f6c453',
|
|
accentSoft: 'rgba(246, 196, 83, 0.18)',
|
|
accentBorder: 'rgba(246, 196, 83, 0.3)',
|
|
actionSecondaryBg: 'rgba(255, 255, 255, 0.04)',
|
|
actionSecondaryBorder: 'rgba(255, 255, 255, 0.09)',
|
|
actionDangerBg: 'rgba(255, 95, 95, 0.12)',
|
|
actionDangerBorder: 'rgba(255, 95, 95, 0.28)',
|
|
actionDangerText: '#ff8f8f',
|
|
statusTagBg: 'rgba(25, 106, 255, 0.16)',
|
|
statusTagBorder: 'rgba(25, 106, 255, 0.28)',
|
|
statusTagMutedBg: 'rgba(255, 255, 255, 0.04)',
|
|
statusTagMutedBorder: 'rgba(255, 255, 255, 0.08)',
|
|
treeHoverBg: 'rgba(255, 255, 255, 0.045)',
|
|
treeSelectedBg: 'linear-gradient(90deg, rgba(246,196,83,0.2) 0%, rgba(246,196,83,0.08) 100%)',
|
|
treeSelectedBorder: 'rgba(246, 196, 83, 0.24)',
|
|
divider: 'rgba(255, 255, 255, 0.07)',
|
|
shadow: '0 20px 48px rgba(0, 0, 0, 0.26)',
|
|
backdropFilter: normalizedBlur > 0 ? `blur(${normalizedBlur}px)` : 'none',
|
|
};
|
|
}
|
|
|
|
const appTopAlpha = isTranslucent ? Math.max(0.16, Math.min(0.36, normalizedOpacity * 0.24)) : 0.98;
|
|
const appBottomAlpha = isTranslucent ? Math.max(0.22, Math.min(0.44, normalizedOpacity * 0.32)) : 0.96;
|
|
const panelAlpha = isTranslucent ? Math.max(0.18, Math.min(0.4, normalizedOpacity * 0.26)) : 0.94;
|
|
const strongAlpha = isTranslucent ? Math.max(0.26, Math.min(0.52, normalizedOpacity * 0.34)) : 0.98;
|
|
return {
|
|
isDark: false,
|
|
appBg: `linear-gradient(180deg, rgba(248, 250, 252, ${appTopAlpha}) 0%, rgba(242, 245, 248, ${appBottomAlpha}) 100%)`,
|
|
panelBg: `rgba(255, 255, 255, ${panelAlpha})`,
|
|
panelBgStrong: `rgba(255, 255, 255, ${strongAlpha})`,
|
|
panelBgSubtle: 'rgba(15, 23, 42, 0.03)',
|
|
panelBorder: `1px solid rgba(15, 23, 42, ${isTranslucent ? Math.max(0.1, Math.min(0.18, normalizedOpacity * 0.12)) : 0.08})`,
|
|
panelInset: `inset 0 1px 0 rgba(255,255,255,${isTranslucent ? 0.38 : 0.72})`,
|
|
toolbarPrimaryBg: 'linear-gradient(135deg, rgba(22,119,255,0.12) 0%, rgba(22,119,255,0.06) 100%)',
|
|
contentEmptyBg: 'linear-gradient(180deg, rgba(15,23,42,0.02) 0%, rgba(15,23,42,0.01) 100%)',
|
|
textPrimary: 'rgba(15, 23, 42, 0.92)',
|
|
textSecondary: 'rgba(51, 65, 85, 0.82)',
|
|
textMuted: 'rgba(100, 116, 139, 0.76)',
|
|
accent: '#1677ff',
|
|
accentSoft: 'rgba(22, 119, 255, 0.12)',
|
|
accentBorder: 'rgba(22, 119, 255, 0.22)',
|
|
actionSecondaryBg: 'rgba(255, 255, 255, 0.72)',
|
|
actionSecondaryBorder: 'rgba(15, 23, 42, 0.08)',
|
|
actionDangerBg: 'rgba(255, 77, 79, 0.08)',
|
|
actionDangerBorder: 'rgba(255, 77, 79, 0.24)',
|
|
actionDangerText: '#cf1322',
|
|
statusTagBg: 'rgba(22, 119, 255, 0.1)',
|
|
statusTagBorder: 'rgba(22, 119, 255, 0.16)',
|
|
statusTagMutedBg: 'rgba(15, 23, 42, 0.04)',
|
|
statusTagMutedBorder: 'rgba(15, 23, 42, 0.08)',
|
|
treeHoverBg: 'rgba(15, 23, 42, 0.035)',
|
|
treeSelectedBg: 'linear-gradient(90deg, rgba(22,119,255,0.12) 0%, rgba(22,119,255,0.05) 100%)',
|
|
treeSelectedBorder: 'rgba(22, 119, 255, 0.18)',
|
|
divider: 'rgba(15, 23, 42, 0.08)',
|
|
shadow: '0 22px 52px rgba(15, 23, 42, 0.08)',
|
|
backdropFilter: normalizedBlur > 0 ? `blur(${normalizedBlur}px)` : 'none',
|
|
};
|
|
};
|
|
|
|
export type { RedisWorkbenchTheme, RedisWorkbenchThemeInput };
|