08. Springboot3+vue3实现登录注册功能 – 朝汐の小站
08. Springboot3+vue3实现登录注册功能
本文最后更新于 289 天前,如有错误请邮件至 zhiligyi222na@gmail.com

登陆

页面 Login.vue

<template>
  <div class="bg">
    <div style="width: 350px; background-color: #fff; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); padding:40px 20px">
      <el-form ref="formRef" :model="data.form" :rules="data.rules">
        <div style="margin-bottom: 40px; text-align: center; font-weight: bold; font-size: 24px;">欢 迎 登 录</div>
        <el-form-item prop="username">
          <el-input size="large" v-model="data.form.username" autocomplete="off" prefix-icon="User" placeholder="请输入账号"/>
        </el-form-item>
        <el-form-item prop="password">
          <el-input size="large" show-password v-model="data.form.password" autocomplete="off" prefix-icon="Lock" placeholder="请输入密码"/>
        </el-form-item>
        <el-form-item prop="role">
          <el-select size="large" style="width: 100%" v-model="data.form.role" placeholder="placeholder">
            <el-option label="管理员" value="ADMIN"></el-option>
            <el-option label="普通用户" value="USER"></el-option>
          </el-select>
        </el-form-item>
        <div>
          <el-button style="width: 100%" size="large" type="primary" @click="login">登 录</el-button>
        </div>
        <div style="text-align: right; margin-top: 20px">
          还没有账号?<a style="color: #409eff;" href="/register">立即注册</a>
        </div>
      </el-form>
    </div>
  </div>
</template>

<script setup>
import { reactive, ref } from "vue";
import {ElMessage} from "element-plus";
import request from "@/utils/request.js";
import router from "@/router";


const formRef = ref(null)
const data = reactive({
  form: { role: "ADMIN" },
  rules: {
    username: [
      { required: true, message: '请输入账号', trigger: 'blur' },
      { min: 3, message: '账号最少3位', trigger: 'blur' }
    ],
    password: [
      { required: true, message: '请输入密码', trigger: 'blur' }
    ]
  }
})

const login = () => {
  formRef.value.validate((valid) => {
    // 验证通过
  if (valid) {
    request.post("/login", data.form).then(res => {
      if (res.code === '200'){
        // 存储用户信息
        localStorage.setItem("code_user",JSON.stringify(res.data || {}))
        ElMessage.success('登录成功')
        router.push('/')
      } else {
        ElMessage.error(res.msg)
      }
    })
  } else {
    // 验证失败
    ElMessage.error('请填写完整信息')
  }
  })
}
</script>

<style scoped>
.bg{
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow:  hidden;
  background-image: url("../assets/imgs/bg.png");
  background-size: cover;
}
</style>

存储用户信息

登录接口

controller

@PostMapping("/login")
    public Result login(@RequestBody Account account) {
        Account dbaccount = null;
        if ("ADMIN".equals(account.getRole())) {
            dbaccount = adminService.login(account);
        } else if ("USER".equals(account.getRole())) {
            dbaccount = userService.login(account);
        }else {
            throw new CustomerException("非法请求");
        }
        return Result.success(dbaccount);
    }

AdminService

    public Admin login(Account account) {
        //验证账号是否存在
        Admin dbAdmin = adminMapper.selectByUsername(account.getUsername());
        if (dbAdmin == null) {
            throw new CustomerException("账号不存在");
        }
        //验证密码是否正确
        if (!dbAdmin.getPassword().equals(account.getPassword())) {
            throw new CustomerException("账号或密码错误");
        }
        return dbAdmin;
    }

UserService

public User login(Account account) {
        //验证账号是否存在
        User dbUser = userMapper.selectByUsername(account.getUsername());
        if (dbUser == null) {
            throw new CustomerException("账号不存在");
        }
        //验证密码是否正确
        if (!dbUser.getPassword().equals(account.getPassword())) {
            throw new CustomerException("账号或密码错误");
        }
        return dbUser;
    }

模仿管理员开发用户管理

数据库表user

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `username` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '账号',
  `password` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码',
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '名称',
  `phone` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机号',
  `email` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '邮箱',
  `role` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '角色',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username_index` (`username`) USING BTREE COMMENT '账号'
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='管理员信息';

user 相关的接口和管理界面

UserService的add方法

    public void add(User user) {
        // 根据新的账号查询数据库 是否存在同样的账号数据
        User dbUser = userMapper.selectByUsername(user.getUsername());
        if (dbUser != null) {
            throw new CustomerException("账号重复");
        }
        //默认密码为123
        if (StrUtil.isBlank(user.getPassword())){
            user.setPassword("123");
        }
        if (StrUtil.isBlank(user.getName())){
            user.setName(user.getUsername());
        }
        user.setRole("USER");
        userMapper.insert(user);
    }

AdminService的add方法

    public void add(Admin admin) {
        // 根据新的账号查询数据库 是否存在同样的账号数据
        Admin dbAdmin = adminMapper.selectByUsername(admin.getUsername());
        if (dbAdmin != null) {
            throw new CustomerException("账号重复");
        }
        //默认密码为admin
        if (StrUtil.isBlank(admin.getPassword())){
            admin.setPassword("admin");
        }
        admin.setRole("ADMIN");
        adminMapper.insert(admin);
    }

注意在 AdminMapper.xml 和 UserMapper.xml 里面补充 role

遇到 “未找到接口” 的问题

这是因为没有重启后台

注册

页面 Register.vue

<template>
  <div class="bg">
    <div style="width: 350px; background-color: #fff; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); padding:40px 20px">
      <el-form status-icon ref="formRef" :model="data.form" :rules="data.rules">
        <div style="margin-bottom: 40px; text-align: center; font-weight: bold; font-size: 24px;">欢 迎 注 册</div>
        <el-form-item prop="username">
          <el-input size="large" v-model="data.form.username" autocomplete="off" prefix-icon="User" placeholder="请输入账号"/>
        </el-form-item>
        <el-form-item prop="password">
          <el-input size="large" show-password v-model="data.form.password" autocomplete="off" prefix-icon="Lock" placeholder="请输入密码"/>
        </el-form-item>
        <el-form-item prop="confirmPassword">
          <el-input size="large" show-password v-model="data.form.confirmPassword" autocomplete="off" prefix-icon="Lock" placeholder="请确认密码"/>
        </el-form-item>
        <div>
          <el-button style="width: 100%; background-color: #248243; border-color: #248243" size="large" type="primary" @click="register">注 册</el-button>
        </div>
        <div style="text-align: right; margin-top: 20px">
          已有账号?<a style="color: #248243;" href="/login">立即登录</a>
        </div>
      </el-form>
    </div>
  </div>
</template>

<script setup>
import { reactive, ref } from "vue";
import {ElMessage} from "element-plus";
import request from "@/utils/request.js";
import router from "@/router";

const validatePass = (rule, value, callback) => {
  // value表示用户输入的确认密码
  if (value !== data.form.password) {
    callback(new Error('两次输入的密码不一致!'))
  } else {
    callback()
  }
}

const formRef = ref(null)
const data = reactive({
  form: {},
  rules: {
    username: [
      { required: true, message: '请输入账号', trigger: 'blur' },
      { min: 3, message: '账号最少3位', trigger: 'blur' }
    ],
    password: [
      { required: true, message: '请输入密码', trigger: 'blur' }
    ],
    confirmPassword: [
      { required: true, message: '请确认密码', trigger: 'blur' },
      { validator: validatePass, trigger: 'blur' }
    ]
  }
})

const register = () => {
  formRef.value.validate((valid) => {
    // 验证通过
    if (valid) {
      request.post("/register", data.form).then(res => {
        if (res.code === '200'){
          ElMessage.success('注册成功')
          router.push('/login')
        } else {
          ElMessage.error(res.msg)
        }
      })
    }
  })
}
</script>

<style scoped>
.bg{
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow:  hidden;
  background-image: url("../assets/imgs/bg1.png");
  background-size: cover;
}
</style>

按钮颜色 #248243

注册接口

controller

    @PostMapping("/register")
    public Result register(@RequestBody User user) {
        userService.register(user);
        return Result.success();
    }

service

public void register(User user) {
        this.add(user);
    }

自定义的错误

不是系统的错误,不是代码的bug,这是给前端抛出的错误信息

其余代码样例

<template>
  <div>
    <!--头部区域开始-->
    <div style="height: 60px; display: flex;">
      <div style="width: 240px; display: flex; align-items: center; padding-left: 20px; background-color: #3a456b">
        <img style="width: 40px; height: 40px; border-radius: 50%;" src="@/assets/imgs/logo.png" alt="">
        <span style="font-size: 20px; font-weight: bold; color: #f1f1f1; margin-left: 5px;">后台管理系统</span>
      </div>
      <div style="flex: 1; display: flex; align-items: center;padding-left: 20px; border-bottom: 1px solid #ddd">
        <span style="margin-right: 5px; cursor: pointer" @click="router.push('/manager/home')">首页</span> / <span style="margin-left: 5px">{{ router.currentRoute.value.meta.name }}</span>
      </div>
      <div style="width: fit-content; padding-right: 20px; display: flex; align-items: center; border-bottom: 1px solid #ddd">
        <el-dropdown>
          <div style=" display: flex; align-items: center;">
            <img style="width: 40px; height: 40px ;border-radius: 50%" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" alt="">
            <span style="margin-left: 5px">{{ data.user?.name }}</span>
          </div>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item>个人中心</el-dropdown-item>
              <el-dropdown-item>修改密码</el-dropdown-item>
              <el-dropdown-item @click="logout">退出登录</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>
    <!--头部区域结束-->

    <!--内容区域开始-->
    <div style="display: flex ;">
      <!--菜单区域开始-->
      <div style="width: 240px;">
        <el-menu router :default-openeds="['1']" :default-active="router.currentRoute.value.path" style=" min-height: calc(100vh - 60px)">
          <el-menu-item index="/manager/home">
            <el-icon><House /></el-icon>
            <span>首页</span>
          </el-menu-item>
          <el-sub-menu index="1">
            <template #title>
              <el-icon><Location /></el-icon>
              <span>用户管理</span>
            </template>
            <el-menu-item index="/manager/admin">管理员信息</el-menu-item>
            <el-menu-item index="/manager/user">普通用户信息</el-menu-item>
          </el-sub-menu>
        </el-menu>
      </div>
      <!--菜单区域结束-->

      <!--数据渲染区域开始-->
      <div style="flex: 1; width: 0; padding: 10px; background-color: #f2f4ff">
        <router-view />
      </div>
      <!--数据渲染区域结束-->
    </div>
    <!--内容区域结束-->
  </div>
</template>

<script setup>

import router from "@/router/index.js";
import { reactive } from "vue";

const data = reactive({
  user: JSON.parse(localStorage.getItem("code_user") || "{}")
})

const logout = () => {
  localStorage.removeItem("code_user")
  location.href = '/login'
}

if (!data.user?.id) {
  location.href = '/login'
}
</script>


<style>
.el-menu {
  background-color: #3a456b;
  border: none;
}
.el-sub-menu__title{
  color: #ddd;
  background-color: #3a456b;
}
.el-menu-item{
  height: 50px;
  color: #ddd;
}
.el-menu .is-active{
  background-color: #537bee;
  color: #fff;
}
.el-sub-menu__title:hover{
  background-color: #3a456b;
}
.el-menu-item:not(.is-active):hover{
  background-color: #7a9fff;
  color: #333;
}
.el-dropdown{
  cursor:  pointer;
}
.el-tooltip__trigger{
  outline: none;
}
.el-menu--inline .el-menu-item{
  padding-left: 50px !important
}
</style>
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇