本文最后更新于 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>








