从0开始搭建vue + flask 旅游景点数据分析系统(十二)【完结篇】:用户管理之增删改查、用户信息更新

这一期继续完成用户管理的增删改查和登录用户修改自己信息的功能,首先完成后端接口的功能。

1 后端接口

这边有查询列表接口、查询单个接口、新增接口、修改接口、删除接口这5个接口:

#** 用户信息的增删改查 ***
# 用户列表
@main.route('/users', methods=['GET'])
def get_users():try:username = request.args.get('username', '')  # 获取查询参数中的 titlepage = int(request.args.get('page', 1))  # 获取当前页码,默认为 1limit = int(request.args.get('limit', 10))  # 获取每页显示的记录数,默认为 10# 根据 title 进行模糊搜索query = User.query.filter(User.username.like(f'%{username}%'), User.deleted==0)# 计算总数和获取当前页数据total = query.count()  # 总记录数records = query.offset((page - 1) * limit).limit(limit).all()  # 当前页的数据result = users_schema.dump(records)  # 使用你的序列化方案处理数据return make_response(data={'total': total, 'records': result})except Exception as e:return make_response(code=1, message=str(e))@main.route('/user/<int:id>', methods=['GET'])
def get_user(id):try:user = User.query.get(id)  # 根据 ID 查询用户result = user_schema.dump(user)  # 使用你的序列化方案处理数据return make_response(data=result)except Exception as e:return make_response(code=1, message=str(e))@main.route('/user', methods=['POST'])
def add_user():data = request.json  # 获取JSON数据# 这里可以进行数据验证,例如检查必填字段是否存在required_fields = ['username', 'realname', 'job', 'age', 'addr', 'intro', 'phone', 'email']for field in required_fields:if field not in data:return make_response(code=1, message=f'错误,缺少字段: {field}')notnull_fields = ['username']for field in notnull_fields:if data[field]=='' or data[field]==None:return make_response(code=1, message= f'错误,字段不能为空: {field}')hashed_password = generate_password_hash('123456')# 创建新的用户对象new_record = User(realname=data['realname'],username=data['username'],password=hashed_password,job=data['job'],age=data['age'],addr=data['addr'],intro=data['intro'],phone=data['phone'],email=data['email'],deleted=0)# 将新景点添加到数据库db.session.add(new_record)db.session.commit()return make_response(code=0, message='添加用户成功')@main.route('/user/<int:id>', methods=['PUT'])
def update_user(id):data = request.json  # 获取JSON数据user = User.query.get(id)  # 根据ID查找if not user:return make_response(code=1, message='用户不存在')# 更新字段for field in ['realname', 'job', 'addr', 'intro', 'phone', 'email', 'age']:if field in data:setattr(user, field, data[field])db.session.commit()return make_response(code=0, message='修改用户成功')@main.route('/user/<int:id>', methods=['DELETE'])
def delete_user(id):user = User.query.get(id)  # 根据ID查找景点if not user:return make_response(code=1, message='用户不存在')user.deleted = 1db.session.commit()return make_response(code=0, message='删除用户成功')

2 前端 Users.vue界面

因为前面已经做过旅游景点信息的增删改查了,所以这次加快速度,直接给出完整源码,先添加users.js的接口:

<template><div class="users-container"><el-card class="box-card"><div slot="header" class="header"><span class="header-title">用户管理</span><div class="header-controls"><el-input v-model="searchParam" placeholder="输入标题进行搜索" class="search-input"></el-input><el-button type="primary" @click="fetchData">搜索</el-button><el-button type="success" @click="handleAdd">添加用户</el-button></div></div><el-table :data="records" style="width: 100%"><el-table-column prop="id" label="ID" width="50"></el-table-column><el-table-column prop="username" label="用户名" min-width="180"></el-table-column><el-table-column prop="realname" label="姓名" min-width="180"></el-table-column><el-table-column prop="age" label="年龄" min-width="180"></el-table-column><el-table-column prop="job" label="职业" min-width="180"></el-table-column><el-table-column prop="phone" label="电话" min-width="180"></el-table-column><el-table-column prop="addr" label="地址" min-width="180"></el-table-column>
<!--        <el-table-column prop="intro" label="签名" min-width="180"></el-table-column>--><el-table-column prop="email" label="邮箱"></el-table-column><el-table-column label="操作" width="180"><template slot-scope="scope"><el-button @click="handleEdit(scope.row)" type="text" size="small">编辑</el-button><el-button @click="handleDelete(scope.row)" type="text" size="small">删除</el-button></template></el-table-column></el-table><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="currentPage":page-size="pageSize":total="totalItems"layout="total, sizes, prev, pager, next, jumper"/></el-card><el-dialog :title="dialogTitle" :visible.sync="dialogVisible"><el-form :model="form"><el-form-item label="用户名" :label-width="formLabelWidth"><el-input v-model="form.username"></el-input></el-form-item><el-form-item label="姓名" :label-width="formLabelWidth"><el-input v-model="form.realname"></el-input></el-form-item><!-- 年龄输入框 --><el-form-item label="年龄" :label-width="formLabelWidth"><el-input-numberv-model="form.age":min="0":max="120"size="small"></el-input-number></el-form-item><el-form-item label="地址" :label-width="formLabelWidth"><el-input v-model="form.addr"></el-input></el-form-item><!-- 职业选择框 --><el-form-item label="职业" :label-width="formLabelWidth"><el-select v-model="form.job" placeholder="请选择职业"><el-option label="学生" value="学生"></el-option><el-option label="公务员" value="公务员"></el-option><el-option label="律师" value="律师"></el-option><el-option label="IT工程师" value="IT工程师"></el-option><el-option label="外卖员" value="外卖员"></el-option><el-option label="文员" value="文员"></el-option></el-select></el-form-item><el-form-item label="电话" :label-width="formLabelWidth"><el-input v-model="form.phone"></el-input></el-form-item><el-form-item label="邮箱" :label-width="formLabelWidth"><el-input v-model="form.email"></el-input></el-form-item><el-form-item label="签名" :label-width="formLabelWidth"><el-input v-model="form.intro"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="handleSave">保存</el-button></div></el-dialog></div>
</template><script>
import {users, addUser, updateUser, deleteUser} from "@/api/user";export default {data() {return {dialogTitle: '',searchParam: '',records: [],dialogVisible: false,form: {},formLabelWidth: '80px',totalItems: 0,currentPage: 1,pageSize: 10,};},mounted() {this.currentPage = 1this.loadData()},methods: {fetchData() {this.loadData()},//加载数据loadData() {users(this.searchParam, this.currentPage, this.pageSize).then(res => {this.records = res.data.data.recordsthis.totalItems = res.data.data.total})},handleAdd() {this.dialogTitle = '新增用户'this.dialogVisible = true;this.form = {};},handleEdit(record) {this.dialogTitle = '编辑用户'this.dialogVisible = true;this.form = {...record};},handleDelete(record) {deleteUser(record.id).then(res => {this.$message(res); // 使用封装的 $message 函数})},handleSave() {if (this.form.id) {updateUser(this.form.id, this.form).then(res => {// console.log(res.data.message)this.$message(res); // 使用封装的 $message 函数})} else {addUser(this.form).then(res => {console.log(res.data.message)this.$message(res); // 使用封装的 $message 函数})}this.dialogVisible = false;this.loadData()},handleCurrentChange(page) {this.currentPage = page;this.loadData();},handleSizeChange(size) {this.pageSize = size;this.loadData();},}
}
</script><style scoped>
.tours-container {padding: 20px;
}.header {display: flex;justify-content: space-between;align-items: center;padding: 10px 20px;
}.dialog-footer {text-align: right;
}.header-title {font-size: 18px;font-weight: bold;
}.header-controls {display: flex;align-items: center;
}.search-input {width: 300px;margin-right: 10px; /* Adjust spacing between input and buttons */
}
</style>

然后修改Users.vue界面

3 完成 Profile.vue界面

<template><div class="profile-settings"><el-card class="box-card"><div slot="header" class="clearfix"><span>个人设置</span></div><el-form :model="form" label-width="100px" :rules="rules" ref="profileForm"><el-form-item label="用户名" prop="username"><el-input v-model="form.username" disabled></el-input></el-form-item><el-form-item label="真实姓名" prop="realname"><el-input v-model="form.realname" ></el-input></el-form-item><!-- 年龄输入框 --><el-form-item label="年龄" ><el-input-numberv-model="form.age":min="0":max="120"size="small"></el-input-number></el-form-item><!-- 职业选择框 --><el-form-item label="职业" ><el-select v-model="form.job" placeholder="请选择职业"><el-option label="学生" value="学生"></el-option><el-option label="公务员" value="公务员"></el-option><el-option label="律师" value="律师"></el-option><el-option label="IT工程师" value="IT工程师"></el-option><el-option label="外卖员" value="外卖员"></el-option><el-option label="文员" value="文员"></el-option></el-select></el-form-item><el-form-item label="签名" prop="intro"><el-input type="textarea" v-model="form.intro"></el-input></el-form-item><el-form-item label="地址" prop="addr"><el-input v-model="form.addr"></el-input></el-form-item><el-form-item label="手机" prop="phone"><el-input v-model="form.phone"></el-input></el-form-item><el-form-item label="邮箱" prop="email"><el-input v-model="form.email"></el-input></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">保存</el-button></el-form-item></el-form></el-card></div>
</template><script>
import {get_one, updateUser} from "@/api/user";export default {data() {return {form: {},rules: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],profession: [{ required: true, message: '请输入职业', trigger: 'blur' }],phone: [{ required: true, message: '请输入手机号码', trigger: 'blur' },{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }],email: [{ required: true, message: '请输入邮箱地址', trigger: 'blur' },{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }]}};},mounted() {const user = JSON.parse(localStorage.getItem('user'));get_one(user.id).then(res=>{// console.log(res.data)this.form = res.data.data})},methods: {onSubmit() {this.$refs.profileForm.validate((valid) => {if (valid) {updateUser(this.form.id, this.form).then(res => {this.$message(res)})} else {return false;}});},}
};
</script><style scoped>
.profile-settings {padding: 20px;
}
</style>

4 项目小结

通过十二期的文章我们终于完成了旅游景点数据分析系统,下面来验收下成果,下面是课程涉及知识点的思维导图:

以下是我们完成的系统界面效果:

4.1 登录界面 & 注册界面

在这里插入图片描述
在这里插入图片描述

4.2 数据大屏界面 & 布局

在这里插入图片描述

4.3 景点管理界面

在这里插入图片描述
在这里插入图片描述

4.4 用户管理界面

在这里插入图片描述

4.5 个人信息修改界面

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/401468.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第36讲:使用Prometheus监控系统全方面监控Ceph集群

文章目录 1.启用Manager组件的Prometheus模块2.部署并配置Prometheus2.1.部署Prometheus服务端2.2.配置Prometheus添加Ceph集群的监控信息2.3.观察Prometheus监控系统中是否能浏览Ceph集群的监控数据 3.部署Grafana用于展示Prometheus的监控数据3.1.部署Grafana仪表盘3.2.Grafa…

开发工具及框架分享

文章目录 前言一、IDEA 开发工具知识分享1.1 功能特点介绍1.2 常见插件使用1.3 快捷键设置1.4 代码调试 二、Maven项目依赖管理介绍2.1 Maven 介绍2.2 Maven 安装及配置2.3 Maven 功能与特性2.4 打包测试 三、Springboot框架介绍3.1 核心特征概述3.2 常用注解介绍3.3 自动装配原…

yolov8/yolov10 MLU370 实现推理/单多卡训练!

文章目录 前言一、平台环境配置二、基础环境配置1.代码下载2.环境安装3.模型下载4.代码修改 三.单卡推理四、单/多卡训练 前言 本章主要操作以yolov8为主&#xff0c;但是yolov10用该操作也能直接适用&#xff0c;开干&#xff01; 一、平台环境配置 镜像选择&#xff1a;v2…

Python Django 框架 01

1. 以新闻内容为主的网站-Django。CMS 查看django官方网站。查看django源码。查看中文文档。对于Django框架遵循MVC设计&#xff0c;并且有个专用名字&#xff1a;MVT。 model 只适用于关系型数据库。 建议使用谷歌浏览器。 Django环境配置 python 环境 因为Django是需要Py…

Leetcode每日刷题之面试题01.02判断是否互为字符重排(C++)

1. 题目解析 本题判断的是两个字符串&#xff0c;其中一个字符串变换顺序是否可以变化为第二个字符串&#xff0c;即重排后是否为同一字符串 2. 算法原理 这里我的思路是直接统计两字符串中字符出现的次数&#xff0c;然后直接比较即可&#xff0c;我使用了范围for以及字符ASCI…

【系统架构设计】系统性能评价

【系统架构设计】系统性能评价 性能指标对计算机对网络对操作系统对数据库管理系统对Web服务器 性能计算MIPS(百万条指令/秒)计算方法峰值计算等效指令速度 性能设计性能评估 性能指标 对计算机 时钟频率&#xff08;主频&#xff09; 指计算机处理器的时钟频率&#xff0c;…

2024 D^3CTF pwn(d3note write_flag_where D3BabyEscape pwnshell)

文章目录 d3note libc 2.37源码exp write_flag_where glibc 2.38源码改scanf利用 改write D3BabyEscape源码exp pwnshellphp堆源码exp d3note libc 2.37 源码 index越界&#xff0c;show也没有检查&#xff0c;直接打印&#xff0c;这里找到got表&#xff0c;直接开搜就行 然后…

asp.net core 调用wps实现word转pdf

安装wps https://www.wps.cn/ 创建.net core控制项目 添加com引用&#xff0c;搜索wps 准备word&#xff0c;名字叫001.docx word转pdf 编写代码 namespace WPSStu01 {internal class Program{static void Main(string[] args){Console.WriteLine("转化开始&q…

日撸Java三百行(day24:二叉树的建立)

目录 一、分析准备 二、代码实现 1.方法创建 2.数据测试 3.完整的程序代码 总结 一、分析准备 在日撸Java三百行&#xff08;day22&#xff1a;二叉树的存储&#xff09;中&#xff0c;我们学习的是如何将链表二叉树转换为顺序表二叉树进行存储&#xff0c;而今天我们要…

一套完整的NVR方案与部分NVR录像机GUI源码剖析

一、部分功能展示 1.1 通道管理部分 在NVR系统中&#xff0c;通道管理是核心功能之一。通过通道管理&#xff0c;用户可以对连接的摄像头进行配置和监控。 通道连接使能&#xff1a;用户可以选择开启或关闭特定通道的连接功能&#xff0c;以实现灵活的设备管理。 时间同步&…

Kali Linux 三种网络攻击方法总结(DDoS、CC 和 ARP 欺骗)

一、引言 在当今数字化的时代&#xff0c;网络安全成为了至关重要的议题。了解网络攻击的方法和原理不仅有助于我们增强防范意识&#xff0c;更是网络安全领域专业人员必备的知识。Kali Linux 作为一款专为网络安全专业人员和爱好者设计的操作系统&#xff0c;提供了丰富的工具…

VideoPlayer插件的用法

文章目录 1. 概念介绍2. 使用方法2.1 实现步骤2.2 具体细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取文件类型"相关的内容&#xff0c;本章回中将介绍如何播放视频.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 播放视频是我们常用…

Windows11下wsl闪退的解决

wsl闪退 1. 原因分析 解释&#xff1a;WSL&#xff08;Windows Subsystem for Linux&#xff09;闪退通常指的是在Windows操作系统中运行的Linux环境突然关闭。这可能是由于多种原因造成的&#xff0c;包括系统资源不足、WSL配置问题、兼容性问题或者是Linux内核的问题。&…

【Python学习-UI界面】PyQt5 小部件13-Slider 拖动条

高级布局管理器&#xff0c;允许通过拖动边界来动态改变子小部件的大小。 Splitter控件提供一个手柄&#xff0c;可以拖动以调整控件的大小 样式如下: 常用方法如下&#xff1a; 序号方法描述1addWidget将小部件添加到拆分器的布局中2indexOf返回布局中小部件的索引3insetW…

MySQL架构与数据库基础

文章目录 一、数据库概念二、数据库的简单概念三、SQL四、MySQL架构 一、数据库概念 数据库是一个以某种由组织的方式存储的数据集合。我们可以把数据库想象称为一个文件柜。此文件柜是一个存放数据的物理位置&#xff0c;不管数据是什么以及如何组织的。数据库本质也需要像文…

EMC学习笔记2——电磁兼容问题分析

分析一个电磁兼容问题一般从三方面入手&#xff0c;分别是骚扰源、敏感源、耦合路径。解决掉其中一个问题&#xff0c;就能解决大部分的电磁兼容问题。 例如&#xff1a;当骚扰源是雷电时&#xff0c;敏感源是电子线路时&#xff0c;我们需要消除的就是耦合电路。 耦合路径就是…

LLM - 微调(Fine-Tuning) Llama3 以及合并微调模型 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/141218047 在微调 Llama3 大模型时&#xff0c;需要注意一些事项&#xff1a; 合适的预训练模型&#xff1a;不同的预训练模型具有不同的特点和适…

Java 操作 Redis和redis持久化

一、Jedis 我们要使用 Java 来操作 Redis&#xff0c;Jedis 是 Redis 官方推荐的 java连接开发工具&#xff01; 使用Java 操作 Redis 中间件&#xff01; 1.导入对应的依赖 https://mvnrepository.com/artifact/redis.clients/jedis <dependency><groupId>redi…

Keycloak中授权的实现-转载

在Keycloak中实现授权&#xff0c;首先需要了解与授权相关的一些概念。授权&#xff0c;简单地说就是某个&#xff08;些&#xff09;用户或者某个&#xff08;些&#xff09;用户组&#xff08;Policy&#xff09;&#xff0c;是否具有对某个资源&#xff08;Resource&#xf…

CAN总线详解-理论知识部分

目录 CAN总线简介 CAN总线硬件电路 CAN电平标准 CAN收发器 ​编辑 CAN物理层特性 CAN总线帧格式 数据帧 数据帧格式 数据帧发展历史 遥控帧 错误帧 过载帧 帧间隔 位填充 波形实例 CAN总线接收方数据采样 接收方数据采样遇到的问题 位时序 硬同步 再同步 波…