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
                            })
                        })
                    }
                })
            },
相关文章
相关标签/搜索