2023-01-10 13:51

Vue3+element-plus+Springboot实现的前后端分离登陆注册

wanmatea

项目

(2338)

(0)

收藏

一、环境

vue3.0

element-plus

axios

vue-router

spring-boot

mybatis-plus

二、开发工具

前端 VSCode

后端 IDEA

三、前端框架

项目结构如下:

image.png

然后我们看一下核心的代码

入口文件main.js

import { createApp } from 'vue'
import App from './App.vue'
import Router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app=createApp(App)
app.use(Router)
app.use(ElementPlus)
app.mount('#app')

axios封装 request.js

import axios from 'axios'
const request = axios.create({
    // baseURL: '/api',  // 注意!! 这里是全局统一加上了 '/api' 前缀,也就是说所有接口都会加上'/api'前缀在,页面里面写接口的时候就不要加 '/api'了,否则会出现2个'/api',类似 '/api/api/user'这样的报错,切记!!!
    timeout: 5000
})
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8';
    // config.headers['token'] = user.token;  // 设置请求头
    return config
}, error => {
    return Promise.reject(error)
});
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
    response => {
        let res = response.data;
        // 如果是返回的文件
        if (response.config.responseType === 'blob') {
            return res
        }
        // 兼容服务端返回的字符串数据
        if (typeof res === 'string') {
            res = res ? JSON.parse(res) : res
        }
        return res;
    },
    error => {
        console.log('err' + error) // for debug
        return Promise.reject(error)
    }
)
export default request

路由router/inde.js

import {createRouter,createWebHistory} from "vue-router"
import LoginView from '@/components/LoginView'
import IndexView from '@/components/IndexView'
const routes=[
    {
        path:'/',
        name:"LoginView",
        component:LoginView
    },
    {
        path:'/index',
        name:"IndexView",
        component:IndexView
    }
]
export const router=createRouter({
    history:createWebHistory(),
    routes:routes
})
export default router

登陆注册组件LoginView.vue

<template>
  <el-tabs v-model="activeName" type="border-card" class="demo-tabs" @tab-click="handleClick">
    <el-tab-pane label="登录" name="login">
        <el-form :model="form" ref="ruleForms" :rules="rules" label-width="70px">
            <el-form-item label="用户名" prop="username">
                <el-input placeholder="请输入5-15位大小写字母数字或者下划线" style = "width: 80%" v-model="form.username"></el-input>
            </el-form-item>  
            <el-form-item label="密码" prop="password">
                <el-input placeholder="请输入5-20位密码" style = "width: 80%" v-model="form.password"></el-input>
            </el-form-item>   
            <el-form-item>
                <el-button type="primary" @click="onLogin">提交</el-button>
                <el-button @click="cannel">取消</el-button>
            </el-form-item>
        </el-form>
    </el-tab-pane>
    <el-tab-pane label="注册" name="register">
        <el-form :model="form" label-width="80px">
        <el-form-item label="用户名">
            <el-input style = "width: 80%" v-model="form.username"></el-input>
        </el-form-item>  
        <el-form-item label="密码">
            <el-input style = "width: 80%" v-model="form.password"></el-input>
        </el-form-item> 
         <el-form-item label="确认密码">
            <el-input style = "width: 80%" v-model="form.password2"></el-input>
        </el-form-item>  
        <el-form-item>
            <el-button type="primary" @click="onRegister">提交</el-button>
            <el-button>取消</el-button>
        </el-form-item>
     </el-form>
    </el-tab-pane>
  </el-tabs>
     
</template>
<script>
  import {reactive,toRefs,ref} from "vue";
    import request from "@/utils/request";
    import { ElMessage } from 'element-plus';
    import {useRouter} from 'vue-router';
    export default{
        setup() {
            const router=useRouter()
            const activeName = ref('login')
            //使用ref定义dom对象
            const ruleForms = ref();
            const state=reactive({
                form:{}
            });
            const rules= reactive({
                username:[
                    {
                        required:true,
                        message:"请输入您的用户名",
                        trigger:"blur"
                    },
                    {
                        pattern:"^\\w{5,15}$",
                        message:"请输入5-15位大小写字母数字或者下划线",
                        trigger:"blur"
                    }
                ],
                password:[
                    {
                        required:true,
                        message:"请输入您的密码",
                        trigger:"blur"
                    },
                    {
                        pattern:"^.{5,20}$",
                        message:"请输入5-20位的密码",
                        trigger:"blur"    
                    }
                ]
            })
            function onLogin(){
                console.log(ruleForms.value);
                //通过ref的值触发验证
                ruleForms.value.validate((valid) => {
                    if (valid) {
                        console.log("通过");
                        request.post("/api/user/login",state.form).then((res)=>{
                            console.log(res);
                            if(res.code==='0'){
                                ElMessage.success("登录成功");
                                router.push({path: '/index'});
                            }
                            else {
                                ElMessage.error(res.msg);
                            }
                        })
                    } else {
                        console.log("未通过");
                    }
                });
            }
            function onRegister(){
                console.log(state.form);
                request.post("/api/user/register",state.form).then((res)=>{
                    console.log(res);
                    if(res.code==='0'){
                        ElMessage.success("注册成功");
                        router.push({path: '/'});
                    }
                    else {
                        ElMessage.error(res.msg);
                    }
                })
            }
            function handleClick(){
                state.form={};
            }
            function cannel(){
                state.form={};
            }
            return{
                ...toRefs(state),
                onLogin,
                cannel,
                onRegister,
                handleClick,
                activeName,
                rules,
                ruleForms
            }
        }
    }
</script>

四、后端框架

项目结构如下:

image.png

核心代码:

Result类

package com.example.springboot.config;
import lombok.Data;
@Data
public class Result<T> {
    private String code;  //状态码
    private String msg; //返回信息
    private T data;     //返 回数据
    public Result(T data){
        this.data=data;
    }
    public Result() {
    }
    //    返回成功的信息
    public static Result success(){
        Result result=new Result<>();
        result.setCode("0");
        result.setMsg("成功");
        return result;
    }
    public static <T> Result<T> success(T data){  //当作是固定用法吧
        Result<T> result =new Result<>(data);
        result.setCode("0");
        result.setMsg("成功");
        return result;
    }
    //    返回失败的信息
    public static Result error(String code, String msg){
        Result result=new Result<>();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
}

User类

package com.example.springboot.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@TableName("user")
@Data
public class User {
    @TableId(type = IdType.AUTO)
    private  Integer id;
    private  String username;
    private  String password;
    private  String nickName;
    private  Integer age;
    private  String sex;
    private  String address;
}

UserMapper类

package com.example.springboot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springboot.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

控制器类UserController类

package com.example.springboot.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springboot.config.Result;
import com.example.springboot.entity.User;
import com.example.springboot.mapper.UserMapper;
import com.example.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
//@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;
    @DeleteMapping("/{id}")
    public Result<?> delete(@PathVariable int id){
        userMapper.deleteById(id);
        return Result.success();
    }
    @PostMapping
    public Result<?> save(@RequestBody User user){
        if(user.getPassword() == null){
            user.setPassword("123456");
        }
        userMapper.insert(user);
       return Result.success();
    }
    //表单更新
    @PutMapping
    public Result<?> update(@RequestBody User user){
        userMapper.updateById(user);
        return Result.success();
    }
    @GetMapping
    public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize,@RequestParam(defaultValue = "") String search){
        Page page = new Page(pageNum, pageSize);
        LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery();
        if (StrUtil.isNotBlank(search)){
            wrapper.like(User::getNickName, search);
        }
        Page<User> userPage = userMapper.selectPage(page,wrapper);
        return Result.success(userPage);
    }
}

五、前台界面

image.pngimage.png

0条评论

点击登录参与评论