安裝sqlite

npm i sqlite3

在main.js中使用ipcMain創建相關函數

記住要導入包

app.whenReady().then(() => {
  createWindow()
  dbInit()
})
const sqlite3 = require('sqlite3').verbose()
let db
const dbInit = () => {
  // Ensure the directory exists
  const dbPath = path.join(__dirname, 'data', 'data.db')
  fs.mkdirSync(path.dirname(dbPath), { recursive: true })

  // Open SQLite database
  db = new sqlite3.Database(dbPath, (err) => {
    if (err) {
      console.error('Error opening database', err)
    } else {
      console.log('Database opened successfully')
    }
  })

  // Create a table if not exists
  db.run('CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT)', (err) => {
    if (err) {
      console.error('Error creating table', err)
    }
  })
}
// 處理IPC通信
ipcMain.handle('set-data', (event, key, value) => {
  return new Promise((resolve, reject) => {
    db.run('INSERT OR REPLACE INTO kv_store (key, value) VALUES (?, ?)', [key, value], (err) => {
      if (err) {
        reject(err)
      } else {
        resolve()
      }
    })
  })
})

ipcMain.handle('get-data', (event, key) => {
  return new Promise((resolve, reject) => {
    db.get('SELECT value FROM kv_store WHERE key = ?', [key], (err, row) => {
      if (err) {
        reject(err)
      } else {
        resolve(row ? row.value : null)
      }
    })
  })
})

這段代碼在一個 Electron 應用程序中初始化了一個 SQLite 數據庫,並確保在創建或打開數據庫之前,數據庫所在的目錄已經存在。此外,還設置了 IPC(進程間通信)處理器,用於在主進程和渲染進程之間進行數據傳遞。以下是這段代碼的詳細解釋:

1. 應用程序初始化:

  • app.whenReady() 方法會在 Electron 應用程序完全就緒後運行 createWindow()dbInit()
  • createWindow() 是一個創建應用程序主窗口的函數(在代碼中未顯示)。
  • dbInit() 被調用來初始化 SQLite 數據庫。

2. SQLite 數據庫初始化 (dbInit()):

  • 使用 path.join 構造 dbPath,指定數據庫文件 (data.db) 的位置,位於 data 目錄中。
  • 使用 fs.mkdirSync 確保目錄存在。{ recursive: true } 選項允許創建嵌套目錄(如果它們不存在)。
  • sqlite3.Database 構造函數用來打開數據庫。如果數據庫文件不存在,它將被創建。
  • 創建名為 kv_store 的表格(如果它尚未存在),該表格用於存儲鍵值對。

3. IPC 通信:

  • 設置了兩個 IPC 處理器來與 SQLite 數據庫交互:
    • set-data: 在 kv_store 表格中插入或替換一個鍵值對。
    • get-data: 從 kv_store 表格中檢索與鍵對應的值。

如果你的electron的main.ts開啓了 contextIsolation: true,

https://www.electronjs.org/zh/docs/latest/tutorial/context-isolation

那麽就需要preload.ts裏面把相關功能暴露給渲染進程了(可以在vue中調用完成存儲功能)

preload.ts
const { contextBridge } = require('electron')
const ipcRender = require('electron').ipcRenderer
contextBridge.exposeInMainWorld('api', {
  ipcRender: ipcRender,
  getData: (key: string) => ipcRender.invoke('get-data', key),
  setData: (key: string, value: string) => ipcRender.invoke('set-data', key, value)
 )}

然後我們就可以在vue中使用,如下

<!-- eslint-disable vue/multi-word-component-names -->
<script lang="ts" setup>
import { checkServerStatus } from '@/api/checkHealth'
import { ShowNotification } from '@/utils/notification'
import { onMounted, reactive } from 'vue'

const api = window.api
console.log(api)

async function check() {
  let res = await checkServerStatus(form_url.url)
  if (res) {
    console.log('正常')
    ShowNotification('服務器驗證', '服務器驗證成功', 'success')
  } else {
    console.log('不正常')
    ShowNotification('服務器驗證', '服務器驗失敗', 'error')
  }
}

const form_url = reactive({
  url: ''
})
const form_login = reactive({
  username: '',
  token: ''
})

async function setData() {
  try {
    await api.setData('username', form_login.username)
    await api.setData('token', form_login.token)
    await api.setData('url', form_url.url)
    console.log('Data saved')
  } catch (error) {
    console.error('Error saving data', error)
  }
}

async function getData() {
  try {
    const value = await api.getData('username')
    console.log('Data retrieved:', value)
  } catch (error) {
    console.error('Error retrieving data', error)
  }
}

onMounted(async () => {
  try {
    form_url.url = await api.getData('url')
    form_login.username = await api.getData('username')
    form_login.token = await api.getData('token')
    console.log('Data fetched')
  } catch (error) {
    console.log(error)
  }
})
</script>
<template>
  <el-header>
    <h2>Gotify配置頁</h2>
  </el-header>
  <el-main class="container">
    <el-form :model="form_url" class="url-container">
      <el-form-item label="url">
        <el-input v-model="form_url.url"></el-input>
      </el-form-item>
      <el-form-item label-width="0">
        <el-button type="primary" @click="check">驗證</el-button>
      </el-form-item>
    </el-form>
    <el-form :model="form_login">
      <el-form-item label="username">
        <el-input v-model="form_login.username"></el-input>
      </el-form-item>
      <el-form-item label="token">
        <el-input type="password" v-model="form_login.token"></el-input>
      </el-form-item>
      <el-form-item label-width="0">
        <el-button type="primary" @click="setData">提交信息</el-button>
        <el-button type="primary" @click="getData">查看信息</el-button>
      </el-form-item>
    </el-form>
  </el-main>
  <el-footer></el-footer>
</template>
<style lang="scss" scoped>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 80%;
  margin: 0 auto;
  padding: 20px;
  background-color: #f9f9f9;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.url-container {
  display: flex;
  flex-direction: row;
}
</style>

const api = window.api
這裏的window.api其實就是我們在preload.ts中暴露的api對象,裏面存儲著我們從ipcMain傳入渲染進程的函數

這樣的話,儅vue頁面挂載的時候,就會獲取sqlite中的數據,儅需要存儲值得時候,就可以通過點擊按鈕調用setData,然後與主進程通信,完成存儲