electron 网页TodoList应用打包win桌面软件数据持久化
参考:
electron 网页TodoList工具打包成win桌面应用exe
https://blog.csdn.net/weixin_42357472/article/details/140648621
electron直接打包exe应用,打开网页上面添加的task在重启后为空,历史没有被保存,需要持久化工具保存之前的操作记录
这里测试用electron-store或electron-conf两个持久化工具运行都ESM报错:
https://zhuanlan.zhihu.com/p/706281785
解决方法:
直接使用 Node.js 的 fs 模块直接读写 JSON 文件。这样可以避免 ES modules 的问题。
1)electron配置文件
main.js
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const fs = require('fs')const STORAGE_PATH = path.join(app.getPath('userData'), 'todos.json')function saveTodos(todos) {fs.writeFileSync(STORAGE_PATH, JSON.stringify(todos))
}function loadTodos() {try {return JSON.parse(fs.readFileSync(STORAGE_PATH, 'utf8'))} catch (error) {return []}
}function createWindow () {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true,contextIsolation: false}})win.loadFile('index.html')
}app.whenReady().then(() => {createWindow()app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow()}})
})app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})// 修改这些 IPC 处理器
ipcMain.on('save-todos', (event, todos) => {saveTodos(todos)
})ipcMain.handle('load-todos', () => {return loadTodos()
})
package.json
{"name": "todolist-app","version": "1.0.0","main": "main.js","build": {"appId": "com.yourcompany.todolist","mac": {"category": "public.app-category.productivity"},"win": {"icon": "icons/icon.png","target": ["nsis"]},"linux": {"target": ["AppImage","deb"]}},"scripts": {"start": "electron .","build": "electron-builder --win"},"keywords": [],"author": "","license": "ISC","description": "","devDependencies": {"electron": "^31.2.1","electron-builder": "^24.13.3"},"dependencies": {}
}
2)网页应用
index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>TodoList</title><link rel="stylesheet" href="styles.css">
</head>
<body><h1>TodoList</h1><form id="todo-form"><input type="text" id="todo-input" placeholder="Enter a new task" required><button type="submit" id="add-button">Add</button></form><ul id="todo-list"></ul><script src="script.js"></script>
</body>
</html>
styles.css
body {font-family: Arial, sans-serif;max-width: 500px;margin: 0 auto;padding: 20px;
}
h1 {text-align: center;
}
#todo-form {display: flex;margin-bottom: 20px;
}
#todo-input {flex-grow: 1;padding: 10px;font-size: 16px;border: 1px solid #ddd;border-radius: 4px 0 0 4px;
}
#add-button {padding: 10px 20px;font-size: 16px;background-color: #4CAF50;color: white;border: none;border-radius: 0 4px 4px 0;cursor: pointer;
}
#todo-list {list-style-type: none;padding: 0;
}
.todo-item {display: flex;align-items: center;padding: 10px;background-color: #f9f9f9;border: 1px solid #ddd;margin-bottom: 10px;border-radius: 4px;
}
.todo-item.completed {text-decoration: line-through;opacity: 0.6;
}
.todo-item input[type="checkbox"] {margin-right: 10px;
}
.delete-button {margin-left: auto;background-color: #f44336;color: white;border: none;padding: 5px 10px;border-radius: 4px;cursor: pointer;
}
script.js
const { ipcRenderer } = require('electron')const todoForm = document.getElementById('todo-form')
const todoInput = document.getElementById('todo-input')
const todoList = document.getElementById('todo-list')async function loadTodos() {const todos = await ipcRenderer.invoke('load-todos')todos.forEach(todo => {addTodoToDOM(todo.text, todo.completed)})
}function saveTodos() {const todos = Array.from(todoList.children).map(li => ({text: li.querySelector('span').textContent,completed: li.classList.contains('completed')}))ipcRenderer.send('save-todos', todos)
}function addTodoToDOM(text, completed = false) {const li = document.createElement('li')li.className = 'todo-item' + (completed ? ' completed' : '')li.innerHTML = `<input type="checkbox" ${completed ? 'checked' : ''}><span>${text}</span><button class="delete-button">Delete</button>`li.querySelector('input[type="checkbox"]').addEventListener('change', function() {li.classList.toggle('completed')if (li.classList.contains('completed')) {todoList.appendChild(li)} else {todoList.insertBefore(li, todoList.firstChild)}saveTodos()})li.querySelector('.delete-button').addEventListener('click', function() {li.remove()saveTodos()})if (completed) {todoList.appendChild(li)} else {todoList.insertBefore(li, todoList.firstChild)}
}todoForm.addEventListener('submit', function(e) {e.preventDefault()if (todoInput.value.trim() === '') returnaddTodoToDOM(todoInput.value)saveTodos()todoInput.value = ''
})loadTodos()
打包:
npm run build
完成在dist下生产安装文件,及win-unpacked 无需安装的解压文件
点击exe运行即可
相关文章:
electron 网页TodoList应用打包win桌面软件数据持久化
参考: electron 网页TodoList工具打包成win桌面应用exe https://blog.csdn.net/weixin_42357472/article/details/140648621 electron直接打包exe应用,打开网页上面添加的task在重启后为空,历史没有被保存,需要持久化工具保存之前…...
软件缺陷(Bug)、禅道
目录 软件缺陷的判定标准 软件缺陷的核心内容 构成缺陷的基本要素 缺陷报告 缺陷管理 缺陷的跟踪流程 项目管理工具--禅道 软件在使用过程中存在的任何问题(如:错误、异常等),都叫软件的缺陷,简称bug。 软件缺…...
MySQL客户端命令一节将.sql文件导入MySQL
MySql客户端命令 直接输入SQL语句 使用MySQL客户端连接到服务器之后,可以发送SQL语句到服务器执行,并且以;和\g, \G作为结束不同的结束方式显示内容有所不同** TIPS: ;和\g结尾以表格的形式显示结果\G以行的形式显示结果 在连接到服务器之后…...
[论文笔记] DCA(Dual Chunk Attention)
DCA(Dual Chunk Attention)是一种在自然语言处理模型中用来处理长文本的技术。传统的注意力机制(Attention)在处理长文本时可能会遇到效率和性能瓶颈,因为计算每个单词与其他所有单词之间的关系会随着文本长度的增加而…...
构建查询洞察 UI
本文字数:2631;估计阅读时间:7 分钟 作者:Bucky Schwarz 本文在公众号【ClickHouseInc】首发 我们最近发布了 Query Insights 的初步实现,为 ClickHouse Cloud 用户提供了一种便捷的方法来查看和解释查询日志。该功能对…...
【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十九章 等待队列
i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...
35.【C语言】详解函数递归
目录: 定义 作用 例子1~3 拓展学习 趣味练习 1.定义:函数自己调用自己(递推回归) int main() {main()return 0; } 这样容易死循环,导致爆栈(Stack Overflow) 所以需要设立限制条件,使执行时越来越接近条…...
【机器学习】智驭未来:机器学习如何重塑制造业的转型与升级
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀目录 🔍1. 引言📒2. 机器学习重塑制造业生产流程🌸预测性维护:减少停机时间,提高设…...
Python爬虫(5) --爬取网页视频
文章目录 爬虫爬取视频指定url发送请求UA伪装请求页面 获取想要的数据解析定位定位音视频位置 存放视频完整代码实现总结 爬虫 Python 爬虫是一种自动化工具,用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持(如 requ…...
【Unity】关于Luban的简单使用
最近看了下Luban导出Excel数据的方式,来记录下 【Unity】关于Luban的简单使用 安装Luban开始使用UnityLubanC# 扩展 安装Luban Luban文档:https://luban.doc.code-philosophy.com/docs/beginner/quickstart 1.安装dotnet sdk 8.0或更高版本sdk 2.githu…...
企业公户验证API如何使用JAVA、Python、PHP语言进行应用
在纷繁复杂的金融与商业领域,确保每笔交易的安全与合规是至关重要的。而企业公户验证API,正是这样一位默默守护的数字卫士,它通过智能化的手段,简化了企业对公账户验证流程,让繁琐的审核变得快捷且可靠。 什么是企业公…...
杰发科技Bootloader(2)—— 基于7840的Keil配置地址
序 在7840的sample代码里面有一个简单的Boot跳转APP的示例 PFlash地址从0开始 DFlash的地址从1000000开始 Boot解析 他的boot地址配置为0 Boot的代码主要是这几行,主要作用就是Flash的跳转 int main(void) {SystemClock_Config();InitDebug();printf("demo…...
cmd常用命令
在Windows操作系统中,CMD(Command Prompt)是一个强大的命令行工具,允许用户通过键入命令来执行各种系统级操作。以下是一些常用的CMD命令及其功能: 文件与目录管理 dir:显示当前目录下的文件和子目录列表。…...
PCIe 以太网芯片 RTL8125B 的 spec 和 Linux driver 分析备忘
1,下载 RTL8125B driver 下载页: https://www.realtek.com/Download/List?cate_id584 2,RTL8125B datasheet下载 下载页: https://file.elecfans.com/web2/M00/44/D8/poYBAGKHVriAHnfWADAT6T6hjVk715.pdf3, 编译driver 解压: $ tar xj…...
Python tkinter Menu菜单组件详解
好久没有更新了,今天我来领大家熟悉一下Menu组件 1.认识、了解Menu 什么是Menu menu组件是tkinter中的菜单组件,通过该组件,开发者可以为窗口设计菜单和工具栏等。(ttk还提供了treeview树形菜单,python遍历目录的两种…...
谷粒商城实战笔记-46-商品服务-API-三级分类-配置网关路由与路径重写
文章目录 一,准备工作1,新增一级菜单2,新增二级菜单 二,前端树形界面开发1,开发分类展示组件 三,远程调用接口获取商品分类数据1,远程调用2,路由配置 错误记录 本节的主要内容&#…...
简要了解sql注入
sql注入安全测试中危害 数据库中的数据,对数据库数据进行操作(查询、删除等);网站的权限,找到注入点后可后门写入; sql注入产生原理详细分析 可控变量,带入数据库查询,变量未存在…...
Java 扫雷游戏
程序分析 使用Java编写的扫雷游戏界面程序,主要内容总结如下: Frame类继承自JFrame,构建了扫雷游戏的界面。 包含文本框text、标签nowBomb和setBomb、按钮start、面板MenuPamel和bombPanel等组件。通过jbInit方法进行初始化设置,…...
vue3 命令运行窗口暴露网络地址,以及修改端口号
一般情况下这里的地址是隐藏的 这里加上 --host 可以暴露网络地址,再加上--port --8080 就可以将端口号修改为8080(修改后边的数字就可以修改为你想要的端口号)...
由CANoe自带协议栈在TCP断开连接时同时发送两条FIN报文引起的注意事项
在我写这篇文章CAPL如何在底层模拟TCP Server端断开TCP连接时,我发现了一个奇怪的现象。我为了使用CAPL组装报文的方式实现TCP Server断开连接的过程,插入一个网络节点作为Client端。为了让Client能够发起连接和发起断开连接,给网络节点配置了独立的TCP/IP Stack,也就是CAN…...
FastGPT部署和接入使用重排模型bce-reranker-base
bce-reranker简介 bce-reranker 是一种专门用于信息检索和自然语言处理领域中的重排序(reranking)模型。这种模型由北京智源人工智能研究院(BAAI)开发,是 BGE(BAAI General Embedding)系列的一部分。BGE 系列模型专注于提供通用的嵌入表示,而 bce-reranker 则更进一步…...
Android笔试面试题AI答之线程Handler、Thread(2)
答案仅供参考,来自 讯飞星火大模型 目录 1.Android多线程间通信和多进程之间通信有什么不同,分别怎么实现?2.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系?3.Android 线程间通信有哪几种方式?4.子线程发消息…...
某某物联rabbitmqhttp二轮充电桩协议充电协议对接
对接方式概述: 1)请求采用 http 协议方式,推送数据采用 amqp(默认 rabbitmq)点对点消息队 列方式。 2)消息队列连接信息,需贵方完善。 1 hostIp: 2 virtualHost: 3 userName: 4 pass…...
黑马JavaWeb企业级开发(知识清单)03——HTML实现正文:排版(音视频、换行、段落)、布局标签(div、span)、盒子模型
文章目录 前言一、正文排版1. 视频标签: < video >2. 音频标签: < audio >3. 换行标签: < br >4. 段落标签 < p >5. vscode实现 二、布局1. 盒子模型2. 布局标签< div >和< span >3. VScode实现 三、源代码和运行结果总结 前言 本篇文章是…...
Java | Leetcode Java题解之第283题移动零
题目: 题解: class Solution {public void moveZeroes(int[] nums) {int n nums.length, left 0, right 0;while (right < n) {if (nums[right] ! 0) {swap(nums, left, right);left;}right;}}public void swap(int[] nums, int left, int right)…...
Django REST Framework(十三)视图集-GenericViewSet
Django REST Framework 中,ModelViewSet 和 ReadOnlyModelViewSet 提供了快速实现常见视图操作的便捷方法。它们分别继承自 GenericViewSet 并组合了多个 Mixin 类,使得视图的编写变得更加简单。 ModelViewSet ModelViewSet 继承自 GenericViewSet&…...
《0基础》学习Python——第二十四讲__爬虫/<7>深度爬取
一、深度爬取 深度爬取是指在网络爬虫中,获取网页上的所有链接并递归地访问这些链接,以获取更深层次的页面数据。 通常,一个简单的爬虫只会获取到初始页面上的链接,并不会进一步访问这些链接上的其他页面。而深度爬取则会不断地获…...
Python Pygame制作简单五子棋游戏
代码参考自:https://blog.csdn.net/weixin_43918046/article/details/119521845 新增功能:1任意棋盘大小;2.任意棋子连线 # 棋盘大小 [670, 670] # 棋盘行列 15*15 import pygame from pygame.locals import QUIT, KEYDOWN import numpy as…...
JS+H5在线文心AI聊天(第三方接口)
源码在最后面 调用的不是文心官方接口 可以正常聊天 有打字动画 效果图 源代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-s…...
kafka源码阅读-ReplicaStateMachine(副本状态机)解析
概述 Kafka源码包含多个模块,每个模块负责不同的功能。以下是一些核心模块及其功能的概述: 服务端源码 :实现Kafka Broker的核心功能,包括日志存储、控制器、协调器、元数据管理及状态机管理、延迟机制、消费者组管理、高并发网络…...
【MetaGPT系列】【MetaGPT完全实践宝典——如何定义单一行为多行为Agent】
目录 前言一、智能体1-1、Agent概述1-2、Agent与ChatGPT的区别 二、多智能体框架MetaGPT2-1、安装&配置2-2、使用已有的Agent(ProductManager)2-3、拥有单一行为的Agent(SimpleCoder)2-3-1、定义写代码行为2-3-2、角色定义2-3…...
Kolla-Ansible的确是不支持CentOS-Stream系列产品了
看着OpenStack最新的 C 版本出来一段时间了,想尝个鲜、用Kolla-Ansible进行容器化部署,结果嘛。。。 根据实验结果,自OpenStack Bobcat版本开始,Kolla-Ansible就适合在CentOS系列产品上部署了,通过对 Bobcat和Caracal…...
IDEA启动C:\Users\badboy\.jdks\corretto-17.0.7\bin\java.exe -Xmx700m报错
这篇文章写的就很详细了(IDEA启动C:\Users\badboy\.jdks\corretto-17.0.7\bin\java.exe -Xmx700m报错_error occurred during initialization of vm failed -CSDN博客)...
ctfshow298-300(java信息泄露,代码审计)
Web298 代码审计 这里看到getVipStatus方法,获得了获取flag的条件就是user等于admin,password等于ctfshow Poc: https://d036a90d-ac1c-4de1-9b0b-86f52d2586b9.challenge.ctf.show/ctfshow/login?usernameadmin&passwordctfshow Web299 打开页面…...
Java 基础 and 进阶面试知识点(超详细)
一个 Java 文件中是否可以存在多个类(修饰类除外)? 一个 Java 文件中是可以存在多个类的,但是一个 Java 文件中只能存在一个 public 所修饰的类,而且这个 Java 文件的文件名还必须和 public 所修饰类的类名保持一致&a…...
【LabVIEW作业篇 - 5】:水仙花数、数组与for循环的连接
文章目录 水仙花数数组与for循环的连接 水仙花数 水仙花数,是指一个3位数,它的每个位上的数字的3次幂之和等于它本身。如371 3^3 7^3 1^3,则371是一个水仙花数。 思路:水仙花数是一个三位数,通过使用for循环…...
Kafka系列之如何提高消费者消费速度
前言 在实际开发过程中,如果使用Kafka处理超大数据量(千万级、亿级)的场景,Kafka消费者的消费速度可能决定系统性能瓶颈。 实现方案 为了提高消费者的消费速度,我们可以采取以下措施: 将主题的分区数量增大,如 20&…...
mac安装Whisper
Whisper 官方git https://github.com/openai/whisper?tabreadme-ov-file 基本上参考官方的安装流程 pip3 install -U openai-whisper pip3 install githttps://github.com/openai/whisper.git pip3 install --upgrade --no-deps --force-reinstall githttps://github.com/…...
Linux:进程概述(什么是进程、进程控制块PCB、并发与并行、进程的状态、进程的相关命令)
进程概述 (1)What(什么是进程) 程序:磁盘上的可执行文件,它占用磁盘、是一个静态概念 进程:程序执行之后的状态,占用CPU和内存,是一个动态概念;每一个进程都有一个对应的进程控制块…...
Unity UGUI 之 坐标转换
本文仅作学习笔记与交流,不作任何商业用途 本文包括但不限于unity官方手册,唐老狮,麦扣教程知识,引用会标记,如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本,请注意分别 前置知识:…...
使用 uPlot 在 Vue 中创建交互式图表
本文由ScriptEcho平台提供技术支持 项目地址:传送门 使用 uPlot 在 Vue 中创建交互式图表 应用场景介绍 uPlot 是一个轻量级、高性能的图表库,适用于创建各种交互式图表。它具有丰富的功能,包括可自定义的轴、网格、刻度和交互性。本篇博…...
SpringBoot 项目配置文件注释乱码的问题解决方案
一、问题描述 在项目的配置文件中,我们写了一些注释,如下所示: 但是再次打开注释会变成乱码,如下所示: 那么如何解决呢? 二、解决方案 1. 点击” File→Setting" 2. 搜索“File Encodings”, 将框…...
TTS如何正确读AI缩写、金额和数字
案例:Tell me whats AI(a i), you need pay $186.30, your card Number is 1 2 3, your work Number is 5 6 7 8...
python基础知识点(蓝桥杯python科目个人复习计划75)
第一题:ip补充 题目描述: 小蓝的ip地址为192.168.*.21,其中*是一个数字,请问这个数字最大可能是多少? import os import sys# 请在此输入您的代码 print("255") 第二题:出现最多的字符 题目描…...
小技巧:如何在已知PDF密码情况下去掉PDF的密码保护
第一步,用Edge打开你的pdf,输入密码进去 第二步,点击打印 第三步,选择导出PDF,选择彩印 第四步,选择导出位置,导出成功后打开发现没有密码限制了!...
Java泛型的介绍和基本使用
什么是泛型 泛型就是将类型参数化,比如定义了一个栈,你必须在定义之前声明这个栈中存放的数据的类型,是int也好是double或者其他的引用数据类型也好,定义好了之后这个栈就无法用来存放其他类型的数据。如果这时候我们想要使用这…...
【C++】动态内存管理与模版
目录 1、关键字new: 1、用法: 2、理解: 3、与malloc的相同与不同: 1、相同: 2、不同: 2、模版初阶: 1、函数模版: 1、概念: 2、关键字:template&…...
MongoDB - 组合聚合阶段:$group、$match、$limit、$sort、$skip、$project、$count
文章目录 1. $group2. $group-> $project2.1 $group2.2 $group-> $project2.3 SpringBoot 整合 MongoDB 3. $match-> $group -> $match3.1 $match3.2 $match-> $group3.3 $match-> $group-> $match3.4 SpringBoot 整合 MongoDB 4. $match-> $group->…...
vue element-ui日期控件传参
前端:Vue element-ui <el-form-item label"过期时间" :rules"[ { required: true, message: 请选择过期时间, trigger: blur }]"><el-date-picker v-model"form.expireTime" type"date" format"yyyy-MM-dd&…...
MacOS安装SDKMan管理Java版本
文章目录 1 简介2 安装与卸载2.1 安装2.2 卸载 3 使用3.1 查看其他工具:支持 Ant, Maven 等3.2 查看Java版本3.3 安装Java,加上相关的版本3.4 设置Java版本(全局)3.5 只在当前窗口生效3.6 卸载1 默认环境无法卸载 4 jdk安装的位置5 与IDEA集成参考 1 简介…...