目录
1 效果
1.1 查询所有用户
1.2 添加新用户
1.3 删除用户
1.4 用户详情
2 后端
2.1 查询所有
2.2 添加
2.3 删除
2.4 查询单个
3 前端
3.1 环境
3.2 main.js
3.3 userList.vue
3.4 userInfo.vue
1 效果
1.1 查询所有用户
1.2 添加新用户
如果点击取消就会显示添加失败
1.3 删除用户
点击取消会显示删除失败
点击确定会显示删除成功
1.4 用户详情
2 后端
pymysql一直开着会有一些问题,只能在每一次查询进行一次启停,每一个视图中写一遍就很麻烦,所以用到了请求钩子
from flask import Flask,request
import pymysql
import json
app = Flask(__name__)
@app.before_request
def before_request():
global conn
conn = pymysql.connect(
host='127.0.0.1',
user='root',
password='12345678',
database='my_db_01',
charset='utf8'
)
@app.after_request
def after_request(response):
conn.commit()
conn.close()
return response
@app.route('/get_users')
def get_users():
cursor = conn.cursor()
sql = 'SELECT * FROM my_db_01.element_ui_users'
cursor.execute(sql)
datas = cursor.fetchall()
cursor.close()
return_results = []
for data in datas:
results_obj = {}
results_obj.__setitem__('id', data[0])
results_obj.__setitem__('username', data[1])
results_obj.__setitem__('age', data[2])
results_obj.__setitem__('position', data[3])
results_obj.__setitem__('create_time', data[4])
return_results.append(results_obj)
return json.dumps(return_results,ensure_ascii=False)
@app.route('/get_one_user')
def get_one_user():
id = request.args['id']
cursor = conn.cursor()
sql = 'SELECT * FROM my_db_01.element_ui_users where id=' + id
cursor.execute(sql)
datas = cursor.fetchall()
cursor.close()
for data in datas:
results_obj = {}
results_obj.__setitem__('id', data[0])
results_obj.__setitem__('username', data[1])
results_obj.__setitem__('age', data[2])
results_obj.__setitem__('position', data[3])
results_obj.__setitem__('create_time', data[4])
return json.dumps(results_obj,ensure_ascii=False)
@app.route('/add_user')
def add_user():
username = request.args['username']
age = request.args['age']
position = request.args['position']
create_time = request.args['create_time']
cursor = conn.cursor()
sql = "insert into my_db_01.element_ui_users (username,age,position,create_time) values ('{}',{},{},'{}')".format(username,age,position,create_time)
cursor.execute(sql)
cursor.close()
return json.dumps({'status':0,'message':'添加成功'},ensure_ascii=False)
@app.route('/delete_user')
def delete_user():
id = request.args['id']
cursor = conn.cursor()
sql = "delete from my_db_01.element_ui_users where id={}".format(id)
cursor.execute(sql)
cursor.close()
return json.dumps({'status':0,'message':'删除成功'},ensure_ascii=False)
if __name__ == '__main__':
app.run()
2.1 查询所有
2.2 添加
2.3 删除
2.4 查询单个
3 前端
3.1 环境
3.2 main.js
main.js主要解决了三个问题
- ElementUI
- axios
- vue-router
import { createApp } from 'vue'
import App from './App.vue'
import userInfo from '@/components/userInfo'
import userList from '@/components/userList'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import axios from 'axios'
import {createRouter,createWebHashHistory} from 'vue-router'
// 解决 ElTable 自动宽度高度导致的「ResizeObserver loop limit exceeded」问题,参考链接 https://blog.csdn.net/weixin_41296877/article/details/130675694
const debounce = (fn, delay) => {
let timer = null;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
}
const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver{
constructor(callback) {
callback = debounce(callback, 16);
super(callback);
}
}
// axios请求部分
// axios.defaults.baseURL = 'http://127.0.0.1:5000'
axios.defaults.baseURL = 'http://localhost:8080'
// 路由部分
const router = createRouter({
history:createWebHashHistory(),
routes:[
{path:'/',redirect:'/userList'},
{path:'/userList',component:userList},
{path:'/userInfo/:id',component:userInfo,props:true}
]
})
const app = createApp(App)
app.use(ElementPlus)
app.config.globalProperties.$http = axios
app.use(router)
app.mount('#app')
3.3 userList.vue
<template>
<!-- 按钮 -->
<el-button type="primary" style="margin-bottom: 20px;" @click="dialogFormVisible = true" >添加新用户</el-button>
<!-- 表格 -->
<el-table :data="userList" border stripe style="width: 100%">
<el-table-column type="index" label="#" />
<el-table-column prop="username" label="姓名" />
<el-table-column prop="age" label="年龄" />
<el-table-column prop="position" label="头衔" />
<el-table-column label="创建时间">
<template #default="scope">
{{ format_time(scope.row.create_time) }}
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="scope">
<div>
<router-link :to="'/userInfo/'+scope.row.id">详情</router-link>
<a href="javascript:void(0)" :delete_user_id="scope.row.id" @click="delete_user(scope.row.id)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
<!-- 提示框 -->
<el-dialog v-model="dialogFormVisible" title="添加新用户" @close="dialogClose()">
<el-form :model="add_user_form" :rules="add_user_form_rules" ref="add_user_form">
<el-form-item label="用户姓名" :label-width="formLabelWidth" prop="username">
<el-input v-model="add_user_form.username" autocomplete="off"/>
</el-form-item>
<el-form-item label="用户年龄" :label-width="formLabelWidth" prop="age">
<el-input v-model.number="add_user_form.age" autocomplete="off" />
</el-form-item>
<el-form-item label="用户头衔" :label-width="formLabelWidth" prop="position">
<el-input v-model="add_user_form.position" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="add_user();">
确认
</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { ElMessage, ElMessageBox } from 'element-plus'
export default {
name: 'userList',
data() {
return {
userList: [],
add_user_form: {
username: '',
age: '',
position: '',
create_time: new Date()
},
dialogFormVisible: false,
formLabelWidth: '100px',
add_user_form_rules: {
username: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 1, max: 15, message: '最小长度为1,最大长度为15', trigger: 'blur' },
],
age: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ validator:this.checkAge,trigger:'blur' }
],
position: [
{ required: true, message: '请输入头衔', trigger: 'blur' },
{ min: 1, max: 10, message: '最小长度为1,最大长度为10', trigger: 'blur' },
],
}
}
},
methods: {
get_users() {
this.$http.get('/get_users').then((res) =>{
this.userList=res.data
})
},
format_time(unformat_time) {
const dt = new Date(unformat_time)
const year = dt.getFullYear()
const month = (dt.getMonth() + 1) > 9 ? (dt.getMonth() + 1) : '0' + (dt.getMonth() + 1)
const day = (dt.getDate()) > 9 ? (dt.getDate()) : '0' + (dt.getDate())
const hour = (dt.getHours()) > 9 ? (dt.getHours()) : '0' + (dt.getHours())
const minute = (dt.getMinutes()) > 9 ? (dt.getMinutes()) : '0' + (dt.getMinutes())
const second = (dt.getSeconds()) > 9 ? (dt.getSeconds()) : '0' + (dt.getSeconds())
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
},
add_user() {
this.$refs.add_user_form.validate((valid)=>{
if (valid) {ElMessageBox.confirm(
'是否添加新用户?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
// type: 'info',
// center: true,
}
).then(() => {
this.$http.get('/add_user',{params:this.add_user_form}).then(()=>{
this.get_users()
this.dialogFormVisible = false
})
ElMessage({
type: 'success',
message: '添加成功',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '添加失败',
})
})
}
})
},
delete_user(delete_user_id) {
ElMessageBox.confirm(
'此操作将永久删除该用户,是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
// center: true,
}
).then(() => {
this.$http.get('/delete_user',{params:{id:delete_user_id}}).then(()=>{
this.get_users()
this.dialogFormVisible = false
})
ElMessage({
type: 'success',
message: '删除成功',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '删除失败',
})
})
},
checkAge(rule,value,callback) {
if (!value) {
return callback(new Error('年龄是必填项'))
}
if (!Number.isInteger(value)) {
return callback(new Error('你需要填写整数数字'))
}
if (value<1 || value>150) {
return callback(new Error('年龄的值应在1-150之间'))
}
callback()
},
dialogClose() {
this.$refs.add_user_form.resetFields()
}
},
created() {
this.get_users()
}
}
</script>
<style scoped>
.el-input {
width: 95%;
height: 40px;
}
</style>
3.4 userInfo.vue
<template>
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>用户详情</span>
<el-button class="button" text @click="this.$router.push('/userList')">返回</el-button>
</div>
</template>
<div class="text item">姓名 {{ username }}</div>
<div class="text item">年龄 {{ age }}</div>
<div class="text item">头衔 {{ position }}</div>
</el-card>
</template>
<script>
export default {
props:['id'],
data() {
return {
username:'',
age:'',
position:''
}
},
methods:{
get_one_user() {
this.$http.get('/get_one_user',{params:{id:this.id}}).then((res) =>{
this.username=res.data.username
this.age=res.data.age
this.position=res.data.position
})
},
},
created() {
this.get_one_user()
}
}
</script>
<style>
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
</style>