Python(Falsk) + React Golang(Gin) + Vue 全栈开发的最佳实践

news2024/11/13 18:10:59

        

        前面分别讲了 Python(Falsk) React Golang(Gin)Vue(Element),现在整体的给大家汇报一下,这个是简单搭建的demo,后面的添砖加瓦需要自己动手咯,有不明白的可以参考一下小编前面的文章,也许会给大家有答疑解惑的帮助

Python(Falsk):

https://blog.csdn.net/masterphp/article/details/136290855
https://blog.csdn.net/masterphp/article/details/138627802

React:

https://blog.csdn.net/masterphp/article/details/139242705

Golang(Gin):

https://blog.csdn.net/masterphp/article/details/129757434
https://blog.csdn.net/masterphp/article/details/130877001
https://blog.csdn.net/masterphp/article/details/131493155
https://blog.csdn.net/masterphp/article/details/131523360
https://blog.csdn.net/masterphp/article/details/132208407
https://blog.csdn.net/masterphp/article/details/132307220
https://blog.csdn.net/masterphp/article/details/132414796

Vscode的安装:

        首先讲一下Vscode的安装(用于React和Vue),本次完成项目的搭建,借助了一个工具:通意灵码,通意灵码:基于阿里云提供的一个服务,说的明白一点就是一个智能代码辅助工具,实际上用下来,个人觉得和Chatgpt平分秋色,各有各的优点与弊端,所以建议大家两个都去安装一下,适合自己的才是最好的

node14版本以上安装:

1.安装13版本
2.下载14版本zip(覆盖安装目录)
3.设置环境变量:NODE_SKIP_PLATFORM_CHECK :1
4.命令行使用 node -v 指令和npm -v ,检查当前 node 版本是否更新成功
5.设置全局模块存放路径和缓存文件夹(新建:node_global文件夹 + node_cache文件夹)
6.npm config set prefix "E:\node\node_global"    npm config set cache "E:\node\node_cache"
7.更换淘宝镜像(npm config set registry=https://registry.npm.taobao.org)
8.查看配置是否成功(npm config list)
9.设置环境变量: C:\Users\你的用户名\AppData\Roaming\npm 修改为 你的安装目录\node_global
10.新建环境变量(NODE_PATH :你的安装目录\node_global\node_modules)
11.新建环境变量(Path:%NODE_PATH%)

npm命令:

react-router-dom 安装命名(路由包):

npm install react-router-dom


antdesign安装命令(前端UI):

npm install antd --save
npm add antd@^4.24.2

使antdesign用babel-plugin-import插件可以实现按需加载:

npm install babel-plugin-import --save-dev


查看typescript版本:

npm view typescript version

CSS样式(5.0版本以下)

import  'antd/dist/antd.min.css'

CSS样式(5.0版本以上)

import 'antd/dist/antd.css'

cnpm安装

安装命令: npm install -g cnpm --registry=https://registry.npm.taobao.org 命令行下输入: cnpm -v 验证是否安装成功。


npm升级命令

npm install -g tar
npm uninstall fstream 


安装react:

1.npm install -g create-react-app(或者 npx create-react-app my-app)
2.create-react-app my-app(其中my-app是你的项目名称)
3.进入创建的项目目录:cd my-app
4.启动开发服务器:npm start


切换镜像:

npm config set registry= https://registry.npmjs.org/
npm config set registry=https://registry.npm.taobao.org

        Python使用的工具的PaCharm,使用这个工具的话需要激活码,所以大家懂的,有工具的,另外来说前期一个月的时间建议大家关闭代码提示,后期可以开启,主要是前期关闭可以加强关联记忆

        Golang使用的工具是Goland,其实使用Vscode也是非常好用的,看个人习惯,当然这个也是需要激活码的,所以嫌麻烦的同学可以直接上Vscode

Golang(Gin) + Vue:项目结构

GIN框架主入口:

package main

import (
	//GIN框架引入
	"github.com/gin-gonic/gin"
	//自定义模块引入
	"project/common"
	user "project/controller"
)

//初始化
func init()  {
	//数据库初始化
	common.Dbinit()
}

func main()  {
	//GIN框架初始化
	r := gin.Default()
	//设置安全访问
	r.SetTrustedProxies([]string{"127.0.0.1"})
	//定义常量
	r.Static("/source", "static")
	//设置模版
	r.LoadHTMLGlob("template/*")

	/*******************登录页开始***********************/
	r.GET("/login", func(c *gin.Context) {
		c.HTML(200,"login.html", gin.H{"title": "登录"})
	})

	r.POST("/logindo", func(context *gin.Context) {
		username := context.PostForm("username")
		password := context.PostForm("password")
		//判断
		if(username == "12" && password == "34"){
			//todo 设置session

			//返回值
			context.JSON(200, gin.H{
				"code": 0,
				"message":"成功",
			})
		}else{
			context.JSON(200, gin.H{
				"code": 1,
				"message":"参数错误",
			})
		}
	})
	/*******************登录页结束***********************/

	/*******************首页开始***********************/
	r.GET("/index", func(context *gin.Context) {
		context.HTML(200,"index.html",gin.H{"title": "首页"})
	})

	r.GET("/indexlist",user.Userlist)
	/*******************首页结束***********************/

	/*******************用户开始***********************/
	r.GET("/user_add", func(context *gin.Context) {
		context.HTML(200,"user_add.html",gin.H{"title":"新增用户"})
	})

	r.POST("/user_add_do",user.User_add_do)

	//用户编辑
	r.GET("/user_edit", func(context *gin.Context) {
		id := context.Query("id")
		context.HTML(200,"user_edit.html",gin.H{"title":"编辑用户","id":id})
	})

	r.POST("/user_info",user.User_info)

	//操作编辑
	r.POST("/user_edit_do",user.User_edit_do)

	r.POST("/user_del", user.User_del)
	/*******************用户结束***********************/

	/*******************文件上传开始***********************/
	r.POST("/imgupload",common.Imgupload)

	/*******************文件上传结束***********************/

	r.Run("localhost:8080")
}

数据库初始化:

package common

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

//定义全局变量
var  DB *gorm.DB

// 连接数据库的函数,返回一个 *sql.DB 对象以及一个 error 对象 (方法名记得大写,才可以被外部引用)。
func Dbinit(){
	dsn := "root:root@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	DB,_ = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	fmt.Print("connect success")
}

公共方法:

package common

import (
	"github.com/gin-gonic/gin"
)

// 定义一个结构体来映射分页查询的数据
type Pagination struct {
	// 当前页码
	Page int `json:"page"`
	// 每页数量
	PageSize int `json:"pageSize"`
	// 总页数
	TotalPages int `json:"totalPages"`
	// 总记录数
	TotalCount int `json:"totalCount"`
}


// 定义一个结构体来映射返回的数据
type Response struct {
	// 状态码
	Code int `json:"code"`
	// 数据
	Data interface{} `json:"data"`
	// 消息
	Msg string `json:"msg"`
}

type Publicmodel struct {
	ID uint `json:"id" gorm:"primaryKey"`
}

//文件上传
func Imgupload(context *gin.Context)  {
	// 单个文件(判断上传的文件是否为空)
	file, err := context.FormFile("file")
	if err != nil {
		context.JSON(500, gin.H{
			"message": err.Error(),
		})
		return
	}
	//文件上传路径
	dst := "./static/img/upload/" + file.Filename
	// 上传文件到指定的目录
	context.SaveUploadedFile(file, dst)
	//返回数据
	context.JSON(200, gin.H{
		"message": "上传成功",
		"filename": file.Filename,
		"raw": dst,
	})
}

登录页面:

<style>
    @import url("/source/index.css");
    .el-input__inner{width: 80%!important;}
    #app{width: 100%;height: 100%;background: url(/source/img/loginbg.png) #F5F5F5 no-repeat;background-size: 70%;position: absolute}
    #content{ box-shadow: 22px 22px 0px #ebebeb;margin-top: 10%;z-index: 999;width: 475px;padding: 2rem;
        box-sizing: border-box;background-color: #fff;border-radius: 5px;position: relative;left: 60%;height: 30%}
</style>

<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>

<div id="app">
    <div id="content">
        <el-form ref="form" :model="form" label-width="80px" >
            <el-form-item label="账号">
                <el-input type="text" v-model="form.username" autocomplete="off"  placeholder="请输入账号"></el-input>
            </el-form-item>

            <el-form-item label="密码">
                <el-input type="password" v-model="form.password" autocomplete="off" maxlength="10" placeholder="请输入密码"></el-input>
            </el-form-item>

            <el-form-item>
                <el-button type="primary" @click="onSubmit(form)">立即创建</el-button>
            </el-form-item>
        </el-form>
    </div>
</div>

<script>
    var Main = {
        data() {
            return {
                form: {
                    username: '',
                    password: '',
                },
                defaultProps: {
                    children: 'children',
                    label: 'label'
                }
            }
        },
        methods: {
            onSubmit(form) {
                //必须使用这个数组
                // let param = new URLSearchParams()
                let param = new FormData()
                //填充护数据
                param.append('username',this.form.username)
                param.append('password',this.form.password)

                //异步请求数据
                axios.post("/logindo",param)
                    .then((response)=>{
                        if(response.data.code == 0){
                            this.$message("提示:"+response.data.message);
                            location.replace("/index", "_self");
                        }else{
                            this.$message("提示:"+response.data.message);
                        }
                    })
                    .catch((error)=>{//错误捕获
                        this.$message("请求错误,请重试");
                    });
            },
        }
    }
    var Ctor = Vue.extend(Main)
    new Ctor().$mount('#app')
</script>

列表页面:

<style>
    @import url("/source/index.css");
    .el-header {
        background-color: #B3C0D1;
        color: #333;
        line-height: 60px;
    }
    .el-aside {
        color: #333;
    }
</style>

<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>

<div id="app">
    <el-container style="height: 500px; border: 1px solid #eee">
        <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
            <el-menu :default-openeds="['1', '3']">
                <el-submenu index="1">
                    <template slot="title"><i class="el-icon-message"></i>导航一</template>
                    <el-menu-item-group>
                        <template slot="title">分组一</template>
                        <el-menu-item index="1-1">选项1</el-menu-item>
                        <el-menu-item index="1-2">选项2</el-menu-item>
                    </el-menu-item-group>
                </el-submenu>
            </el-menu>
        </el-aside>

        <el-container>
            <!--右上角菜单开始-->
            <el-header style="text-align: right; font-size: 12px">
                <el-dropdown>
                    <i class="el-icon-setting" style="margin-right: 15px"></i>
                    <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item>查看</el-dropdown-item>
                        <el-dropdown-item>新增</el-dropdown-item>
                        <el-dropdown-item>删除</el-dropdown-item>
                        <el-dropdown-item></el-dropdown-item>
                    </el-dropdown-menu>
                </el-dropdown>
                <span>王小虎</span>&nbsp;&nbsp;&nbsp;
                <el-button type="primary" @click="login_out()">退出</el-button>
            </el-header>
            <!--右上角菜单结束-->

            <!--主体开始-->
            <el-main>
                <el-row>
                    <el-input v-model="input" placeholder="请输入内容" style="width: 80%"></el-input>
                    <el-button type="primary">搜索</el-button>
                    <el-button type="primary" @click="user_add()">新增</el-button>
                </el-row>

                <el-table :data="tableData">
                    <el-table-column prop="id" label="ID" width="140">
                    </el-table-column>
                    <el-table-column prop="username" label="姓名" width="120">
                    </el-table-column>
                    <el-table-column prop="sex" label="性别">
                    </el-table-column>
                    <el-table-column prop="age" label="年龄">
                    </el-table-column>
                    <el-table-column label="操作">
                        <template slot-scope="scope">
                            <el-button
                                    size="mini"
                                    @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                            <el-button
                                    size="mini"
                                    type="danger"
                                    @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                        </template>
                    </el-table-column>
                </el-table>

                <el-pagination
                        @size-change="handleSizeChange"
                        @current-change="handleCurrentChange"
                        :current-page="currentPage"
                        :page-sizes="[1, 2, 3, 4,5,6,7,8,9,10]"
                        :page-size="pageSize"
                        layout="total, sizes, prev, pager, next, jumper"
                        :total="total">
                </el-pagination>
            </el-main>
            <!--主体结束-->
        </el-container>
    </el-container>
</div>

<script>
    var Main = {
        data() {
            return {
                tableData: [],
                currentPage: 1,
                pageSize: 2,
                total: 0,
                input: '',
            };
        },
        methods: {
            //定义刷新方法
            fetchData(page, size) {
                // 这里的API请求应该替换为实际的API地址和参数
                axios.get('/indexlist', {
                    params: {
                        page: page,
                        size: size
                    }
                }).then(response => {
                    this.tableData = response.data.data.users;
                    this.total = response.data.data.pagination.totalCount;
                }).catch(error => {
                    console.error('Error fetching data: ', error);
                });
            },
            handleSizeChange(val) {
                this.pageSize = val;
                this.fetchData(this.currentPage, this.pageSize);
            },
            handleCurrentChange(val) {
                this.currentPage = val;
                this.fetchData(this.currentPage, this.pageSize);
            },
            handleEdit(index, row) {//编辑
                var id = row.id
                var url = "/user_edit?id="+id;
                location.replace(url, "_self");
            },
            handleDelete(index, row) {//删除
                //异步请求
                axios({
                    method: "post",
                    url: "/user_del",
                    data: {id:row.id},
                    headers: { "Content-Type": "multipart/form-data" },
                }).then((response) => {
                    if(response.data.code ==200){
                        this.$message("提示:"+response.data.msg);
                        //跳转
                        this.fetchData(this.currentPage, this.pageSize);
                    }else{
                        this.$message("提示:"+response.data.msg);
                    }
                });
            },
            //退出
            login_out(){
                this.$message("退出提示");
            },
            //用户新增
            user_add(){
                var url = "/user_add";
                location.replace(url, "_self");

            }
        },
        mounted(){//初始化加载
            this.fetchData(this.currentPage, this.pageSize);
        }
    }
    var Ctor = Vue.extend(Main)
    new Ctor().$mount('#app')
</script>

添加数据:

<style>
    @import url("/source/index.css");
    #content{width: 100%;height: 100%}
</style>

<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>

<div id="app">
    <div id="content">
        <el-form ref="form" :model="form" label-width="80px">
            <el-form-item label="真实名称">
                <el-input v-model="form.username"  autocomplete="off"></el-input>
            </el-form-item>

            <el-form-item label="性别">
                <el-select v-model="form.sex" placeholder="请选择性别">
                    <el-option label="男" value="男"></el-option>
                    <el-option label="女" value="女"></el-option>
                </el-select>
            </el-form-item>

            <el-form-item label="年龄">
                <el-input type="number" v-model="form.age" autocomplete="off"></el-input>
            </el-form-item>

            <el-form-item>
                <el-button type="primary" @click="onSubmit">立即创建</el-button>
                <el-button>取消</el-button>
            </el-form-item>
        </el-form>
    </div>
</div>

<script>
    var Main = {
        data() {
            return {
                form: {
                    username: '',
                    sex: '',
                    age: '',
                }
            }
        },
        methods: {
            onSubmit(form) {
                //必须使用这个数组
                // let param = new URLSearchParams()
                let param = new FormData()
                //填充护数据
                param.append('username',this.form.username)
                param.append('sex',this.form.sex)
                param.append('age',this.form.age)

                //异步请求数据
                axios.post("/user_add_do",param)
                    .then((response)=>{
                        if(response.data.code ==200){
                            this.$message("提示:"+response.data.msg);
                            //跳转
                            setTimeout(function () {
                                var url = "/index";
                                location.replace(url, "_self");
                            },1000);
                        }else{
                            this.$message("提示:"+response.data.msg);
                        }
                    })
                    .catch((error)=>{//错误捕获
                        this.$message("请求错误,请重试");
                    });
            },
        }
    }
    var Ctor = Vue.extend(Main)
    new Ctor().$mount('#app')
</script>

编辑数据:

<style>
    @import url("/source/index.css");
    #content{width: 100%;height: 100%}
    .avatar-uploader .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
    }
    .avatar-uploader .el-upload:hover {
        border-color: #409EFF;
    }
    .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 178px;
        height: 178px;
        line-height: 178px;
        text-align: center;
    }
    .avatar {
        width: 178px;
        height: 178px;
        display: block;
    }
</style>

<script src="/source/vue.js"></script>
<script src="/source/index.js"></script>
<script src="/source/axios.min.js"></script>

<div id="app">
    <div id="content">
        <el-form ref="form" :model="form" label-width="80px">

            <el-form-item label="用户ID">
                <el-input type="number" v-model="form.id" autocomplete="off" disabled></el-input>
            </el-form-item>

            <el-form-item label="真实名称">
                <el-input v-model="form.username"  autocomplete="off"></el-input>
            </el-form-item>

            <el-form-item label="性别">
                <el-select v-model="form.sex" placeholder="请选择性别">
                    <el-option label="男" value="男"></el-option>
                    <el-option label="女" value="女"></el-option>
                </el-select>
            </el-form-item>

            <el-form-item label="年龄">
                <el-input type="number" v-model="form.age" autocomplete="off"></el-input>
            </el-form-item>

            <!--图片上传开始-->
            <el-form-item label="头像" v-model="form.url">
                <el-upload
                        class="avatar-uploader"
                        action="/imgupload"
                        :show-file-list="false"
                        :on-success="handleAvatarSuccess"
                        :before-upload="beforeAvatarUpload">
                    <img v-if="imageUrl" :src="imageUrl" class="avatar">
                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                </el-upload>
            </el-form-item>
            <!--图片上传结束-->

            <el-form-item>
                <el-button type="primary" @click="onSubmit">确认修改</el-button>
            </el-form-item>
        </el-form>
    </div>
</div>

<script>
    var Main = {
        data() {
            return {
                form: {
                    id: '{{.id}}',
                    username: '',
                    sex: '',
                    age: '',
                },
                imageUrl: ''
            }
        },
        methods: {
            fetchData() {
                // 这里的API请求应该替换为实际的API地址和参数
                axios({
                    method: "post",
                    url: "/user_info",
                    data: {id:'{{.id}}'},
                    headers: { "Content-Type": "multipart/form-data" },
                }).then((response) => {
                    if(response.data.code ==200){
                        //数据填充
                        this.form.username = response.data.data.users[0].username;
                        this.form.sex = response.data.data.users[0].sex;
                        this.form.age = response.data.data.users[0].age;
                        this.imageUrl = response.data.data.users[0].url;
                    }else{
                        this.$message("提示:"+response.data.msg);
                    }
                });
            },
            onSubmit(form) {
                //填充数据
                let param = new FormData()
                //填充护数据
                param.append('id',this.form.id)
                param.append('username',this.form.username)
                param.append('sex',this.form.sex)
                param.append('age',this.form.age)
                param.append('url',this.imageUrl)

                //异步请求数据
                axios.post("/user_edit_do",param)
                .then((response)=>{
                    if(response.data.code ==200){
                        this.$message("提示:"+response.data.msg);
                        //跳转
                        setTimeout(function () {
                            var url = "/index";
                            location.replace(url, "_self");
                        },1000);
                    }else{
                        this.$message("提示:"+response.data.msg);
                    }
                })
                .catch((error)=>{//错误捕获
                    this.$message("请求错误,请重试");
                });
            },
            handleAvatarSuccess(res, file) {
                this.imageUrl = file.response.raw.replace("./static","http://127.0.0.1:8080/source")
            },
            beforeAvatarUpload(file) {
                const isJPG = file.type === 'image/jpeg';
                const isLt2M = file.size / 1024 / 1024 < 2;

                if (!isJPG) {
                    this.$message.error('上传头像图片只能是 JPG 格式!');
                }
                if (!isLt2M) {
                    this.$message.error('上传头像图片大小不能超过 2MB!');
                }
                return isJPG && isLt2M;
            },
        },
        mounted(){//初始化加载
            this.fetchData();
        }
    }
    var Ctor = Vue.extend(Main)
    new Ctor().$mount('#app')
</script>

Python(Falsk) + React 项目结构

Python(Flask)框架主入口:

from flask import Flask,Blueprint,json
from flask_cors import CORS
from xst.controller.user_controller import *
from xst.mapper.fileupload import *
import requests
from bs4 import BeautifulSoup

app = Flask(__name__)
#设置跨域
CORS(app)

# 蓝图
admin = Blueprint('admin', __name__)

# 登录操作
@admin.route('/logindo',methods=['POST'])
def logindo():
    # 获取数据(方式一)
    username = request.form['username']
    # 获取数据(方式二)
    # data = request.form.to_dict()
    # username = request.form['username']
    # 数据操作
    logindata = Userlogin(username)
    return json.dumps(logindata)

# 用户列表
@admin.route('/userlist',methods=['POST','GET'])
def userlist():
    list = Userlist()
    return json.dumps(list)

# 用户个数
@admin.route('/usernum',methods=['POST','GET'])
def usernum():
    num = Usercount()
    return json.dumps(num)

# 用户新增
@admin.route("/useradd",methods=["POST"])
def useradd():
    # 接收数据
    username = request.form['username']
    sex = request.form['sex']
    age = request.form['age']
    url = request.form['url']
    # 请求方法
    result = Useradd(username,sex,age,url)
    return json.dumps(result)

# 用户修改
@admin.route("/useredit",methods=["POST"])
def useredit():
    # 请求方法
    return json.dumps(Useredit())


# 文件上传
@admin.route("/fileupload",methods=["POST"])
def fileupload():
    return json.dumps(Fileupload())



# 蓝图注册
app.register_blueprint(admin,url_prefix='/admin')

if __name__ == '__main__':
    app.run()

公共方法:

from flask import Flask
import mysql.connector

# 数据库连接(设置参数)
mydb = mysql.connector.connect(
    host="localhost",
    user="root",
    passwd="root",
    database="test"
)
from flask import request
from werkzeug.utils import secure_filename
import os

# 指定文件上传路径
UPLOAD_PATH = "/upload"
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}


# 数据过滤器
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# 文件上传方法
def Fileupload():

    # 判断文件是否存在
    if 'file' not in request.files:
        data = {
            "code": "300",
            "msg": "修改成功",
            "data": ""
        }
        return data

    # 获取文件
    file = request.files['file']
    if file.filename == '':
        data = {
            "code": "300",
            "msg": "未选择文件",
            "data": ""
        }
    return data

    # 这里可以加入文件类型的判断
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(UPLOAD_PATH, filename))
        data = {
            "code": "200",
            "msg": "上传成功",
            "data": filename
        }
    return data


数据处理:

from xst.mapper.exts import mydb
from flask import request

# 用户登录
def Userlogin(usernum):
    mycursor = mydb.cursor()
    # 获取数据量
    mycursor.execute("SELECT count(users.id) as num FROM users where username = '" + usernum + "'")
    num = mycursor.fetchone()[0]
    # 获取数据
    mycursor.execute("SELECT * FROM users where username = '" + usernum + "'")
    userinfo = mycursor.fetchall()
    # 判断
    if num >0:
        data = {
            "code": "200",
            "msg": "成功",
            "data": userinfo
        }
    else:
        data = {
            "code": "300",
            "msg": "失败",
            "data": ""
        }
    # 返回
    return data

# 数据查询(获取数据量)
def Usercount():
    mycursor = mydb.cursor()
    mycursor.execute("SELECT count(users.id) as num FROM users")
    num = mycursor.fetchone()[0]
    # 数据组合
    data = {
        "code": "200",
        "msg": "成功",
        "data": num
    }
    # 返回
    return data

# 数据查询(全部数据)
def Userlist():
    mycursor = mydb.cursor()
    mycursor.execute("SELECT * FROM users")
    userlist = mycursor.fetchall()
    # 数据组合
    data = {
        "code": "200",
        "msg": "成功",
        "data": userlist
    }
    # 返回
    return data

# 数据查询(新增用户)
def Useradd(username,sex,age,url):
    mycursor = mydb.cursor()
    mycursor.execute("INSERT INTO users (username, sex, age, url) VALUES ('"+username+"', '"+sex+"', "+age+", '"+url+"');")
    mydb.commit()
    new_id = mycursor.lastrowid
    # 判断
    if new_id >0:
        data = {
            "code": "200",
            "msg": "新增成功",
            "data": new_id
        }
    else:
        data = {
            "code": "300",
            "msg": "新增失败",
            "data": ""
        }
    # 返回
    return data

# 数据查询(修改用户)
def Useredit():
    # //接收数据
    id = request.form['id']
    username = request.form['username']
    sex = request.form['sex']
    age = request.form['age']
    url = request.form['url']

    # 数据操作
    mycursor = mydb.cursor()
    mycursor.execute("UPDATE users SET username = '"+username+"', sex = '"+sex+"', age = "+age+", url = '"+url+"' WHERE id = "+id)
    mydb.commit()

    # 判断
    if mycursor.rowcount > 0:
        data = {
            "code": "200",
            "msg": "修改成功",
            "data": ""
        }
    else:
        data = {
            "code": "300",
            "msg": "修改失败",
            "data": ""
        }
    # 返回
    return data

React主入口文件:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import Route from './pages/route';
import reportWebVitals from './reportWebVitals';
// 新增路由组件
import { BrowserRouter } from "react-router-dom"

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <Route />
    </BrowserRouter>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

主文件:

import React from "react";
import { useRoutes } from "react-router-dom"
import Userlist from "./userlist";
import Useradd from "./useradd";
import Useredit from "./useredit";
import Layout from "./layout";


function Route(){
    const routes = useRoutes([
        { path: "/userlist", element: <Userlist /> },
        { path: "/useradd", element: <Useradd /> },
        { path: "/useredit", element: <Useredit /> },
        { path: "/*", element: <Layout /> },
      ]);

      return (
        <div className="container">
          <div className="layout">
            <div style={{ width: '100%' }}>
              {routes}
            </div>
          </div>
        </div>
      );
}

export default Route;

数据列表:

import React from 'react';
import { LikeOutlined, MessageOutlined, StarOutlined } from '@ant-design/icons';
import {List, Space } from 'antd';

function Userlist(){
    // 设置数据
    const data = Array.from({ length: 23 }).map((_, i) => ({
        // 跳转地址
        href: 'https://ant.design',
        title: `序号: ${i}`,
        description:
          '描述',
        content:
          '内容',
      }));
  
    
      //列表渲染
      return (
        <List
            itemLayout="vertical"
            size="large"
            pagination={{
                onChange: page => {
                console.log(page);
                },
                pageSize: 3,
            }}
            dataSource={data}
            renderItem={item => (
                <List.Item
                key={item.title}
                extra={
                    <img
                    width={272}
                    alt="logo"
                    src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png"
                    />
                }
                >
                <List.Item.Meta
                    title={<a href={item.href}>{item.title}</a>}
                    description={item.description}
                />
                {item.content}
                </List.Item>
            )}
        />
      );
}

export default Userlist;

新增数据:

import React from 'react';
// antdesign引入
import { Button, Form, Input,InputNumber  } from 'antd';
import { InboxOutlined } from '@ant-design/icons';
import { message, Upload,Select } from 'antd';
import "./layout.css"

// 方法定义
function Useradd(){
  //常量定义
  const onFinish = (values) => {
    console.log('Success:', values);
  };

  const onFinishFailed = (errorInfo) => {
    console.log('Failed:', errorInfo);
  };

  //上传组件初始化
  const { Dragger } = Upload;
  const props = {
    name: 'file',
    multiple: true,
    action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
    onChange(info) {
      const { status } = info.file;
      if (status !== 'uploading') {
        console.log(info.file, info.fileList);
      }
      if (status === 'done') {
        message.success(`${info.file.name} file uploaded successfully.`);
      } else if (status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
    onDrop(e) {
      console.log('Dropped files', e.dataTransfer.files);
    },
  };

  //定义下拉组件
  const { Option } = Select;

  // 方法定义
  return (
    <Form
      name="basic"
      labelCol={{
        span: 8,
      }}
      wrapperCol={{
        span: 16,
      }}
      initialValues={{
        remember: true,
      }}
      onFinish={onFinish}
      onFinishFailed={onFinishFailed}
      autoComplete="off"
    >
      {/* 用户名 */}
      <Form.Item
        label="用户名"
        name="username"
        rules={[
          {
            required: true,
            message: 'Please input your 用户名!',
          },
        ]}
      >
        <Input />
      </Form.Item>

      {/* 性别 */}
      <Form.Item
        label="性别"
        name="sex"
        rules={[
          {
            required: true,
            message: 'Please input your 性别!',
          },
        ]}
      >
        <Select
          placeholder="选择性别"
          allowClear
        >
            <Option value="男">男</Option>
            <Option value="女">女</Option>
        </Select>
 
      </Form.Item>

        {/* 年龄 */}
      <Form.Item name={['user', 'age']} label="年龄" rules={[{ type: 'number', min: 0, max: 99 }]}>
        <InputNumber />
      </Form.Item>


      {/* 头像 */}
      <Form.Item label="头像"name="url">
        <Dragger {...props} maxCount={1}>
          <p className="ant-upload-drag-icon">
            <InboxOutlined />
          </p>
          <p className="ant-upload-text">点击上传</p>
          <p className="ant-upload-hint">支持单次或批量上传</p>
        </Dragger>
      </Form.Item>


      <Form.Item
        wrapperCol={{
          offset: 8,
          span: 16,
        }}
      >
        <Button type="primary" htmlType="submit">提交</Button>
      </Form.Item>
    </Form>
  );
}

export default Useradd;

编辑数据:

import React from 'react';
// antdesign引入
import { Button, Form, Input,InputNumber  } from 'antd';
import { InboxOutlined } from '@ant-design/icons';
import { message, Upload,Select } from 'antd';
import "./layout.css"
 
// 方法定义
function Useradd(){
  //常量定义
  const onFinish = (values) => {
    console.log('Success:', values);
  };

  const onFinishFailed = (errorInfo) => {
    console.log('Failed:', errorInfo);
  };

  //上传组件初始化
  const { Dragger } = Upload;
  const props = {
    name: 'file',
    multiple: true,
    action: 'http://127.0.0.1:500/fileupload',
    onChange(info) {
      const { status } = info.file;
      if (status !== 'uploading') {
        console.log(info.file, info.fileList);
      }
      if (status === 'done') {
        message.success(`${info.file.name} file uploaded successfully.`);
      } else if (status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
    onDrop(e) {
      console.log('Dropped files', e.dataTransfer.files);
    },
  };

  //定义下拉组件
  const { Option } = Select;

  // 方法定义
  return (
    <Form
      name="basic"
      labelCol={{
        span: 8,
      }}
      wrapperCol={{
        span: 16,
      }}
      initialValues={{
        remember: true,
      }}
      onFinish={onFinish}
      onFinishFailed={onFinishFailed}
      autoComplete="off"
    >
      {/* 用户名 */}
      <Form.Item
        label="用户名"
        name="username"
        rules={[
          {
            required: true,
            message: 'Please input your 用户名!',
          },
        ]}
      >
        <Input />
      </Form.Item>

      {/* 性别 */}
      <Form.Item
        label="性别"
        name="sex"
        rules={[
          {
            required: true,
            message: 'Please input your 性别!',
          },
        ]}
      >
        <Select
          placeholder="选择性别"
          allowClear
        >
            <Option value="男">男</Option>
            <Option value="女">女</Option>
        </Select>
 
      </Form.Item>

        {/* 年龄 */}
      <Form.Item name={['user', 'age']} label="年龄" rules={[{ type: 'number', min: 0, max: 99 }]}>
        <InputNumber />
      </Form.Item>


      {/* 头像 */}
      <Form.Item label="头像"name="url">
        <Dragger {...props} maxCount={1}>
          <p className="ant-upload-drag-icon">
            <InboxOutlined />
          </p>
          <p className="ant-upload-text">点击上传</p>
          <p className="ant-upload-hint">支持单次或批量上传</p>
        </Dragger>
      </Form.Item>


      <Form.Item
        wrapperCol={{
          offset: 8,
          span: 16,
        }}
      >
        <Button type="primary" htmlType="submit">修改</Button>
      </Form.Item>
    </Form>
  );
}

export default Useradd;

公共样式:

 .formbody{width: 40%;height: 25%;background: white;position: absolute;top: 30%;left: 50%;padding: 1.5rem !important;}
 .ant-col-8{flex: 0 0 20% !important}
 #root{padding: 1rem;}

至此讲解完成,主要讲解了登录、数据列表、数据新增、数据编辑,至于会话控制前面小编写的文章里面有,所以大家可以参考一下,还是那句话,脑袋会了手不一定会了,所以多练练习。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QTday04

1.思维导图 2. . #include "widget.h" #include "ui_widget.h" #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), speecher(new QTextToSpeech(this)) //给语音播报者实例化空间{ui->setupUi(th…

ansible搭建+ansible常用模块

ansible搭建 管理机安装ansible,被管理节点必须打开ssh服务 1.管理机安装ansible yum -y install ansible 2.查看版本 ansible --version ansible 2.9.27 3.查找配置文件 find /etc/ -name "*ansible*" /etc/ansible /etc/ansible/ansible.cfg 4.三台被管理机…

轻松捕捉屏幕精彩,2024年录屏神器大盘点

随着技术的不断进步和用户需求的日益多样化&#xff0c;市场上的录屏软件更是层出不穷&#xff0c;各有千秋。今天&#xff0c;就让我们一同盘点那些和win10录屏快捷键一样可以快捷控制的专业录屏软件&#xff0c;探索它们如何助力我们更加高效地捕捉屏幕上的每一个精彩瞬间。 …

数据结构-链表-第二天

结合leetcode学习c 链表比数组更易增加和删除数据&#xff0c;但访问速度更慢 定义 链表&#xff08;linked list&#xff09;是一种线性数据结构&#xff0c;其中的每个元素都是一个节点对象&#xff0c;各个节点通过“引用”相连接。 引用记录了下一个节点的内存地址&#…

「字符串」前缀函数|KMP匹配:规范化next数组 / LeetCode 28(C++)

概述 为什么大家总觉得KMP难&#xff1f;难的根本就不是这个算法本身。 在互联网上你可以见到八十种KMP算法的next数组定义和模式串回滚策略&#xff0c;把一切都懂得特别混乱。很多时候初学者的难点根本不在于这个算法本身&#xff0c;而是它令人痛苦的百花齐放的定义。 有…

[C++] map、set的 红黑树 封装(一)

标题&#xff1a;[C] map、set的 红黑树 封装 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、红黑树与AVL树的比较&#xff08;为什么容器选择红黑树&#xff09; 二、map、set的封装 1.模板参数 2.红黑树迭代器设计 正文开始&#xff1a; 一、红黑树与AV…

RK3588J正式发布Ubuntu桌面系统,丝滑又便捷!

本文主要介绍瑞芯微RK3588J的Ubuntu系统桌面演示&#xff0c;开发环境如下&#xff1a; U-Boot&#xff1a;U-Boot-2017.09 Kernel&#xff1a;Linux-5.10.160 Ubuntu&#xff1a;Ubuntu20.04.6 LinuxSDK&#xff1a; rk3588-linux5.10-sdk-[版本号] &#xff08;基于rk3…

【GH】【EXCEL】P7: Control

XL Label XL Dropdown XL CHECK BOX XL Button XL Scroller XL Spinner XL ListBox

RocketMQ源码分析 - 环境搭建

RocketMQ源码分析 - 环境搭建 环境搭建源码拉取导入IDEA调试1) 启动NameServer2) 启动Broker3) 发送消息4) 消费消息 环境搭建 依赖工具 JDK&#xff1a;1.8MavenIntellij IDEA 源码拉取 从官方仓库 https://github.com/apache/rocketmq clone或者download源码。 源码目录…

【微服务】微服务组件之Nacos注册中心和配置中心的使用

背景&#xff1a; 在当前的软件架构领域&#xff0c;微服务架构凭借其高度的可扩展性、灵活性和可维护性&#xff0c;已成为企业构建复杂应用的首选。微服务架构通过将应用拆分成一系列小的、独立的服务&#xff0c;实现了服务的解耦和复用&#xff0c;从而提高了应用的可扩展性…

Sass实现网页背景主题切换

Sass 实现网页背景主题切换 前言准备工作一、 简单的两种主题黑白切换1.定义主题2. 添加主题切换功能3. 修改 data-theme 属性 二、多种主题切换1. 定义主题2. 动态生成 CSS 变量1.遍历列表2.遍历映射3.高级用法 3. 设置默认主题4. 切换功能HTML 三、多种主题多种样式切换1. 定…

在 Fedora 上安装 LAMP(Linux、Apache、MySQL、PHP)的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 关于 LAMP LAMP 栈是一组用于启动和运行 Web 服务器的开源软件。该缩写代表 Linux、Apache、MySQL 和 PHP。由于服务器已经在运行 Fedo…

高性能web服务器1

基础 Web 服务简介 Web 服务是互联网的核心组成部分之一&#xff0c;它允许用户通过浏览器访问信息和应用程序。一个基础的 Web 服务通常由 Web 服务器软件、静态网页内容、以及可选的动态内容生成程序组成。 Web 服务器软件 Web 服务器软件是运行在服务器上的程序&#xff…

【Java 数据结构】PriorityQueue介绍

优先级队列 回顾二叉树堆堆是什么堆的实现初始化堆的创建向下调整建堆复杂度插入向上调整建堆复杂度删除 PriorityQueue类介绍PriorityQueue是什么PriorityQueue使用构造方法常用方法 PriorityQueue源码介绍Top-K问题 回顾二叉树 上一次我们简单的了解了二叉树这个数据结构, 但…

每天五分钟深度学习框架pytorch:神经网络工具箱nn的介绍

本文重点 我们前面一章学习了自动求导,这很有用,但是在实际使用中我们基本不会使用,因为这个技术过于底层,我们接下来将学习pytorch中的nn模块,它是构建于autograd之上的神经网络模块,也就是说我们使用pytorch封装好的神经网络层,它自动会具有求导的功能,也就是说这部…

夏晖WMS是什么?夏晖WMS怎么与金蝶云星空进行集成?

在数字化浪潮席卷全球的今天&#xff0c;企业对于业务流程的高效管理和数据集成的需求愈发迫切。夏晖WMS作为一款领先的仓库管理系统&#xff0c;与金蝶云星空ERP的集成成为了众多企业提升管理效率的关键环节。 夏晖WMS是什么? 夏晖WMS是一款由夏晖物流&#xff08;上海&…

Golang | Leetcode Golang题解之第355题设计推特

题目&#xff1a; 题解&#xff1a; type Twitter struct {Tweets []intUserTweets map[int][]intFollows map[int][]intIsFollowMy map[int]bool }/** Initialize your data structure here. */ func Constructor() Twitter {// 每一次实例化的时候&#xff0c;都重新分配一次…

C语言 | Leetcode C语言题解之第354题俄罗斯套娃信封问题

题目&#xff1a; 题解&#xff1a; int cmp(int** a, int** b) {return (*a)[0] (*b)[0] ? (*b)[1] - (*a)[1] : (*a)[0] - (*b)[0]; }int maxEnvelopes(int** envelopes, int envelopesSize, int* envelopesColSize) {if (envelopesSize 0) {return 0;}qsort(envelopes, …

宜佰丰超市进销存管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; JavaMysql 工具&#xff1a; IDEA/Eclipse、Navicat、Maven 系统展示 首页 管理员功能模块…

接口测试及常用接口测试工具(postman/jmeter)详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#x…