From dc97ee982d13116176d86398df53a84218fd1f64 Mon Sep 17 00:00:00 2001 From: chenqiang Date: Wed, 10 Sep 2025 12:07:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=8D=B0=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background/db/index.js | 56 ++---------------- background/db/path.js | 56 +++++++----------- background/main.js | 110 ++++++++++++++---------------------- background/preload.js | 5 ++ package-windows-portable.js | 22 ++++---- src/views/WelcomeView.vue | 88 ++++++++++++++++------------- 6 files changed, 132 insertions(+), 205 deletions(-) diff --git a/background/db/index.js b/background/db/index.js index 5b648ff..b2c3cf3 100644 --- a/background/db/index.js +++ b/background/db/index.js @@ -1,4 +1,3 @@ -// 添加缺失的导入 const { getSystemDbPath, getUserDbPath } = require('./path.js'); const { systemSchema, userSchema, defaultData } = require('./schema.js'); const { openDatabase, batchInsert } = require('./utils.js'); @@ -36,58 +35,15 @@ exports.closeAllConnections = function closeAllConnections() { exports.checkDatabaseInitialized = async function checkDatabaseInitialized() { try { console.log('开始检查数据库初始化状态...'); - const systemDbPath = getSystemDbPath(); - console.log('系统数据库路径:', systemDbPath); - - // 首先检查数据库文件是否存在 - const fs = require('fs'); - const dbExists = fs.existsSync(systemDbPath); - console.log('系统数据库文件存在:', dbExists); - - if (!dbExists) { - console.log('系统数据库文件不存在,返回未初始化状态'); - return false; - } - - // 检查文件大小,如果是空文件则认为未初始化 - const stats = fs.statSync(systemDbPath); - if (stats.size === 0) { - console.log('系统数据库文件为空,返回未初始化状态'); - return false; - } - - // 尝试打开数据库连接 - const systemDb = await exports.getDbConnection(systemDbPath); + const systemDb = await exports.getDbConnection(getSystemDbPath()); console.log('成功打开系统数据库'); - try { - // 尝试查询config表 - const result = await systemDb.getAsync('SELECT value FROM config WHERE key = ?', ['initialized']); - console.log('查询初始化状态结果:', result); + const result = await systemDb.getAsync('SELECT value FROM config WHERE key = ?', ['initialized']); + console.log('查询初始化状态结果:', result); - const isInitialized = result && result.value === 'true'; - console.log('数据库初始化状态:', isInitialized ? '已初始化' : '未初始化'); - return isInitialized; - } catch (queryError) { - // 如果查询失败,可能是表不存在,说明数据库未初始化 - console.log('查询config表失败,可能表不存在:', queryError.message); - - // 尝试检查数据库是否有表结构 - try { - const tables = await systemDb.allAsync("SELECT name FROM sqlite_master WHERE type='table'"); - console.log('数据库中的表:', tables.map(t => t.name).join(', ')); - - // 如果有表但没有config表,可能是结构不完整 - if (tables.length > 0) { - console.log('数据库有表结构但可能不完整,需要重新初始化'); - return false; - } - } catch (tablesError) { - console.error('检查数据库表结构失败:', tablesError); - } - - return false; - } + const isInitialized = result && result.value === 'true'; + console.log('数据库初始化状态:', isInitialized ? '已初始化' : '未初始化'); + return isInitialized; } catch (error) { console.error('检查数据库初始化状态失败:', error); return false; diff --git a/background/db/path.js b/background/db/path.js index ede7913..c445993 100644 --- a/background/db/path.js +++ b/background/db/path.js @@ -11,55 +11,37 @@ let isPortable = false; let appDir; let dataDir; -// 调试信息 -console.log('环境检测:'); -console.log('- 开发环境:', isDev); -console.log('- 当前工作目录:', process.cwd()); -console.log('- 可执行文件路径:', app.getPath('exe')); - if (isDev) { // 开发环境:数据存储在工程的data目录 dataDir = path.join(process.cwd(), 'data'); - console.log('开发环境数据目录:', dataDir); } else { // 非开发环境:确定应用目录 const exePath = app.getPath('exe'); appDir = path.dirname(exePath); - console.log('应用目录:', appDir); - // 检测便携模式的多种可能性 - // 1. 检查可执行文件同级目录是否有data文件夹 - const dataPathSameLevel = path.join(appDir, 'data'); - // 2. 检查可执行文件所在目录是否为portable-app,如果是,检查其父目录下是否有data - const isPortableAppDir = path.basename(appDir) === 'portable-app'; - const dataPathParentLevel = isPortableAppDir ? path.join(path.dirname(appDir), 'data') : null; - // 3. 检查可执行文件同级目录是否有portable-app/data文件夹 - const dataPathInPortableApp = path.join(appDir, 'portable-app', 'data'); - - console.log('检测便携模式:'); - console.log('- 同级data目录存在:', fs.existsSync(dataPathSameLevel)); - if (isPortableAppDir) { - console.log('- 父级data目录存在:', fs.existsSync(dataPathParentLevel)); + // 检测是否存在便携模式标记文件 + const portableFlagPath = path.join(appDir, 'portable.txt'); + if (fs.existsSync(portableFlagPath)) { + isPortable = true; } - console.log('- portable-app/data目录存在:', fs.existsSync(dataPathInPortableApp)); - // 优先级顺序:同级data > portable-app内data > 父级data - if (fs.existsSync(dataPathSameLevel)) { - dataDir = dataPathSameLevel; + // 关键修改:在便携模式下,data目录与可执行文件同级 + // 如果可执行文件在portable-app目录中,则data目录与portable-app目录同级 + if (path.basename(appDir) === 'portable-app') { + dataDir = path.join(path.dirname(appDir), 'data'); isPortable = true; - console.log('使用同级data目录:', dataDir); - } else if (fs.existsSync(dataPathInPortableApp)) { - dataDir = dataPathInPortableApp; - isPortable = true; - console.log('使用portable-app内data目录:', dataDir); - } else if (isPortableAppDir && fs.existsSync(dataPathParentLevel)) { - dataDir = dataPathParentLevel; - isPortable = true; - console.log('使用父级data目录:', dataDir); } else { - // 默认使用用户数据目录 - dataDir = path.join(app.getPath('userData'), 'data'); - console.log('使用用户数据目录:', dataDir); + // 否则data目录与可执行文件同级 + dataDir = path.join(appDir, 'data'); + } + + // 确保便携模式标记文件存在于data目录同级 + if (isPortable) { + const flagDir = path.dirname(dataDir); + const flagPath = path.join(flagDir, 'portable.txt'); + if (!fs.existsSync(flagPath)) { + fs.writeFileSync(flagPath, ''); + } } } diff --git a/background/main.js b/background/main.js index 15a0b1a..fe2e08a 100644 --- a/background/main.js +++ b/background/main.js @@ -16,7 +16,7 @@ const { initializeUserDatabase, } = require("./db/index.js"); // 导入数据库路径函数 -const { getUserDbPath } = require("./db/path.js"); +const { getSystemDbPath, getUserDbPath } = require("./db/path.js"); // 导入配置服务 const { initConfigIpc } = require("./service/configService.js"); // 导入字典服务 @@ -301,81 +301,27 @@ let appDataPath = ""; // 初始化应用路径 - 兼容Node.js 12和Windows 7 function initializeAppPaths() { - console.log("开始初始化应用路径..."); - - // 获取应用相关路径 + // 检查应用根目录是否存在data文件夹,如果存在则认为是便携模式 + // Windows路径兼容处理 const appRoot = process.cwd(); - const exePath = app.getPath("exe"); - const appDir = path.dirname(exePath); - const userDataPath = app.getPath("userData"); - - console.log("应用路径信息:"); - console.log("- 当前工作目录:", appRoot); - console.log("- 可执行文件路径:", exePath); - console.log("- 应用目录:", appDir); - console.log("- 用户数据目录:", userDataPath); - - // 检查多个可能的便携模式数据目录位置 - const possibleDataPaths = [ - // 1. 当前工作目录下的data - path.join(appRoot, "data"), - // 2. 可执行文件同级目录下的data - path.join(appDir, "data"), - // 3. 如果在portable-app目录中,检查其父目录下的data - path.basename(appDir) === "portable-app" ? path.join(path.dirname(appDir), "data") : null, - // 4. 可执行文件同级目录下的portable-app/data - path.join(appDir, "portable-app", "data") - ].filter(Boolean); // 过滤掉null值 - - // 检查便携模式标记文件 - const possibleFlagPaths = [ - path.join(appRoot, "portable.txt"), - path.join(appDir, "portable.txt"), - path.basename(appDir) === "portable-app" ? path.join(path.dirname(appDir), "portable.txt") : null - ].filter(Boolean); - - // 记录检测结果 - console.log("便携模式检测:"); - possibleDataPaths.forEach((p, i) => { - console.log(`- 数据路径 ${i+1} 存在:`, fs.existsSync(p) ? "是" : "否", p); - }); - possibleFlagPaths.forEach((p, i) => { - console.log(`- 标记文件 ${i+1} 存在:`, fs.existsSync(p) ? "是" : "否", p); - }); - - // 确定是否为便携模式 - // 1. 如果存在便携模式标记文件,则为便携模式 - const flagFileExists = possibleFlagPaths.some(p => fs.existsSync(p)); - // 2. 如果存在data目录,也视为便携模式 - const dataPathExists = possibleDataPaths.some(p => fs.existsSync(p)); - - isPortableMode = flagFileExists || dataPathExists; - - // 确定数据目录路径 - if (isPortableMode) { - // 按优先级选择第一个存在的数据目录 - appDataPath = possibleDataPaths.find(p => fs.existsSync(p)) || possibleDataPaths[0]; - console.log("检测到便携模式,使用数据文件夹:", appDataPath); - - // 确保数据目录存在 - if (!fs.existsSync(appDataPath)) { - try { - fs.mkdirSync(appDataPath, { recursive: true }); - console.log("已创建便携模式数据目录:", appDataPath); - } catch (error) { - console.error("创建便携模式数据目录失败:", error); - } - } + const portableDataPath = path.join(appRoot, "data"); + const defaultDataPath = path.join(app.getPath("userData"), "data"); + + // 检查是否为便携模式 + if (fs.existsSync(portableDataPath)) { + isPortableMode = true; + appDataPath = portableDataPath; + console.log("检测到便携模式,使用当前目录的data文件夹:", appDataPath); } else { - // 非便携模式使用默认用户数据目录 - appDataPath = path.join(userDataPath, "data"); + isPortableMode = false; + appDataPath = defaultDataPath; console.log("使用默认数据目录:", appDataPath); - + // 确保默认数据目录存在 if (!fs.existsSync(appDataPath)) { + // 递归创建目录,兼容Windows路径 try { fs.mkdirSync(appDataPath, { recursive: true }); - console.log("已创建默认数据目录:", appDataPath); } catch (error) { console.error("创建默认数据目录失败:", error); } @@ -394,3 +340,29 @@ global.isPortableMode = function () { // 在应用ready事件前初始化路径 initializeAppPaths(); + +// 新增:添加获取路径信息的IPC处理程序 +ipcMain.handle("get-exe-path", (event) => { + try { + const exePath = app.getPath('exe'); + console.log('获取exe路径:', exePath); + return exePath; + } catch (error) { + console.error('获取exe路径失败:', error); + return null; + } +}); + +ipcMain.handle("get-database-paths", (event) => { + try { + const systemDbPath = getSystemDbPath(); + const userDbPath = getUserDbPath(); + console.log('获取数据库路径:'); + console.log('system.db:', systemDbPath); + console.log('user.db:', userDbPath); + return { systemDbPath, userDbPath }; + } catch (error) { + console.error('获取数据库路径失败:', error); + return { systemDbPath: '获取失败', userDbPath: '获取失败' }; + } +}); diff --git a/background/preload.js b/background/preload.js index 8fa9e8e..5a87f96 100644 --- a/background/preload.js +++ b/background/preload.js @@ -156,6 +156,11 @@ contextBridge.exposeInMainWorld("electronAPI", { ipcRenderer: { invoke: (channel, data) => ipcRenderer.invoke(channel, data), }, + // 新增:获取可执行文件路径的API + getExePath: () => ipcRenderer.invoke("get-exe-path"), + + // 新增:获取数据库路径的API + getDatabasePaths: () => ipcRenderer.invoke("get-database-paths"), }); // 也保留原来的electron对象,确保现有功能正常 diff --git a/package-windows-portable.js b/package-windows-portable.js index 167a418..9fbe0aa 100644 --- a/package-windows-portable.js +++ b/package-windows-portable.js @@ -101,19 +101,19 @@ function buildPortableApp() { console.log('已复制.gitignore文件'); } - // 不再创建空的数据库文件,而是确保复制已初始化的数据库文件 + // 创建空的system.db和user.db文件(如果不存在) const systemDbPath = path.join(destDataDir, 'system.db'); const userDbPath = path.join(destDataDir, 'user.db'); - - // 创建便携模式标记文件 - const portableFlagPath = path.join(path.dirname(destDataDir), 'portable.txt'); - fs.writeFileSync(portableFlagPath, 'This file indicates portable mode operation.'); - console.log('已创建便携模式标记文件:', portableFlagPath); - - // 在portable-app目录内也创建一个标记文件,以防万一 - const innerPortableFlagPath = path.join(portableAppDir, 'portable.txt'); - fs.writeFileSync(innerPortableFlagPath, 'This file indicates portable mode operation.'); - console.log('已在portable-app目录内创建便携模式标记文件'); + + if (!fs.existsSync(systemDbPath)) { + fs.writeFileSync(systemDbPath, ''); + console.log('已创建空的system.db文件'); + } + + if (!fs.existsSync(userDbPath)) { + fs.writeFileSync(userDbPath, ''); + console.log('已创建空的user.db文件'); + } // 可选:如果项目中已有数据库文件,可以复制它们 const projectSystemDb = path.join(projectRoot, 'data', 'system.db'); diff --git a/src/views/WelcomeView.vue b/src/views/WelcomeView.vue index 8340bd1..6850bba 100644 --- a/src/views/WelcomeView.vue +++ b/src/views/WelcomeView.vue @@ -140,8 +140,57 @@ export default { this.checkDatabaseStatus() console.log('mounted: 调用this.checkDatabaseStatus方法完成') this.checkAndInitializeUserDb() + + // 添加:打印路径信息,帮助排查便携模式问题 + this.logPathInformation() }, methods: { + // 新增:打印路径信息 + async logPathInformation() { + try { + if (window.electronAPI) { + console.log('===== 路径信息开始 ====='); + + // 获取并打印appDir + try { + // 通过获取exe路径来间接获取appDir + const exePath = await window.electronAPI.getExePath(); + const appDir = exePath ? exePath.substring(0, exePath.lastIndexOf('\\')) : '无法获取'; + console.log('应用程序目录(appDir):', appDir); + } catch (error) { + console.error('获取appDir失败:', error); + } + + // 获取并打印数据库路径 + try { + // 由于没有直接获取数据库路径的API,我们通过检查数据库状态的日志来推断 + console.log('尝试获取数据库路径信息...'); + // 触发一次数据库检查以生成相关日志 + await window.electronAPI.checkDatabaseInitialized(); + } catch (error) { + console.error('触发数据库检查失败:', error); + } + + // 尝试直接获取system.db和user.db路径 + if (window.electronAPI.getDatabasePaths) { + try { + const paths = await window.electronAPI.getDatabasePaths(); + console.log('system.db路径:', paths.systemDbPath); + console.log('user.db路径:', paths.userDbPath); + } catch (error) { + console.error('获取数据库路径失败:', error); + } + } + + console.log('===== 路径信息结束 ====='); + } else { + console.log('electronAPI不存在,无法获取路径信息'); + } + } catch (error) { + console.error('打印路径信息时出错:', error); + } + }, + // 检查并静默初始化用户数据库 async checkAndInitializeUserDb() { try { @@ -165,47 +214,10 @@ export default { console.log('组件挂载 - 开始检查数据库初始化状态') const initialized = await window.electronAPI.checkDatabaseInitialized() console.log('组件挂载 - 数据库初始化状态检查完成:', initialized) - - // 处理undefined或null的情况 - if (initialized === undefined || initialized === null) { - console.warn('数据库初始化状态未知,可能是便携模式下的问题') - - // 检查user.db是否存在 - const userDbExists = await window.electronAPI.checkUserDbExists() - console.log('user.db存在状态:', userDbExists) - - if (userDbExists) { - console.log('user.db存在但初始化状态未知,尝试静默初始化系统数据库') - // 尝试初始化数据库 - try { - const initResult = await window.electronAPI.initializeDatabase() - console.log('静默初始化数据库结果:', initResult) - - if (initResult === true || (initResult && initResult.success)) { - console.log('静默初始化数据库成功,设置初始化状态为true') - this.isDatabaseInitialized = true - } else { - console.warn('静默初始化数据库失败,显示初始化界面') - this.isDatabaseInitialized = false - } - } catch (initError) { - console.error('静默初始化数据库出错:', initError) - this.isDatabaseInitialized = false - } - } else { - // user.db不存在,需要显示初始化界面 - console.log('user.db不存在,显示初始化界面') - this.isDatabaseInitialized = false - } - } else { - // 正常情况,使用返回的初始化状态 - this.isDatabaseInitialized = initialized - } + this.isDatabaseInitialized = initialized } catch (error) { console.error('检查数据库初始化状态失败:', error) Message.error('检查数据库初始化状态失败,请重试') - // 出错时默认显示初始化界面 - this.isDatabaseInitialized = false } },