diff --git a/build/darwin/Info.dev.plist b/build/darwin/Info.dev.plist new file mode 100644 index 0000000..14121ef --- /dev/null +++ b/build/darwin/Info.dev.plist @@ -0,0 +1,68 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{.Info.ProductName}} + CFBundleExecutable + {{.OutputFilename}} + CFBundleIdentifier + com.wails.{{.Name}} + CFBundleVersion + {{.Info.ProductVersion}} + CFBundleGetInfoString + {{.Info.Comments}} + CFBundleShortVersionString + {{.Info.ProductVersion}} + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + {{.Info.Copyright}} + {{if .Info.FileAssociations}} + CFBundleDocumentTypes + + {{range .Info.FileAssociations}} + + CFBundleTypeExtensions + + {{.Ext}} + + CFBundleTypeName + {{.Name}} + CFBundleTypeRole + {{.Role}} + CFBundleTypeIconFile + {{.IconName}} + + {{end}} + + {{end}} + {{if .Info.Protocols}} + CFBundleURLTypes + + {{range .Info.Protocols}} + + CFBundleURLName + com.wails.{{.Scheme}} + CFBundleURLSchemes + + {{.Scheme}} + + CFBundleTypeRole + {{.Role}} + + {{end}} + + {{end}} + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + diff --git a/build/darwin/Info.plist b/build/darwin/Info.plist new file mode 100644 index 0000000..d17a747 --- /dev/null +++ b/build/darwin/Info.plist @@ -0,0 +1,63 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{.Info.ProductName}} + CFBundleExecutable + {{.OutputFilename}} + CFBundleIdentifier + com.wails.{{.Name}} + CFBundleVersion + {{.Info.ProductVersion}} + CFBundleGetInfoString + {{.Info.Comments}} + CFBundleShortVersionString + {{.Info.ProductVersion}} + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + {{.Info.Copyright}} + {{if .Info.FileAssociations}} + CFBundleDocumentTypes + + {{range .Info.FileAssociations}} + + CFBundleTypeExtensions + + {{.Ext}} + + CFBundleTypeName + {{.Name}} + CFBundleTypeRole + {{.Role}} + CFBundleTypeIconFile + {{.IconName}} + + {{end}} + + {{end}} + {{if .Info.Protocols}} + CFBundleURLTypes + + {{range .Info.Protocols}} + + CFBundleURLName + com.wails.{{.Scheme}} + CFBundleURLSchemes + + {{.Scheme}} + + CFBundleTypeRole + {{.Role}} + + {{end}} + + {{end}} + + diff --git a/build/darwin/icon.icns b/build/darwin/icon.icns new file mode 100644 index 0000000..ceac95f Binary files /dev/null and b/build/darwin/icon.icns differ diff --git a/frontend/src/App.css b/frontend/src/App.css index b8e73f2..e34d510 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -6,6 +6,10 @@ html, body, #root { background-color: transparent !important; /* CRITICAL: Allow Wails window transparency */ } +body, #root { + border-radius: 14px; /* Slightly rounded app window corners */ +} + /* 侧边栏 Tree 样式优化 */ .ant-tree .ant-tree-treenode { width: 100%; diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 162c895..77e545d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -9,6 +9,7 @@ import DataSyncModal from './components/DataSyncModal'; import LogPanel from './components/LogPanel'; import { useStore } from './store'; import { SavedConnection } from './types'; +import { blurToFilter, normalizeBlurForPlatform, normalizeOpacityForPlatform } from './utils/appearance'; import './App.css'; const { Sider, Content } = Layout; @@ -22,17 +23,21 @@ function App() { const appearance = useStore(state => state.appearance); const setAppearance = useStore(state => state.setAppearance); const darkMode = themeMode === 'dark'; + const effectiveOpacity = normalizeOpacityForPlatform(appearance.opacity); + const effectiveBlur = normalizeBlurForPlatform(appearance.blur); + const blurFilter = blurToFilter(effectiveBlur); + const windowCornerRadius = 14; // Background Helper const getBg = (darkHex: string, lightHex: string) => { - if (!darkMode) return `rgba(255, 255, 255, ${appearance.opacity ?? 0.95})`; // Light mode usually white + if (!darkMode) return `rgba(255, 255, 255, ${effectiveOpacity})`; // Light mode usually white // Parse hex to rgb const hex = darkHex.replace('#', ''); const r = parseInt(hex.substring(0, 2), 16); const g = parseInt(hex.substring(2, 4), 16); const b = parseInt(hex.substring(4, 6), 16); - return `rgba(${r}, ${g}, ${b}, ${appearance.opacity ?? 0.95})`; + return `rgba(${r}, ${g}, ${b}, ${effectiveOpacity})`; }; // Specific colors const bgMain = getBg('#141414', '#ffffff'); @@ -386,13 +391,9 @@ function App() { }; useEffect(() => { - if (darkMode) { - document.body.style.backgroundColor = '#141414'; - document.body.style.color = '#ffffff'; - } else { - document.body.style.backgroundColor = '#ffffff'; - document.body.style.color = '#000000'; - } + document.body.style.backgroundColor = 'transparent'; + document.body.style.color = darkMode ? '#ffffff' : '#000000'; + document.body.setAttribute('data-theme', darkMode ? 'dark' : 'light'); }, [darkMode]); useEffect(() => { @@ -429,14 +430,14 @@ function App() { token: { colorBgLayout: 'transparent', colorBgContainer: darkMode - ? `rgba(29, 29, 29, ${appearance.opacity ?? 0.95})` - : `rgba(255, 255, 255, ${appearance.opacity ?? 0.95})`, + ? `rgba(29, 29, 29, ${effectiveOpacity})` + : `rgba(255, 255, 255, ${effectiveOpacity})`, colorBgElevated: darkMode ? '#1f1f1f' : '#ffffff', colorFillAlter: darkMode - ? `rgba(38, 38, 38, ${appearance.opacity ?? 0.95})` - : `rgba(250, 250, 250, ${appearance.opacity ?? 0.95})`, + ? `rgba(38, 38, 38, ${effectiveOpacity})` + : `rgba(250, 250, 250, ${effectiveOpacity})`, }, components: { Layout: { @@ -464,7 +465,10 @@ function App() { display: 'flex', flexDirection: 'column', background: 'transparent', - backdropFilter: `blur(${appearance.blur ?? 0}px)` + borderRadius: windowCornerRadius, + clipPath: `inset(0 round ${windowCornerRadius}px)`, + backdropFilter: blurFilter, + WebkitBackdropFilter: blurFilter, }}> {/* Custom Title Bar */}
@@ -585,7 +591,7 @@ function App() { /> -
+
{isLogPanelOpen && ( diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index c27aa32..f0ec973 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -9,6 +9,7 @@ import { useStore } from '../store'; import { v4 as uuidv4 } from 'uuid'; import 'react-resizable/css/styles.css'; import { buildWhereSQL, escapeLiteral, quoteIdentPart, quoteQualifiedIdent } from '../utils/sql'; +import { blurToFilter, normalizeBlurForPlatform, normalizeOpacityForPlatform } from '../utils/appearance'; // 内部行标识字段:避免与真实业务字段(如 `key` 列)冲突。 export const GONAVI_ROW_KEY = '__gonavi_row_key__'; @@ -359,7 +360,9 @@ const DataGrid: React.FC = ({ const theme = useStore(state => state.theme); const appearance = useStore(state => state.appearance); const darkMode = theme === 'dark'; - const opacity = appearance.opacity ?? 0.95; + const opacity = normalizeOpacityForPlatform(appearance.opacity); + const blur = normalizeBlurForPlatform(appearance.blur); + const blurFilter = blurToFilter(blur); const selectionColumnWidth = 46; // Background Helper @@ -371,7 +374,6 @@ const DataGrid: React.FC = ({ const b = parseInt(hex.substring(4, 6), 16); return `rgba(${r}, ${g}, ${b}, ${opacity})`; }; - const blur = appearance.blur ?? 0; const bgContent = getBg('#1d1d1d'); const bgFilter = getBg('#262626'); const bgContextMenu = getBg('#1f1f1f'); @@ -1314,7 +1316,7 @@ const DataGrid: React.FC = ({ const enableVirtual = mergedDisplayData.length >= 200; return ( -
0 ? `blur(${blur}px)` : undefined }}> +
{/* Toolbar */}
{onReload &&