当前位置: 首页 > news >正文

使用 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 开发中&#xff0c;前后端分离的架构已经成为主流。本文将详细介绍如何使用 Vue3、Node.js、MySQL、Electron 和 Express 实现一个完整的用户登录、文章管理和截屏功能的应用。我们将从项目的初始化开始&#xff0c;逐步实现各个功能模块&#xff0c;并提供详细的代…...

django中日志模块logging的配置和使用

一、文件的配置 settings.py文件中添加LOGGING块的配置&#xff0c;配置如下 # 日志记录 LOGGING {"version": 1,"disable_existing_loggers": False, # 用于确定在应用新的日志配置时是否禁用之前配置的日志器# 格式器"formatters": {"v…...

pyqt/pyside QTableWidget失去焦点后,选中的行仍高亮的显示

正常情况下pyqt/pyside的QTableWidget&#xff0c;点击input或者按钮失去焦点后 行的颜色消失了 如何在失去焦点时保持行的选中颜色&#xff0c;增加下面的代码&#xff1a; # 获取当前表格部件的调色板 p tableWidget.palette()# 获取活跃状态下的高亮颜色和高亮文本颜色&a…...

函数定义、合约与面向对象(以太坊solidity合约)

函数定义、合约与面向对象&#xff08;以太坊solidity合约&#xff09; 1-函数定义、构造与多态2-事件日志3-面向对象特征 1-函数定义、构造与多态 创建合约就是创建类&#xff0c;部署合约就是实例化 合约的方法还支持多态 还能使用第三方的库进行开发 整个合约部署后&…...

微服务: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 中&#xff0c;控件模板&#xff08;ControlTemplate&#xff09;、样式&#xff08;Style&#xff09;、自定义控件&#xff08;CustomControl&#xff09;和用户控件&#xff08;UserControl&#xff09;都是构建复杂和灵活用户界面的重要工具&#xff0c;但它们…...

如何用EXCEL自动解方程/方程组?利用 矩阵乘法X=A-*B,X=mmult(minverse(A), B)

目录 问题的由来 1 数据 → 模拟分析 → 单变量求解 1.1 找一个单元格填入公式 1.2 功能入口 1.3 选择单变量求解&#xff0c;分别填入内容 1.4 求解 1.5 这个感觉用处不大 2 重点介绍&#xff0c;用EXCEL进行矩阵运算解方程的操作 2.1 运用EXCEL进行矩阵运算&…...

ComfyUI进阶:Comfyroll插件 (二)

前言&#xff1a; 学习ComfyUI是一场持久战&#xff0c;而Comfyroll Studio 是一款功能强大的自定义节点集合&#xff0c;专为 ComfyUI 用户打造&#xff0c;旨在提供更加丰富和专业的图像生成与编辑工具。借助这些节点&#xff0c;用户可以在静态图像的精细调整和动态动画的复…...

Spring Boot集成Activity7实现简单的审批流

由于客户对于系统里的一些新增数据&#xff0c;例如照片墙、照片等&#xff0c;想实现上级逐级审批通过才可见的效果&#xff0c;于是引入了Acitivity7工作流技术来实现&#xff0c;本文是对实现过程的介绍讲解&#xff0c;由于我是中途交接前同事的这块需求&#xff0c;所以具…...

自动驾驶,革了谁的命

概述 从AI 的出现开始&#xff0c;到现在已经慢慢地开始改变着周遭的世界。 从对话聊天&#xff0c;到当前的看图识文&#xff0c;图片转动效等等&#xff0c;慢慢地在与实体结合后&#xff0c;其发挥的威力是巨大的。 科技将会是改变世界的核心驱动力之一&#xff0c;已经深…...

在线实习项目|泰迪智能科技企业级项目学习,暑期大数据人工智能学习

在线实习介绍 实习时间&#xff1a;每个项目周期七周左右 面向对象&#xff1a;大数据、计算机相关专业学生&#xff1b;大三、大四毕业年度学生 在线实习收获 1、获得项目实战技能&#xff0c;积累项目经验 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 【常见模块错误】 解决办法&#xff1a; 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&…...

Lua 运算符

Lua 运算符 Lua 是一种轻量级的编程语言&#xff0c;广泛用于游戏开发、脚本编写和其他应用程序。它具有一套丰富的运算符&#xff0c;用于执行各种数学和逻辑操作。本文将详细介绍 Lua 中的运算符&#xff0c;包括算术运算符、关系运算符、逻辑运算符和其他特殊运算符。 算术…...

园区道路车辆智能管控视频解决方案,打造安全畅通的园区交通环境

一、背景需求分析 随着企业园区的快速发展和扩张&#xff0c;道路车辆管理成为了保障园区秩序、提升运营效率及确保员工安全的重要任务。针对这一需求&#xff0c;旭帆科技TSINGSEE青犀提出了一种企业园区道路车辆管控的解决方案&#xff0c;通过整合视频监控、智能识别等技术…...

MATLAB R2023b下载安装教程汉化中文版设置

MATLAB R2023b下载安装教程汉化中文版设置 Matlab 是一款功能强大的商业数学软件 Matlab&#xff08;Matrix Labortory&#xff09;即矩阵实验室&#xff0c;它在数值计算、数据分析、算法开发、建模与仿真等众多领域都发挥着重要作用。 Matlab 具有以下显著特点和优势&…...

Java二十三种设计模式-工厂方法模式(2/23)

工厂方法模式&#xff1a;设计模式中的瑞士军刀 引言 在软件开发中&#xff0c;工厂方法模式是一种常用的创建型设计模式&#xff0c;它用于处理对象的创建&#xff0c;将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程&#xff0c;还提高了代码的可维护性…...

【iOS】OC类与对象的本质分析

目录 前言clang常用命令对象本质探索属性的本质对象的内存大小isa 指针探究 前言 OC 代码的底层实现都是 C/C代码&#xff0c;OC 的对象都是基于 C/C 的数据结构实现的&#xff0c;实际 OC 对象的本质就是结构体&#xff0c;那到底是一个怎样的结构体呢&#xff1f; clang常用…...

【机器学习】使用Python的dlib库实现人脸识别技术

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、传统人脸识别技术1. 基于几何特征的方法2. 基于模板匹配的方法3. 基于统计学习的方法 三、深度学习在脸识别中的应用1. 卷积神经网络&#xff08;CNN&#xff09;2. FaceNet和ArcFace 四、使用Python和dlib库实…...

GitHub 令牌泄漏, Python 核心资源库面临潜在攻击

TheHackerNews网站消息&#xff0c;软件供应链安全公司 JFrog 的网络安全研究人员称&#xff0c;他们发现了一个意外泄露的 GitHub 令牌&#xff0c;可授予 Python 语言 GitHub 存储库、Python 软件包索引&#xff08;PyPI&#xff09;和 Python 软件基金会&#xff08;PSF&…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...