使用 Vue3、Node.js、MySQL、Electron 和 Express 实现用户登录、文章管理和截屏功能
在现代 Web 开发中,前后端分离的架构已经成为主流。本文将详细介绍如何使用 Vue3、Node.js、MySQL、Electron 和 Express 实现一个完整的用户登录、文章管理和截屏功能的应用。我们将从项目的初始化开始,逐步实现各个功能模块,并提供详细的代码示例。
项目初始化
前端:Vue3
首先,我们使用 Vue CLI 创建一个新的 Vue3 项目:
npm install -g @vue/cli
vue create vue-electron-app
cd vue-electron-app
选择默认配置或根据需要进行自定义配置。
后端:Node.js 和 Express
在项目根目录下创建一个新的文件夹 server,并在其中初始化一个新的 Node.js 项目:
mkdir server
cd server
npm init -y
npm install express mysql body-parser cors
创建 server.js 文件并设置基本的 Express 服务器:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const port = 3000;app.use(cors());
app.use(bodyParser.json());app.listen(port, () => {console.log(`Server running on port ${port}`);
});
数据库:MySQL
创建一个新的 MySQL 数据库和表:
CREATE DATABASE vue_electron_app;USE vue_electron_app;CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(255) NOT NULL,password VARCHAR(255) NOT NULL
);CREATE TABLE articles (id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255) NOT NULL,content TEXT NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
实现用户登录功能
后端:用户登录 API
在 server 文件夹中创建一个新的文件 auth.js,并实现用户注册和登录功能:
const express = require('express');
const router = express.Router();
const mysql = require('mysql');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');const db = mysql.createConnection({host: 'localhost',user: 'root',password: 'password',database: 'vue_electron_app'
});router.post('/register', (req, res) => {const { username, password } = req.body;const hashedPassword = bcrypt.hashSync(password, 10);db.query('INSERT INTO users (username, password) VALUES (?, ?)', [username, hashedPassword], (err, result) => {if (err) return res.status(500).send(err);res.status(201).send('User registered');});
});router.post('/login', (req, res) => {const { username, password } = req.body;db.query('SELECT * FROM users WHERE username = ?', [username], (err, results) => {if (err) return res.status(500).send(err);if (results.length === 0) return res.status(404).send('User not found');const user = results[0];const isPasswordValid = bcrypt.compareSync(password, user.password);if (!isPasswordValid) return res.status(401).send('Invalid password');const token = jwt.sign({ id: user.id }, 'secret_key', { expiresIn: '1h' });res.status(200).send({ token });});
});module.exports = router;
在 server.js 中引入并使用该路由:
const authRoutes = require('./auth');
app.use('/auth', authRoutes);
前端:用户登录页面
在 Vue 项目中创建一个新的组件 Login.vue:
<template><div><h2>Login</h2><form @submit.prevent="login"><div><label for="username">Username:</label><input type="text" v-model="username" required /></div><div><label for="password">Password:</label><input type="password" v-model="password" required /></div><button type="submit">Login</button></form></div>
</template><script>
import axios from 'axios';export default {data() {return {username: '',password: ''};},methods: {async login() {try {const response = await axios.post('http://localhost:3000/auth/login', {username: this.username,password: this.password});localStorage.setItem('token', response.data.token);this.$router.push('/dashboard');} catch (error) {console.error('Login failed:', error);}}}
};
</script>
实现文章管理功能
后端:文章管理 API
在 server 文件夹中创建一个新的文件 articles.js,并实现文章的 CRUD 操作:
const express = require('express');
const router = express.Router();
const mysql = require('mysql');
const jwt = require('jsonwebtoken');const db = mysql.createConnection({host: 'localhost',user: 'root',password: 'password',database: 'vue_electron_app'
});const authenticate = (req, res, next) => {const token = req.headers['authorization'];if (!token) return res.status(401).send('Access denied');jwt.verify(token, 'secret_key', (err, decoded) => {if (err) return res.status(401).send('Invalid token');req.userId = decoded.id;next();});
};router.post('/articles', authenticate, (req, res) => {const { title, content } = req.body;db.query('INSERT INTO articles (title, content) VALUES (?, ?)', [title, content], (err, result) => {if (err) return res.status(500).send(err);res.status(201).send('Article created');});
});router.get('/articles', authenticate, (req, res) => {db.query('SELECT * FROM articles', (err, results) => {if (err) return res.status(500).send(err);res.status(200).send(results);});
});router.put('/articles/:id', authenticate, (req, res) => {const { id } = req.params;const { title, content } = req.body;db.query('UPDATE articles SET title = ?, content = ? WHERE id = ?', [title, content, id], (err, result) => {if (err) return res.status(500).send(err);res.status(200).send('Article updated');});
});router.delete('/articles/:id', authenticate, (req, res) => {const { id } = req.params;db.query('DELETE FROM articles WHERE id = ?', [id], (err, result) => {if (err) return res.status(500).send(err);res.status(200).send('Article deleted');});
});module.exports = router;
在 server.js 中引入并使用该路由:
const articleRoutes = require('./articles');
app.use('/api', articleRoutes);
前端:文章管理页面
在 Vue 项目中创建一个新的组件 ArticleManager.vue:
<template><div><h2>Article Manager</h2><form @submit.prevent="createArticle"><div><label for="title">Title:</label><input type="text" v-model="title" required /></div><div><label for="content">Content:</label><textarea v-model="content" required></textarea></div><button type="submit">Create Article</button></form><ul><li v-for="article in articles" :key="article.id"><h3>{{ article.title }}</h3><p>{{ article.content }}</p><button @click="deleteArticle(article.id)">Delete</button><button @click="editArticle(article)">Edit</button></li></ul></div>
</template><script>
import axios from 'axios';export default {data() {return {title: '',content: '',articles: []};},async created() {await this.fetchArticles();},methods: {async fetchArticles() {try {const response = await axios.get('http://localhost:3000/api/articles', {headers: { Authorization: localStorage.getItem('token') }});this.articles = response.data;} catch (error) {console.error('Failed to fetch articles:', error);}},async createArticle() {try {await axios.post('http://localhost:3000/api/articles', {title: this.title,content: this.content}, {headers: { Authorization: localStorage.getItem('token') }});this.title = '';this.content = '';await this.fetchArticles();} catch (error) {console.error('Failed to create article:', error);}},async deleteArticle(id) {try {await axios.delete(`http://localhost:3000/api/articles/${id}`, {headers: { Authorization: localStorage.getItem('token') }});await this.fetchArticles();} catch (error) {console.error('Failed to delete article:', error);}},editArticle(article) {this.title = article.title;this.content = article.content;// Implement update logic here}}
};
</script>
实现截屏功能
Electron:截屏功能
在项目根目录下安装 Electron:
npm install electron --save-dev
创建 main.js 文件并配置 Electron 主进程:
const { app, BrowserWindow, ipcMain, desktopCapturer } = require('electron');
const path = require('path');function createWindow() {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js'),contextIsolation: true,enableRemoteModule: false,nodeIntegration: false}});win.loadURL('http://localhost:8080');
}app.whenReady().then(createWindow);app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit();}
});app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow();}
});ipcMain.handle('capture-screen', async () => {const sources = await desktopCapturer.getSources({ types: ['screen'] });return sources[0].thumbnail.toDataURL();
});
创建 preload.js 文件并配置预加载脚本:
const { contextBridge, ipcRenderer } = require('electron');contextBridge.exposeInMainWorld('electron', {captureScreen: () => ipcRenderer.invoke('capture-screen')
});
前端:截屏功能页面
在 Vue 项目中创建一个新的组件 ScreenCapture.vue:
<template><div><h2>Screen Capture</h2><button @click="captureScreen">Capture Screen</button><img v-if="screenshot" :src="screenshot" alt="Screenshot" /></div>
</template><script>
export default {data() {return {screenshot: null};},methods: {async captureScreen() {try {this.screenshot = await window.electron.captureScreen();} catch (error) {console.error('Failed to capture screen:', error);}}}
};
</script>
结语
通过本文,我们详细介绍了如何使用 Vue3、Node.js、MySQL、Electron 和 Express 实现一个完整的用户登录、文章管理和截屏功能的应用。希望这篇文章能为你提供有价值的参考,帮助你更好地理解和实现前后端分离的应用开发。
如果你有任何问题或建议,欢迎在评论区留言讨论。Happy coding!
相关文章:
使用 Vue3、Node.js、MySQL、Electron 和 Express 实现用户登录、文章管理和截屏功能
在现代 Web 开发中,前后端分离的架构已经成为主流。本文将详细介绍如何使用 Vue3、Node.js、MySQL、Electron 和 Express 实现一个完整的用户登录、文章管理和截屏功能的应用。我们将从项目的初始化开始,逐步实现各个功能模块,并提供详细的代…...
django中日志模块logging的配置和使用
一、文件的配置 settings.py文件中添加LOGGING块的配置,配置如下 # 日志记录 LOGGING {"version": 1,"disable_existing_loggers": False, # 用于确定在应用新的日志配置时是否禁用之前配置的日志器# 格式器"formatters": {"v…...
pyqt/pyside QTableWidget失去焦点后,选中的行仍高亮的显示
正常情况下pyqt/pyside的QTableWidget,点击input或者按钮失去焦点后 行的颜色消失了 如何在失去焦点时保持行的选中颜色,增加下面的代码: # 获取当前表格部件的调色板 p tableWidget.palette()# 获取活跃状态下的高亮颜色和高亮文本颜色&a…...
函数定义、合约与面向对象(以太坊solidity合约)
函数定义、合约与面向对象(以太坊solidity合约) 1-函数定义、构造与多态2-事件日志3-面向对象特征 1-函数定义、构造与多态 创建合约就是创建类,部署合约就是实例化 合约的方法还支持多态 还能使用第三方的库进行开发 整个合约部署后&…...
微服务:nacos
Nacos 由Alibaba推出的集成于SpringCloudAlibaba中的一款开源注册中心框架 主要功能: 注册中心 配置管理 nacos的安装和部署 nacos默认访问端口8848 docker pull nacos/nacos-server:1.2.0 docker run --env MODEstandalone --name nacos --restartalways -d -p 8848:8…...
前端css常用笔记
文章目录 一、样式二、vue笔记2.1、组件之间的通信2.1.1 子组件调用父组件的方法2.1.2 父组件调用子组件的方法2.1.3 孙组件调用祖父组件方法的实现 2.2、使用若依时,node_nodules越来越大的问题2.3、echart笔记 一、样式 1 文字与图标对不齐的解决方法 /**给icon加上这个样式即…...
WINUI或WPF灵活使用样式、控件模板、自定义控件、用户控件
在WINUI与WPF 中,控件模板(ControlTemplate)、样式(Style)、自定义控件(CustomControl)和用户控件(UserControl)都是构建复杂和灵活用户界面的重要工具,但它们…...
如何用EXCEL自动解方程/方程组?利用 矩阵乘法X=A-*B,X=mmult(minverse(A), B)
目录 问题的由来 1 数据 → 模拟分析 → 单变量求解 1.1 找一个单元格填入公式 1.2 功能入口 1.3 选择单变量求解,分别填入内容 1.4 求解 1.5 这个感觉用处不大 2 重点介绍,用EXCEL进行矩阵运算解方程的操作 2.1 运用EXCEL进行矩阵运算&…...
ComfyUI进阶:Comfyroll插件 (二)
前言: 学习ComfyUI是一场持久战,而Comfyroll Studio 是一款功能强大的自定义节点集合,专为 ComfyUI 用户打造,旨在提供更加丰富和专业的图像生成与编辑工具。借助这些节点,用户可以在静态图像的精细调整和动态动画的复…...
Spring Boot集成Activity7实现简单的审批流
由于客户对于系统里的一些新增数据,例如照片墙、照片等,想实现上级逐级审批通过才可见的效果,于是引入了Acitivity7工作流技术来实现,本文是对实现过程的介绍讲解,由于我是中途交接前同事的这块需求,所以具…...
自动驾驶,革了谁的命
概述 从AI 的出现开始,到现在已经慢慢地开始改变着周遭的世界。 从对话聊天,到当前的看图识文,图片转动效等等,慢慢地在与实体结合后,其发挥的威力是巨大的。 科技将会是改变世界的核心驱动力之一,已经深…...
在线实习项目|泰迪智能科技企业级项目学习,暑期大数据人工智能学习
在线实习介绍 实习时间:每个项目周期七周左右 面向对象:大数据、计算机相关专业学生;大三、大四毕业年度学生 在线实习收获 1、获得项目实战技能,积累项目经验 2、获得在线实习证明 项目特点…...
【BUG】已解决:To update, run: python.exe -m pip install --upgrade pip
To update, run: python.exe -m pip install --upgrade pip 目录 To update, run: python.exe -m pip install --upgrade pip 【常见模块错误】 解决办法: 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰&…...
Lua 运算符
Lua 运算符 Lua 是一种轻量级的编程语言,广泛用于游戏开发、脚本编写和其他应用程序。它具有一套丰富的运算符,用于执行各种数学和逻辑操作。本文将详细介绍 Lua 中的运算符,包括算术运算符、关系运算符、逻辑运算符和其他特殊运算符。 算术…...
园区道路车辆智能管控视频解决方案,打造安全畅通的园区交通环境
一、背景需求分析 随着企业园区的快速发展和扩张,道路车辆管理成为了保障园区秩序、提升运营效率及确保员工安全的重要任务。针对这一需求,旭帆科技TSINGSEE青犀提出了一种企业园区道路车辆管控的解决方案,通过整合视频监控、智能识别等技术…...
MATLAB R2023b下载安装教程汉化中文版设置
MATLAB R2023b下载安装教程汉化中文版设置 Matlab 是一款功能强大的商业数学软件 Matlab(Matrix Labortory)即矩阵实验室,它在数值计算、数据分析、算法开发、建模与仿真等众多领域都发挥着重要作用。 Matlab 具有以下显著特点和优势&…...
Java二十三种设计模式-工厂方法模式(2/23)
工厂方法模式:设计模式中的瑞士军刀 引言 在软件开发中,工厂方法模式是一种常用的创建型设计模式,它用于处理对象的创建,将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程,还提高了代码的可维护性…...
【iOS】OC类与对象的本质分析
目录 前言clang常用命令对象本质探索属性的本质对象的内存大小isa 指针探究 前言 OC 代码的底层实现都是 C/C代码,OC 的对象都是基于 C/C 的数据结构实现的,实际 OC 对象的本质就是结构体,那到底是一个怎样的结构体呢? clang常用…...
【机器学习】使用Python的dlib库实现人脸识别技术
🔥 个人主页:空白诗 文章目录 一、引言二、传统人脸识别技术1. 基于几何特征的方法2. 基于模板匹配的方法3. 基于统计学习的方法 三、深度学习在脸识别中的应用1. 卷积神经网络(CNN)2. FaceNet和ArcFace 四、使用Python和dlib库实…...
GitHub 令牌泄漏, Python 核心资源库面临潜在攻击
TheHackerNews网站消息,软件供应链安全公司 JFrog 的网络安全研究人员称,他们发现了一个意外泄露的 GitHub 令牌,可授予 Python 语言 GitHub 存储库、Python 软件包索引(PyPI)和 Python 软件基金会(PSF&…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
