新增Person(个人页面),Password(修改密码页面),还需要对Manager,login页面进行修改

router文件夹下的index.js:
- import Vue from 'vue'
- import VueRouter from 'vue-router'
- import Manager from '../views/Manager.vue'
- // 解决导航栏或者底部导航tabBar中的vue-router在3.0版本以上频繁点击菜单报错的问题。
- const originalPush = VueRouter.prototype.push
- VueRouter.prototype.push = function push (location) {
- return originalPush.call(this, location).catch(err => err)
- }
- Vue.use(VueRouter)
-
- const routes = [
- {
- path: '/',
- name: 'manager',
- component: Manager,
- children:[
- {path:'home',name:'Home',meta:{ name:'系统首页' },component:()=>import('../views/manager/Home.vue')},
- {
- path:'user',name:'User',meta:{ name:'用户信息' },component:()=>import('../views/manager/User.vue')
- },
- {
- path:'403',name:'Auth',meta:{ name:'无权限' },component:()=>import('../views/Auth.vue')
- },
- {
- path:'Person',name:'person',meta:{ name:'个人信息' },component:()=>import('../views/manager/Person.vue')
- },
- {
- path:'Password',name:'password',meta:{ name:'修改密码' },component:()=>import('../views/manager/Password.vue')
- }
- ],
- redirect:'/home'
- },
- {
- path: '/about',
- name: 'about',
- // route level code-splitting
- // this generates a separate chunk (about.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
- },
- {
- path:'/login',
- name:'login',
- meta:{ name:'登录' },
- component: ()=>import('../views/login.vue')
- },
- {
- path:'/register',
- name:'register',
- meta:{ name:'注册' },
- component: ()=>import('../views/register.vue')
- },
- {
- path:'*',
- name:'404',
- meta:{ name:'无法访问' },
- component: ()=>import('../views/404.vue')
- }
- ]
-
- const router = new VueRouter({
- mode: 'history',
- base: process.env.BASE_URL,
- routes
- })
- router.beforeEach((to,from,next)=>{
- let adminPaths=['/user']
- let user=JSON.parse(localStorage.getItem('honey-user')||'{}')
- if(user.role !== '管理员' && adminPaths.includes(to.path)){
- next('/403')
- }else{
- next()
- }
- })
- export default router
Person.vue
- <template>
- <div>
- <el-card style="width: 50%">
- <el-form :model="user" label-width="80px" style="padding-right: 20px">
- <div style="margin: 15px;text-align: center">
- <el-upload
- class="avatar-uploader"
- action="http://localhost:9090/file/upload"
- :headers="{ token: user.token }"
- :show-file-list="false"
- :on-success="handleAvatarSuccess">
- <img v-if="user.avatar" :src="user.avatar" class="avatar">
- <i v-else class="el-icon-plus avatar-uploader-icon"></i>
- </el-upload>
- </div>
- <el-form-item label="用户名" prop="username">
- <el-input v-model="user.username" disabled></el-input>
- </el-form-item>
- <el-form-item label="姓名" prop="name">
- <el-input v-model="user.name"></el-input>
- </el-form-item>
- <el-form-item label="电话" prop="phone">
- <el-input v-model="user.phone"></el-input>
- </el-form-item>
- <el-form-item label="邮箱" prop="email">
- <el-input v-model="user.email"></el-input>
- </el-form-item>
- <el-form-item label="地址" prop="address">
- <el-input type="textarea" v-model="user.address"></el-input>
- </el-form-item>
- </el-form>
- <div style="text-align: center;margin-bottom: 20px"><el-button type="primary" @click="update">保存</el-button></div>
- </el-card>
- </div>
- </template>
-
- <script>
- export default {
- data(){
- return{
- user:JSON.parse(localStorage.getItem('honey-user'||'{}'))
- }
- },
- methods:{
- update(){
- this.$request.put('/user/update',this.user).then(res=>{
- if(res.code==='200'){
- this.$message.success('保存成功')
- localStorage.setItem('honey-user',JSON.stringify(this.user))
- this.$emit('update:user',this.user)
- }else{
- this.$message.error(res.msg)
- }
- })
- },
- handleAvatarSuccess(response,file,fileList){
- console.log(response)
- this.user.avatar=response.data
- }
- }
- }
- </script>
-
- <style scoped>
- /deep/.el-form-item__label{
- font-weight: bold;
- }
- /deep/.el-upload{
- border-radius: 50%;
- }
- /deep/.avatar-uploader .el-upload {
- border: 1px dashed #d9d9d9;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- border-radius: 50%;
- }
- /deep/.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;
- border-radius: 50%;
- }
- .avatar {
- width: 178px;
- height: 178px;
- display: block;
- border-radius: 50%;
- }
- </style>
Password.vue:
- <template>
- <div>
- <el-card style="width: 50%">
- <el-form ref="fromRef" :model="user" label-width="80px" style="padding-right: 20px" :rules="rules">
- <el-form-item label="原始密码" prop="password">
- <el-input v-model="user.password" show-password></el-input>
- </el-form-item>
- <el-form-item label="新密码" prop="newPassword">
- <el-input v-model="user.newPassword"></el-input>
- </el-form-item>
- <el-form-item label="确认密码" prop="confirmPassword">
- <el-input v-model="user.confirmPassword"></el-input>
- </el-form-item>
- <div style="text-align: center;margin-bottom: 20px"><el-button type="primary" @click="update">确认修改</el-button></div>
- </el-form>
- </el-card>
- </div>
- </template>
-
- <script>
- export default {
- data(){
- const validatePassword = (rule, value, callback) => {
- if (value === '') {
- callback(new Error('请输入确认密码'));
- } else if(value !== this.user.newPassword){
- callback(new Error('两次密码不一致'));
- } else {
- callback();
- }
- };
- return{
- user:JSON.parse(localStorage.getItem('honey-user'||'{}')),
- rules:{
- password:[{
- required:true,
- message:'请输入原始密码',
- trigger:'blur'
- }],
- newPassword:[{
- required:true,
- message:'请输入新密码',
- trigger:'blur'
- }],
- confirmPassword:[{
- validator:validatePassword,
- required:true,
- trigger:'blur',
- }]
- }
- }
- },
- methods:{
- update(){
- this.$refs.fromRef.validate((valid)=>{
- if(valid){
- this.user.password=this.user.newPassword
- this.$request.put('/user/update',this.user).then(res=>{
- if(res.code==='200'){
- this.$message.success('保存成功')
- this.$router.push('/login')
- }else{
- this.$message.error(res.msg)
- }
- })
- }
- })
- },
- }
- }
- </script>
-
- <style scoped>
- /deep/.el-form-item__label{
- font-weight: bold;
- }
- </style>
Manager.vue:
- <template>
- <div>
- <el-container>
- <!-- 侧边栏 -->
- <el-aside :width="asideWidth" style="min-height: 100vh; background-color: #001529">
- <div style="height: 60px; color: white; display: flex; align-items: center; justify-content: center">
- <img src="@/assets/logo1.png" alt="" style="width: 40px; height: 40px">
- <span class="logo-title" v-show="!isCollapse">honey2024</span>
- </div>
-
- <el-menu :collapse="isCollapse" :collapse-transition="false" router background-color="#001529" text-color="rgba(255, 255, 255, 0.65)" active-text-color="#fff" style="border: none" :default-active="$route.path">
- <el-menu-item index="/home">
- <i class="el-icon-s-home"></i>
- <span slot="title">系统首页</span>
- </el-menu-item>
- <el-submenu index="info" v-if="user.role === '管理员'">
- <template slot="title">
- <i class="el-icon-menu"></i>
- <span>信息管理</span>
- </template>
- <el-menu-item index="/user">用户信息</el-menu-item>
- </el-submenu>
- </el-menu>
-
- </el-aside>
-
- <el-container>
- <!-- 头部区域-->
- <el-header>
-
- <i :class="collapseIcon" style="font-size: 26px" @click="handleCollapse"></i>
- <el-breadcrumb separator-class="el-icon-arrow-right" style="margin-left: 20px">
- <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
- <el-breadcrumb-item :to="{ path: $route.path }">{{ $route.meta.name }}</el-breadcrumb-item>
- </el-breadcrumb>
-
- <div style="flex: 1; width: 0; display: flex; align-items: center; justify-content: flex-end">
- <i class="el-icon-quanping" style="font-size: 26px" @click="handleFull"></i>
- <el-dropdown placement="bottom">
- <div style="display: flex; align-items: center; cursor: default">
- <img :src="user.avatar||'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'" alt="" style="width: 40px; height: 40px; margin: 0 5px;border-radius: 50%">
- <span>{{user.name}}</span>
- </div>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item @click.native="$router.push('/person')">个人信息</el-dropdown-item>
- <el-dropdown-item @click.native="$router.push('/password')">修改密码</el-dropdown-item>
- <el-dropdown-item @click.native="logout">退出登录</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </div>
-
- </el-header>
-
- <!-- 主体区域-->
- <el-main>
- <router-view @update:user="updateUser"></router-view>
- </el-main>
-
- </el-container>
-
-
- </el-container>
- </div>
- </template>
-
- <script>
- import axios from "axios";
- import request from '@/utils/request'
-
- export default {
- name: 'HomeView',
- data() {
- return {
- isCollapse: false, // 不收缩
- asideWidth: '200px',
- collapseIcon: 'el-icon-s-fold',
- user:JSON.parse(localStorage.getItem('honey-user')||'{}'),
- }
- },
- mounted() {
- // axios.get('http://localhost:9090/user/selectall').then(res=>{
- // console.log(res.data);
- // this.users=res.data.data
- // })
-
- // request.get('/user/selectall').then(res => {
- // this.users = res.data
- // })
- },
- methods: {
- updateUser(user){
- this.user=JSON.parse(JSON.stringify(user))
- },
- handleFileUpload(response,file,fileList){
- this.fileList=fileList
- console.log(response,file,fileList)
- },
- logout() {
- localStorage.removeItem("honey-user")
- this.$router.push('/login')
- },
- handleFull() {
- document.documentElement.requestFullscreen()
- },
- handleCollapse() {
- this.isCollapse = !this.isCollapse
- this.asideWidth = this.isCollapse ? '64px' : '200px'
- this.collapseIcon = this.isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'
- }
- }
- }
- </script>
-
- <style>
- .el-menu--inline {
- background-color: #000c17 !important;
- }
-
- .el-menu--inline .el-menu-item {
- background-color: #000c17 !important;
- padding-left: 49px !important;
- }
-
- .el-menu-item:hover, .el-submenu__title:hover {
- color: #fff !important;
- }
-
- .el-submenu__title:hover i {
- color: #fff !important;
- }
-
- .el-menu-item:hover i {
- color: #fff !important;
- }
-
- .el-menu-item.is-active {
- background-color: #1890ff !important;
- border-radius: 5px !important;
- width: calc(100% - 8px);
- margin-left: 4px;
- }
-
- .el-menu-item.is-active i, .el-menu-item.is-active .el-tooltip {
- margin-left: -4px;
- }
-
- .el-menu-item {
- height: 40px !important;
- line-height: 40px !important;
- }
-
- .el-submenu__title {
- height: 40px !important;
- line-height: 40px !important;
- }
-
- .el-submenu .el-menu-item {
- min-width: 0 !important;
- }
-
- .el-menu--inline .el-menu-item.is-active {
- padding-left: 45px !important;
- }
-
- /*.el-submenu__icon-arrow {*/
- /* margin-top: -5px;*/
- /*}*/
-
- .el-aside {
- transition: width .3s;
- box-shadow: 2px 0 6px rgba(0, 21, 41, .35);
- }
-
- .logo-title {
- margin-left: 5px;
- font-size: 20px;
- transition: all .3s; /* 0.3s */
- }
-
- .el-header {
- box-shadow: 2px 0 6px rgba(0, 21, 41, .35);
- display: flex;
- align-items: center;
- }
- </style>
login.vue:
- <template>
- <div style="display: flex;align-items: center;justify-content: center;background-color: aquamarine;height: 100vh;">
- <div style="display: flex;width: 50%;background-color: white;border-radius: 5px;overflow: hidden;">
- <div style="flex: 1;">
- <img src="@/assets/login.png" alt="" style="width: 100%;">
- </div>
- <div style="flex: 1;display: flex;align-items: center;justify-content: center;">
- <el-form :model="user" style="width: 80%;" :rules="rules" ref="loginRef">
- <div style="font-weight: bold; font-size: 20px;margin-bottom: 20px;text-align: center;">
- 欢迎登陆后台管理系统
- </div>
- <el-form-item prop="username">
- <el-input placeholder="请输入用户名" v-model="user.username" prefix-icon="el-icon-user"></el-input>
- </el-form-item>
- <el-form-item prop="password">
- <el-input placeholder="请输入密码" v-model="user.password" show-password prefix-icon="el-icon-lock"></el-input>
- </el-form-item>
- <el-form-item prop="code">
- <div style="display: flex;">
- <el-input prefix-icon="el-icon-circle-check" v-model="user.code"></el-input>
- <div style="flex: 1;height: 32px"><valid-code @update:value="getCode"></valid-code></div>
- </div>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" style="width: 100%;" @click="login">登录</el-button>
- </el-form-item>
- <div style="display: flex;">
- <div style="flex: 1;">还没有账号?去<span style="color:aquamarine;cursor: pointer;" @click="$router.push('/register')">注册</span></div>
- <div style="flex: 1;text-align: right;cursor: pointer;color: aquamarine;" @click="handleForgetPass">忘记密码</div>
- </div>
- </el-form>
- </div>
- </div>
- <el-dialog title="忘记密码" :visible.sync="forgetPassDialogVis" width="30%">
- <el-form :model="forgetUserForm" label-width="80px" style="padding-right: 20px">
- <el-form-item label="用户名">
- <el-input v-model="forgetUserForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="手机号">
- <el-input v-model="forgetUserForm.phone" autocomplete="off"></el-input>
- </el-form-item>
- </el-form>
- <div slot="footer" class="dialog-footer">
- <el-button @click="forgetPassDialogVis = false">取 消</el-button>
- <el-button type="primary" @click="resetPassword">确 定</el-button>
- </div>
- </el-dialog>
- </div>
- </template>
-
- <script>
- import ValidCode from "@/components/ValidCode.vue";
- export default {
- name:'login',
- components:{
- ValidCode
- },
- data() {
-
- const validateCode = (rule, value, callback) => {
- if (value === '') {
- callback(new Error('请输入验证码'));
- } else if(value.toLowerCase() !== this.code){
- callback(new Error('验证码错误'));
- } else {
- callback();
- }
- };
- return {
- forgetUserForm:{
-
- },
- forgetPassDialogVis:false,
- code:'',
- user: {
- code:'',
- username: '',
- password: ''
- },
- rules:{
- username:[{
- required:'true',message:'请输入账号',trigger:'blur'
- }],
- password:[{
- required:'true',message:'请输入密码',trigger:'blur'
- }],
- code:[{
- validator:validateCode,trigger:'blur'
- }]
- },
- }
- },
- methods:{
- handleForgetPass(){
- this.forgetUserForm={}
- this.forgetPassDialogVis=true
- },
- getCode(code){
- this.code=code.toLowerCase()
- },
- resetPassword(){
- this.$request.put('/password',this.forgetUserForm).then(res=>{
- if(res.code==='200'){
- this.$message.success('密码重置成功')
- this.forgetPassDialogVis=false
- }else{
- this.$message.error(res.msg)
- }
- })
- },
- login(){
- this.$refs['loginRef'].validate((valid=>{
- if(valid){
- this.$request.post("/login",this.user).then(res=>{
- if(res.code === '200'){
- this.$router.push('/')
- this.$message.success('登录成功')
- localStorage.setItem('honey-user',JSON.stringify(res.data))
- }else{
- this.$message.error(res.msg)
- }
- console.log(res);
- })
- }
- }))
- }
- }
- }
- </script>
-
- <style scoped></style>
只需要为忘记密码编写一个新接口即可:

WebController:
- package com.example.springboot.controller;
-
- import cn.hutool.core.util.StrUtil;
- import com.example.springboot.common.AuthAccess;
- import com.example.springboot.common.Result;
- import com.example.springboot.entity.User;
- import com.example.springboot.exception.ServiceException;
- import com.example.springboot.service.UserService;
- import org.springframework.web.bind.annotation.*;
-
- import javax.annotation.Resource;
-
- @RestController
- public class WebController {
- @Resource
- UserService userService;
-
- @AuthAccess
- @GetMapping("/")
- public Result hello(){
- return Result.success("success");
- }
-
- @PostMapping("/login")
- public Result login(@RequestBody User user){
- if(StrUtil.isBlank(user.getUsername())||StrUtil.isBlank(user.getPassword())){
- return Result.error("数据输入错误");
- }
- user=userService.login(user);
- return Result.success(user);
- }
-
- @AuthAccess
- @PostMapping("/register")
- public Result register(@RequestBody User user){
- if(StrUtil.isBlank(user.getUsername())||StrUtil.isBlank(user.getPassword())){
- throw new ServiceException("输入不合法");
- }
- if(user.getUsername().length()>10||user.getPassword().length()>20){
- throw new ServiceException("长度过长");
- }
- user=userService.register(user);
- return Result.success(user);
- }
- @AuthAccess
- @PutMapping("/password")
- public Result password(@RequestBody User user){
- if(StrUtil.isBlank(user.getUsername())||StrUtil.isBlank(user.getPhone())){
- throw new ServiceException("输入不合法");
- }
- userService.resetPassword(user);
- return Result.success();
- }
- }
UserService:
- package com.example.springboot.service;
-
- import com.example.springboot.entity.User;
- import com.example.springboot.exception.ServiceException;
- import com.example.springboot.mapper.UserMapper;
- import com.example.springboot.utils.TokenUtils;
- import jdk.nashorn.internal.parser.Token;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.web.bind.annotation.RequestBody;
-
- import java.util.List;
-
- @Service
- public class UserService {
- @Autowired
- UserMapper userMapper;
- public void insertUser(User user){
- userMapper.insert(user);
- }
-
- public void updateUser(User user) {
- userMapper.updateUser(user);
- }
-
- public void deleteUser(Integer id) {
- userMapper.deleteUser(id);
- }
-
- public void batchdeleteUser(List
ids ) { - for(Integer id : ids){
- userMapper.deleteUser(id);
- }
- }
-
-
- public List<User> selectall() {
- return userMapper.selectall();
- }
-
- public User selectbyid(Integer id) {
- return userMapper.selectbyid(id);
- }
-
- public List<User> selectbyname(String name) {
- return userMapper.selectbyname(name);
- }
-
- public List<User> selectbymore(String username, String name) {
- return userMapper.selectbymore(username,name);
- }
-
- public List<User> selectbymo(String username, String name) {
- return userMapper.selectbymo(username,name);
- }
-
- public User login(User user) {
- User dbuser=userMapper.selectbyUsername(user.getUsername());
- if(dbuser == null){
- throw new ServiceException("账号不存在");
- }
- if(!user.getPassword().equals(dbuser.getPassword())){
- throw new ServiceException("账号或者密码错误");
- }
- String token=TokenUtils.createToken(dbuser.getId().toString(),dbuser.getPassword());
- dbuser.setToken(token);
- return dbuser;
- }
-
- public User register(User user) {
- User dbuser=userMapper.selectbyUsername(user.getUsername());
- if(dbuser != null){
- throw new ServiceException("用户名已存在");
- }
- userMapper.insert(user);
- return user;
- }
-
- public void resetPassword(User user) {
- User dbuser=userMapper.selectbyUsername(user.getUsername());
- if(dbuser==null){
- throw new ServiceException("用户不存在");
- }
- if(!user.getPhone().equals(dbuser.getPhone())){
- throw new ServiceException("验证错误");
- }
- dbuser.setPassword("123");
- userMapper.updateUser(dbuser);
- }
- }