Electron開發實戰之記帳軟件18——備份、恢復、導入、導出

代碼倉庫: https://github.com/hilanmiao/LanMiaoDesktopnode

備份

咱們用的是json文件數據庫,備份數據很是簡單,直接複製文件便可。咱們用fs-extra這個庫操做,很是簡單。git

https://github.com/jprichardson/node-fs-extragithub

// With Promises:
fs.emptyDir('/tmp/some/dir')
.then(() => {
  console.log('success!')
})
.catch(err => {
  console.error(err)
})

// Async with promises:
fs.copy('/tmp/myfile', '/tmp/mynewfile')
  .then(() => console.log('success!'))
  .catch(err => console.error(err))

核心代碼:shell

backup() {
                this.backuping = true
                const backupFileName = moment(new Date()).format('YYYYMMDDHHMMSS') + 'Backup.json'

                // 若是沒有目錄則建立
                fs.ensureDir(this.backupPath).then(() => {
                    // 複製文件
                    fs.copy(this.userDataPath + '/' + this.dbFileName, this.backupPath + '/' + backupFileName)
                        .then(() => {
                            this.backuping = false
                            this.snackbar = true
                            this.submitResult = true
                            this.snackbarMsg = 'Backup succeeded'
                        })
                        .catch(err => {
                            this.backuping = false
                            this.snackbar = true
                            this.submitResult = false
                            this.snackbarMsg = 'Backup failed'
                        })
                }).catch(err => {
                    this.backuping = false
                    this.snackbar = true
                    this.submitResult = false
                    this.snackbarMsg = 'Failed to create folder'
                })
            },

恢復

原理同備份同樣,都是直接操做文件便可。恢復至關於刪除和移動文件,函數使用remove和move,copy等方法。固然還有彈出文件選擇框等操做。恢復完必定記得重啓程序,使用relaunch、和 exist方法。數據庫

核心代碼:json

recovery() {
                this.recovering = true

                // 彈出文件選擇框
                remote.dialog.showOpenDialog({
                    // title: '請選擇須要導入的文件',
                    defaultPath: this.backupPath,
                    // buttonLabel: '確認',
                    // 過濾
                    filters: [
                        {name: 'json', extensions: ['json']}
                    ],
                    // 包含功能
                    properties: ['openFile']
                }, (filepaths, bookmarks) => {
                    if (filepaths) {
                        // 移除舊文件
                        fs.remove(this.userDataPath + '/' + this.dbFileName).then(() => {
                            // 複製文件
                            fs.copy(filepaths[0], this.userDataPath + '/' + this.dbFileName)
                                .then(() => {
                                    this.recovering = false
                                    this.snackbar = true
                                    this.submitResult = true
                                    this.snackbarMsg = 'Recovering succeeded'

                                    // 重啓應用
                                    remote.app.relaunch()
                                    // remote.app.quit()
                                    remote.app.exit()
                                })
                                .catch(err => {
                                    this.recovering = false
                                    this.snackbar = true
                                    this.submitResult = false
                                    this.snackbarMsg = 'Recovering failed'
                                })
                        }).catch(err => {
                            this.recovering = false
                            this.snackbar = true
                            this.submitResult = false
                            this.snackbarMsg = 'Error deleting old files'
                        })
                    } else {
                        this.recovering = false
                    }
                })
            },

導出

導出數據是很常規的操做,咱們使用exceljs這個庫來作導出。promise

核心代碼:app

exportLocalFile() {
                // 日期範圍判斷
                if (this.search.dateStart && this.search.dateEnd) {
                    if (moment(this.search.dateStart).isAfter(moment(this.search.dateEnd))) {
                        this.snackbar = true
                        this.snackbarMsg = 'Please select the correct date range'
                        return
                    }
                }

                this.exporting = true

                // 建立一個文件
                const workbook = new Excel.Workbook()
                workbook.creator = 'test'
                workbook.lastModifiedBy = 'test'
                workbook.created = new Date()
                workbook.modified = new Date()

                // 建立一個工做組
                let sheet = workbook.addWorksheet('test')

                // 設置默認行高
                sheet.properties.defaultRowHeight = 20;

                // 建立列
                sheet.getRow(1).values = ['Detail', , 'AssetsName', 'CategoryName', 'CreatedAt', 'Remark']
                sheet.getRow(2).values = ['Type', 'AmountOfMoney', 'AssetsName', 'CategoryName', 'CreatedAt', 'Remark']

                // 設置表頭樣式
                const colorHeader = 'FFDB8B89'
                const rowHeader1 = sheet.getRow(2)
                rowHeader1.eachCell((cell, rowNumber) => {
                    sheet.getColumn(rowNumber).alignment = {vertical: 'middle', horizontal: 'center'}
                    sheet.getColumn(rowNumber).font = {size: 12, family: 2, bold: true}
                    sheet.getColumn(rowNumber).fill = {
                        type: 'pattern',
                        pattern: 'solid',
                        fgColor: {argb: colorHeader}
                    }
                    sheet.getColumn(rowNumber).border = {
                        top: {style: 'thin'},
                        left: {style: 'thin'},
                        bottom: {style: 'thin'},
                        right: {style: 'thin'}
                    }
                })

                // 凍結行
                sheet.views = [{
                    state: 'frozen', ySplit: 2, activeCell: 'A1'
                }]

                // 合併單元格
                sheet.mergeCells('A1:B1')
                sheet.mergeCells('C1:C2')
                sheet.mergeCells('D1:D2')
                sheet.mergeCells('E1:E2')
                sheet.mergeCells('F1:F2')

                // 添加數據項定義
                sheet.columns = [
                    {key: 'type', width: 30},
                    {key: 'amountOfMoney', width: 30},
                    {key: 'assetsName', width: 30},
                    {key: 'categoryName', width: 30},
                    {key: 'createdAt', width: 30},
                    {key: 'remark', width: 60},
                ]

                // 獲取數據
                this._getModelExport().then(result => {
                    console.log(result)
                    // 建立行
                    sheet.addRows(result.data)

                    // 建立文件及文件夾
                    const APP = process.type === 'renderer' ? remote.app : app
                    // 獲取electron應用的用戶目錄
                    const STORE_PATH = APP.getPath('userData')

                    const dir = STORE_PATH + '/export'
                    const fileName = moment(new Date()).format('YYYYMMDDHHMMSS') + 'Export.xlsx'
                    const fullPath = dir + '/' + fileName

                    // 若是沒有目錄則建立
                    fs.ensureDir(dir).then(() => {
                        // 寫文件
                        workbook.xlsx.writeFile(fullPath).then(() => {
                            this.exporting = false

                            // 在文件管理器中顯示給定的文件,若是能夠,'選中'該文件
                            shell.showItemInFolder(dir)
                            // 播放嗶嗶的聲音
                            shell.beep()

                            // 打開文件
                            shell.openItem(fullPath)
                        })
                    }).catch(err => {
                        this.snackbar = true
                        this.snackbarMsg = 'Failed to create folder'
                    })
                }).catch(err => {
                    this.snackbar = true
                    this.snackbarMsg = err.message
                })
            },

效果以下,官網還有其餘的設置,能夠自行參考嘗試。electron

https://github.com/exceljs/exceljs函數

導入

導入數據咱們使用exceljsreadFile方法,它有好幾個讀取文件的方式,xlsx、csv、流等方式,由於咱們的程序導出的xlsx文件,因此咱們使用xlsx.readFile(),固然你能夠能夠用csv等。讀取到的數據記得打印出來看看,篩選出你真正須要的數據。下面代碼還用到了Electron的dialog來彈出文件選擇框,但因爲是renderer進程,因此要用remote.diaolog

核心代碼:

importLocalFile() {
                this.importing = true

                // 彈出文件選擇框
                remote.dialog.showOpenDialog({
                    // title: '請選擇須要導入的文件',
                    defaultPath: this.exportPath,
                    // buttonLabel: '確認',
                    // 過濾
                    filters: [
                        {name: 'xlsx', extensions: ['xlsx']}
                    ],
                    // 包含功能
                    properties: ['openFile']
                }, (filepaths, bookmarks) => {

                    if (filepaths) {
                        // 讀取文件
                        const workbook = new Excel.Workbook()
                        workbook.xlsx.readFile(filepaths[0]).then(() => {
                            // 從新結構化數據
                            let data = []

                            // 獲取工做表
                            const worksheet = workbook.getWorksheet(1)
                            // 迭代工做表中具備值的全部行
                            worksheet.eachRow(function (row, rowNumber) {
                                console.log('Row ' + rowNumber + ' = ' + JSON.stringify(row.values))
                                // 去掉兩行表頭
                                if (rowNumber > 2) {
                                    // 從新組織數據,excel不管單元格仍是行都是從1開始的
                                    const model = {
                                        type: row.values[1],
                                        amountOfMoney: row.values[2],
                                        assetsName: row.values[3],
                                        categoryName: row.values[4],
                                        createdAt: row.values[5],
                                        remark: row.values[6],
                                    }

                                    data.push(model)
                                }
                            })
                            // 業務處理
                            // console.log(data)
                            this._importData(data).then(result => {
                                if (result.code === 200) {
                                    this.submitResult = true
                                    this.importing = false
                                    this.snackbar = true
                                    this.snackbarMsg = 'Successfully imported'
                                }
                            }).catch(err => {
                                this.submitResult = false
                                this.importing = false
                                this.snackbar = true
                                this.snackbarMsg = err.message
                            })
                        })
                    }
                })
            },
相關文章
相關標籤/搜索