From 618e434cb158a2ab55c0e3481ab698561d97b45a Mon Sep 17 00:00:00 2001 From: cles <208023732@qq.com> Date: Tue, 9 Sep 2025 13:46:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=89=E6=8B=A9=E5=92=8C=E6=89=93=E5=BC=80?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/ipcRouter.js | 37 +++++++++ src/preload/index.js | 25 +++++- .../SystemSettings/SystemSettings.jsx | 76 ++++++++++++++++++- 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/src/main/ipcRouter.js b/src/main/ipcRouter.js index a303d92..12d13e5 100644 --- a/src/main/ipcRouter.js +++ b/src/main/ipcRouter.js @@ -1,4 +1,5 @@ import { ipcMain } from 'electron' +import { dialog, shell } from 'electron' import dgram from 'dgram' import net from 'net' import { IPC_EVENT } from '../renderer/src/common/ipcEvents.js' @@ -187,6 +188,9 @@ export function registerIpRouter() { ipcMain.handle(IPC_EVENT.INVALID_DATA_COUNT_SET, invalidDataCountSet) ipcMain.handle(IPC_EVENT.IMAGE_SEND_ENABLED, imageSendEnabledSet) ipcMain.handle(IPC_EVENT.IS_CLEAR_ZERO, isClearZeroSet) + // 存储目录相关处理 + ipcMain.handle('open-directory', openDirectory) + ipcMain.handle('select-directory', selectDirectory) } // 搜索设备 const searchDevice = (event) => { @@ -1446,3 +1450,36 @@ const stopHeartbeatCheck = (ip) => { lastHeartbeatTime.delete(ip) log.info(`Stopped heartbeat check for ${ip}`) } + +// 存储目录相关处理函数 +const openDirectory = async (event, path) => { + try { + await shell.openPath(path) + log.info(`Opened directory: ${path}`) + return { success: true } + } catch (error) { + log.error('Failed to open directory:', error) + return { success: false, error: error.message } + } +} + +const selectDirectory = async (event, options) => { + try { + const result = await dialog.showOpenDialog({ + title: options.title || '选择目录', + properties: ['openDirectory', 'createDirectory'], + defaultPath: options.defaultPath + }) + + if (result.canceled) { + return { success: false, canceled: true } + } + + const selectedPath = result.filePaths[0] + log.info(`Directory selected: ${selectedPath}`) + return { success: true, path: selectedPath } + } catch (error) { + log.error('Failed to select directory:', error) + return { success: false, error: error.message } + } +} diff --git a/src/preload/index.js b/src/preload/index.js index 122fde5..d3c475a 100644 --- a/src/preload/index.js +++ b/src/preload/index.js @@ -1,7 +1,30 @@ import { contextBridge } from 'electron' import { electronAPI } from '@electron-toolkit/preload' +import { join } from 'path' +import { homedir } from 'os' +import { existsSync, mkdirSync } from 'fs' +import log from 'electron-log' -const api = {} +const api = { + // 获取用户主目录 + getHomeDir: () => homedir(), + // 获取默认存储目录 + getDefaultStoragePath: () => { + const defaultPath = join(homedir(), 'FlexometerSetup', 'data') + + // 检查目录是否存在,不存在则创建 + try { + if (!existsSync(defaultPath)) { + mkdirSync(defaultPath, { recursive: true }) + log.info('Created default storage directory at:', defaultPath) + } + } catch (error) { + log.error('Error creating default storage directory:', error) + return homedir() // 出错时返回用户主目录 + } + return defaultPath + } +} if (process.contextIsolated) { try { diff --git a/src/renderer/src/components/SystemSettings/SystemSettings.jsx b/src/renderer/src/components/SystemSettings/SystemSettings.jsx index 22490dc..7be0edb 100644 --- a/src/renderer/src/components/SystemSettings/SystemSettings.jsx +++ b/src/renderer/src/components/SystemSettings/SystemSettings.jsx @@ -20,6 +20,7 @@ function SystemSettings() { const [settingLoading, setSettingLoading] = useState(false) const [imageControlLoading, setImageControlLoading] = useState(false) const [clearZeroLoading, setClearZeroLoading] = useState(false) + const [storagePath, setStoragePath] = useState('') // 获取设备连接状态和重连配置 const connectedDevice = useDeviceStore((state) => state.connectedDevice) @@ -64,6 +65,60 @@ function SystemSettings() { } }, [setReconnecting]) + // 初始化存储路径 + useEffect(() => { + const savedPath = localStorage.getItem('storagePath') + if (savedPath) { + setStoragePath(savedPath) + } else { + // 使用暴露的 API 获取默认存储路径 + const defaultPath = window.api.getDefaultStoragePath() + setStoragePath(defaultPath) + localStorage.setItem('storagePath', defaultPath) + } + }, []) + + // 打开存储目录 + const handleOpenStoragePath = async () => { + if (!storagePath) { + message.warning('存储路径未设置') + return + } + + try { + // 使用 IPC 调用主进程打开目录 + const result = await window.electron.ipcRenderer.invoke('open-directory', storagePath) + if (!result.success) { + message.error(`打开目录失败:${result.error}`) + } + } catch (error) { + console.error('打开存储目录失败:', error) + message.error(`打开目录失败:${error.message}`) + } + } + + // 选择存储目录 + const handleSelectStoragePath = async () => { + try { + // 使用 IPC 调用主进程选择目录 + const result = await window.electron.ipcRenderer.invoke('select-directory', { + title: '选择存储目录', + defaultPath: storagePath + }) + + if (result.success && result.path) { + setStoragePath(result.path) + localStorage.setItem('storagePath', result.path) + message.success('存储目录设置成功!') + } else if (!result.canceled) { + message.error(`选择目录失败:${result.error}`) + } + } catch (error) { + console.error('选择存储目录失败:', error) + message.error(`选择目录失败:${error.message}`) + } + } + // 读取参数函数 const handleReadParam = async () => { if (!selectedParam) { @@ -444,13 +499,28 @@ function SystemSettings() { 存储目录