Electron 数据持久化

2,060 阅读2分钟

前言

  • 背景:由于特殊需求,访问我们的网站需要通过一个客户端来使用。所以,使用了Electron loadURL 嵌入了链接。
  • 问题:正常情况下,登录网页后,登录状态会保存14天,但是在个别window电脑中每次重启软件,都需要重新登录网页
  • 原因:原因不详,升级Electron也没有解决

解决方法(简单处理)

利用electron-store数据持久化保存用户的密码,自动登录。

  1. 主线程暴露保存数据的方法
  2. 渲染端在登录的时候,把密码保传给Electron存起来,并标记时间
  3. 下载在登录界面时,从主线程获取密码,调用登录接口自动登录
  4. 如果用户主动退出登录,则清空数据

主线程main.js

const { app, BrowserWindow, ipcMain, Menu } = require('electron')
const path = require('path')
const Store = require('electron-store')
const Config = require('./config/env.js')

// 数据持久化
const store = new Store()

// 定义ipcRenderer监听事件
initIpcRenderer()

let mainWindow = null
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1920,
    height: 1200,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.loadURL(Config.url)
}

app.whenReady().then(() => {
  createWindow()
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

function initIpcRenderer(params) {
  ipcMain.on('setStore', (_, key, value) => {
    store.set(key, value)
  })

  ipcMain.on('getStore', (_, key) => {
    let value = store.get(key)
    _.returnValue = value || ''
  })

  ipcMain.on('deleteStore', (_, key) => {
    let value = store.delete(key)
    _.returnValue = value || ''
  })
}

preload.js

const { contextBridge, ipcRenderer } = require('electron')

...

const electronHandler = {
  ipcRenderer: {
    setStoreValue: (key, value) => {
      ipcRenderer.send('setStore', key, value)
    },

    getStoreValue(key) {
      const resp = ipcRenderer.sendSync('getStore', key)
      return resp
    },

    deleteStore(key) {
      ipcRenderer.send('deleteStore', key)
    }
  }
}

contextBridge.exposeInMainWorld('electron', electronHandler)

...

网页端

/**
 * Eletron.js
 * 封装了与H5 与 electron的通信
 */

export default class Electron {
    static isInElectron() {
        return navigator.userAgent.toLowerCase().indexOf(' electron/') > -1
    }

    static saveLoginData(data) {
        const loginData = {
            ...data,
            createTime: this.getNextMonthTime(),
        }
        this.setStore({ loginData })
    }

    static deleteLoginData() {
        this.deleteStore('loginData')
    }

    static setStore(key, value) {
        if (!this.isInElectron()) {
            return
        }
        window.electron?.ipcRenderer?.setStoreValue(key, value)
    }

    static getStore(key) {
        if (!this.isInElectron()) {
            return
        }
        return window.electron?.ipcRenderer?.getStoreValue(key)
    }

    static deleteStore(key) {
        if (!this.isInElectron()) {
            return
        }
        window.electron?.ipcRenderer?.deleteStore(key)
    }
    
    // 保存一个月
    static getNextMonthTime() {
        const date = new Date()

        const currentMonth = date.getMonth()
        const currentYear = date.getFullYear()

        let nextMonth = currentMonth + 1
        let nextYear = currentYear

        if (nextMonth > 11) {
            nextMonth = 0
            nextYear += 1
        }

        return new Date(nextYear, nextMonth).getTime()
    }
}

Login

import Electron from '@/common/electron.js'

// 检测是否有数据,有则自动登录
if (Electron.isInElectron()) {
    const loginData = Electron.getStore('loginData')
    const { username, password, createTime } = loginData
    if (username && password && createTime > new Date().getTime()) {
        login({ username, password })
    }
}

// 登录时,保存登录密码
Electron.saveLoginData({
    username: config.username,
    password: config.password,
})