一、数据库配置
路径: electron/ipc/db/db-config.js
const path = require('path')
const fs = require('fs')
// 数据库存放路径(建议放在用户数据目录)
const { app } = require('electron')
const dbDir = path.join(app.getPath('userData'), 'database')
// 确保目录存在
if (!fs.existsSync(dbDir)) {
fs.mkdirSync(dbDir, { recursive: true })
}
module.exports = {
dbFile: path.join(dbDir, 'app_data.db'),
dbVersionFile: path.join(dbDir, 'db_version.json'),
currentVersion: 1 // 🔧 修改此处即可触发结构重建
}
二、表结构定义
electron/ipc/db/schema/goods.js
module.exports = {
name: 'goods',
createTableSQL: `
CREATE TABLE IF NOT EXISTS goods (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
barcode TEXT,
price REAL DEFAULT 0,
stock INTEGER DEFAULT 0,
category TEXT,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
)
`
}
electron/ipc/db/schema/version.js
module.exports = {
name: 'db_version',
createTableSQL: `
CREATE TABLE IF NOT EXISTS db_version (
id INTEGER PRIMARY KEY AUTOINCREMENT,
version INTEGER,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`
}
三、数据库初始化与版本检测逻辑
路径: electron/ipc/db/index.js
const Database = require('better-sqlite3')
const fs = require('fs')
const path = require('path')
const config = require('./db-config')
// 加载所有表结构定义
const goods = require('./schema/goods')
const orders = require('./schema/orders')
const version = require('./schema/version')
const tables = [goods, orders, version]
let dbInstance = null
/**
* 获取当前数据库实例
*/
function getDB() {
if (!dbInstance) initializeDatabase()
return dbInstance
}
/**
* 初始化数据库
*/
function initializeDatabase() {
console.log('[DB] 初始化数据库...')
// 检查数据库版本
const currentVersion = config.currentVersion
const versionFile = config.dbVersionFile
let savedVersion = 0
if (fs.existsSync(versionFile)) {
try {
savedVersion = JSON.parse(fs.readFileSync(versionFile, 'utf8')).version || 0
} catch {
savedVersion = 0
}
}
// 如果版本不一致则重建数据库
if (savedVersion !== currentVersion) {
console.log(`[DB] 版本不一致 (${savedVersion} -> ${currentVersion}),重建数据库...`)
if (fs.existsSync(config.dbFile)) fs.unlinkSync(config.dbFile)
}
// 初始化数据库连接
dbInstance = new Database(config.dbFile)
dbInstance.pragma('journal_mode = WAL')
// 创建表
for (const table of tables) {
dbInstance.prepare(table.createTableSQL).run()
console.log(`[DB] 表 ${table.name} 已创建`)
}
// 更新版本文件
fs.writeFileSync(versionFile, JSON.stringify({ version: currentVersion }, null, 2))
console.log(`[DB] 数据库版本 ${currentVersion} 已同步`)
}
/**
* 重建数据库(手动触发)
*/
function rebuildDatabase() {
if (fs.existsSync(config.dbFile)) {
fs.unlinkSync(config.dbFile)
}
initializeDatabase()
}
/**
* 执行查询(封装简单查询接口)
*/
function query(sql, params = []) {
return getDB().prepare(sql).all(params)
}
/**
* 执行更新/插入
*/
function execute(sql, params = []) {
return getDB().prepare(sql).run(params)
}
module.exports = {
getDB,
initializeDatabase,
rebuildDatabase,
query,
execute
}
四、数据库 API 暴露(前端可调用)
路径: electron/ipc/api/db.js
const db = require('../db/index')
/**
* 获取所有商品
*/
async function getAllGoods() {
return db.query('SELECT * FROM goods ORDER BY id DESC')
}
/**
* 新增商品
*/
async function addGood(_, { name, barcode, price, stock, category }) {
const sql = `INSERT INTO goods (name, barcode, price, stock, category)
VALUES (?, ?, ?, ?, ?)`
return db.execute(sql, [name, barcode, price, stock, category])
}
/**
* 获取所有订单
*/
async function getAllOrders() {
return db.query('SELECT * FROM orders ORDER BY id DESC')
}
/**
* 新增订单
*/
async function addOrder(_, { order_no, goods_list, total_amount, pay_type }) {
const sql = `INSERT INTO orders (order_no, goods_list, total_amount, pay_type)
VALUES (?, ?, ?, ?)`
return db.execute(sql, [order_no, JSON.stringify(goods_list), total_amount, pay_type])
}
module.exports = {
getAllGoods,
addGood,
getAllOrders,
addOrder
}
五、在更新模块中集成数据库版本检查
路径: electron/ipc/api/updater.js
在自动更新成功后(或下载完成后)检查数据库结构。
在原 update-downloaded 事件中加入:
const db = require('../db/index')
// ...
autoUpdater.on('update-downloaded', (info) => {
console.log('更新下载完成,准备安装')
updateState.isDownloading = false
updateState.updateDownloaded = true
updateState.downloadProgress = 100
// ✅ 自动检查数据库版本
try {
db.initializeDatabase()
console.log('[DB] 数据库结构检查完毕')
} catch (err) {
console.error('[DB] 初始化失败:', err)
}
if (mainWindow) {
mainWindow.webContents.send('updater:updateDownloaded', info)
mainWindow.webContents.send('updater:updateMessage', '更新下载完成,准备安装')
}
// ...
})
六、manifest 增加 db 模块
路径: electron/ipc/manifest.js
{
namespace: 'db',
methods: ['getAllGoods', 'addGood', 'getAllOrders', 'addOrder'],
events: []
},
七、前端调用封装
路径: src/utils/electron.js
export const ipcInvoke = (channel, ...args) => {
return window.electron?.ipcRenderer.invoke(channel, ...args)
}
export const DB = {
getAllGoods: () => ipcInvoke('db:getAllGoods'),
addGood: (data) => ipcInvoke('db:addGood', data),
getAllOrders: () => ipcInvoke('db:getAllOrders'),
addOrder: (data) => ipcInvoke('db:addOrder', data)
}