SpringBoot2+Vue2实战(十三)用户前台页面设计与实现

Front.vue

<template>
  <div>
    <!--头部-->
    <div style="display: flex; height: 60px;line-height: 60px;border-bottom: 1px solid #ccc">
      <div style="width: 300px;display: flex;padding-left: 30px">
        <div style="width: 60px">
          <img src="../../assets/logo1.png" alt="" style="width: 50px;position: relative;top: 5px;right: 0">
        </div>
        <span style="flex: 1">欢迎来到xx系统</span>
      </div>


      <div style="flex: 1">
        
        <el-menu :default-active="'1'" class="el-menu-demo" mode="horizontal">
          <el-menu-item index="1">处理中心</el-menu-item>
          <el-submenu index="2">
            <template slot="title">我的工作台</template>
            <el-menu-item index="2-1">选项1</el-menu-item>
            <el-menu-item index="2-2">选项2</el-menu-item>
            <el-menu-item index="2-3">选项3</el-menu-item>
            <el-submenu index="2-4">
              <template slot="title">选项4</template>
              <el-menu-item index="2-4-1">选项1</el-menu-item>
              <el-menu-item index="2-4-2">选项2</el-menu-item>
              <el-menu-item index="2-4-3">选项3</el-menu-item>
            </el-submenu>
          </el-submenu>
          <el-menu-item index="3" disabled>消息中心</el-menu-item>
          <el-menu-item index="4">订单管理</el-menu-item>
        </el-menu>
      </div>


      <div style="width: 200px">
        <div v-if="!user.username" style="text-align: right;padding-right: 30px">
          <el-button @click="$router.push('/login')">登录</el-button>
          <el-button @click="$router.push('/register')">注册</el-button>
        </div>
        <div v-else>
          <el-dropdown trigger="click" style="width: 150px; cursor: pointer;text-align:right">
            <div style="display: inline-block">
              <img :src="user.avatarUrl" referrerpolicy="no-referrer" alt=""
                   style="width: 30px; border-radius: 50%; position: relative; top: 10px; right: 5px">
              <span>{{ user.nickname }}</span><i class="el-icon-arrow-down" style="margin-left: 5px"></i>
            </div>
            <el-dropdown-menu slot="dropdown" style="width: 100px; text-align: center">
              <el-dropdown-item style="font-size: 14px; padding: 5px 0">
                <router-link to="/person" style="text-decoration: none">个人信息</router-link>
              </el-dropdown-item>
              <el-dropdown-item style="font-size: 14px; padding: 5px 0">
                <span style="text-decoration: none" @click="logout">退出</span>
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>
    </div>


   <div style="width: 1000px;margin: 0 auto">
     <router-view/>
   </div>


  </div>
</template>

<script>
export default {
  name: "Front",
  data() {
    return {
      user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}
    }
  },
  created() {
  },
  methods: {
    logout() {
      this.$store.commit("logout")
      this.$message.success("退出成功")
    }
  }
}
</script>

<style>

.item {
  display: inline-block;
  width: 100px;
  color: #1E90FF;
  text-align: center;
  cursor: pointer;
}

.item:hover {
  background-color: LightPink;
}

.item a {
  color: #1E90FF;
}
</style>

Front/Home.vue

<template>
  <div>
    <div style="margin: 10px  0 ">
      <el-carousel height="450px" :interval="10000">
        <el-carousel-item v-for="item in imgs " :key="item">
          <img :src="item" alt="" style="width: 100%">
        </el-carousel-item>
      </el-carousel>
    </div>

    <div style="margin: 10px 0">
      <el-row :gutter="10">
        <el-col :span="6">

        </el-col>
        <el-col :span="6">

        </el-col>
        <el-col :span="6">

        </el-col>
        <el-col :span="6">

        </el-col>
      </el-row>
    </div>


  </div>
</template>

<script>
export default {
  name: "FrontHome",
  data() {
    return {
      imgs: [
        'https://img.zcool.cn/community/01a3ac554552c80000019ae94606ed.jpg?x-oss-process=image/auto-orient,1/resize,m_lfit,w_1280,limit_1/sharpen,100',
        'https://img0.baidu.com/it/u=4046160075,3620795722&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1688835600&t=1e123cac27815414376ce5c302027d8b'
      ]
    }
  }
}
</script>

<style scoped>

</style>

router/index.js

{
        path: '/front',
        name: 'Front',
        component: () => import('../views/front/Front.vue'),
        children:[
            {
                path: 'home',
                name: 'FrontHome',
                component: () => import('../views/front/Home.vue')
            },
        ]
    },

Login.vue

使得学生只能访问前台页面

login() {
      this.$refs['userForm'].validate((valid) => {
        if (valid) {  // 表单校验合法
          this.request.post("/user/login", this.user).then(res => {
            if (res.code === '200') {
              //存储用户信息到浏览器
              localStorage.setItem("user", JSON.stringify(res.data))
              localStorage.setItem("menus", JSON.stringify(res.data.menus))
              //动态设置当前用户的路由
              setRoutes()
              this.$message.success("登录成功")

              if (res.data.role === 'ROLE_STUDENT') {
                this.$router.push("/front/home")
              } else {
                this.$router.push("/")
              }
            } else {
              this.$message.error(res.msg)
            }
          })
        }
      });
    }

一、接口放开

第一种方法 

jwt拦截

InterceptorConfig
//放行
                .excludePathPatterns("/user/login","/user/register","/**/export","/**/import","/file/**");

FileController 

@GetMapping("/find/all")
    public Result frontAll(){
        return Result.success(fileMapper.selectList(null));
    }

 

 第二种方法

 自定义注解

AuthAccess

package com.example.springboot.config;

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthAccess {


}

EchartsController

@Resource
    private FileMapper fileMapper;




@AuthAccess
    @GetMapping("/file/front/all")
    public Result frontAll(){
        return Result.success(fileMapper.selectList(null));
    }
JwtInterceptor进行判断是否加了注解,加了就放行
if (!(handler instanceof  HandlerMethod)){
            return true;
        }else {
            HandlerMethod h  = (HandlerMethod) handler;
            AuthAccess authAccess = h.getMethodAnnotation(AuthAccess.class);
            if (authAccess != null){
                return true;
            }
        }

front/Home.vue

<div>
    <div style="margin: 10px  0 ">
      <el-carousel height="450px" :interval="10000">
        <el-carousel-item v-for="item in imgs " :key="item">
          <img :src="item" alt="" style="width: 100%">
        </el-carousel-item>
      </el-carousel>
    </div>

    <div style="margin: 10px 0">
      <el-row :gutter="10">
        <el-col :span="6" v-for="item in files" :key="item.id" style="margin-bottom: 10px">

          <div style="padding-bottom: 10px;border: 1px solid #ccc">
            <img :src="item.url" alt="" style="width: 200px ;height: 200px">
            <div style="color: #666;padding: 10px">{{ item.name }}</div>
            <div style="padding: 10px">
              <el-button type="primary">购买</el-button>
            </div>
          </div>
        </el-col>
      </el-row>
    </div>


  </div>
</template>

<script>
export default {
  name: "FrontHome",
  data() {
    return {
      imgs: [
        'https://img.zcool.cn/community/01a3ac554552c80000019ae94606ed.jpg?x-oss-process=image/auto-orient,1/resize,m_lfit,w_1280,limit_1/sharpen,100',
        'https://img0.baidu.com/it/u=4046160075,3620795722&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1688835600&t=1e123cac27815414376ce5c302027d8b'
      ],
      files: []
    }
  },
  created() {
    this.request.get("/echarts/file/front/all").then(res => {
      this.files = res.data.filter(v => v.type === 'png' || v.type === 'jpg' || v.type === 'webp')
    })
  },
  methods: {}
}
</script>

<style scoped>

</style>

添加一个个人信息界面

Front.vue

<el-dropdown-item style="font-size: 14px; padding: 5px 0">
                <router-link to="/front/person" style="text-decoration: none">个人信息</router-link>
              </el-dropdown-item>

front/Person.vue

<template>
  <el-card style="width: 500px;">
    <el-form label-width="80px" size="small">
      <el-upload

          class="avatar-uploader"
          action="http://localhost:9090/file/upload"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
      >
        <img v-if="form.avatarUrl" :src="form.avatarUrl" class="avatar">
        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
      </el-upload>
      <el-form-item label="用户名">
        <el-input v-model="form.username" disabled autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="昵称">
        <el-input v-model="form.nickname" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="邮箱">
        <el-input v-model="form.email" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="电话">
        <el-input v-model="form.phone" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="地址">
        <el-input type="textarea" v-model="form.address" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="save">确 定</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script>
export default {
  name: "FrontPerson",
  data() {
    return {
      form: {},
      user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}
    }
  },
  created() {
    this.getUser().then(res => {
      this.form = res
    })
  },
  methods: {
    async getUser() {
      return (await this.request.get("/user/findUserName/" + this.user.username)).data
    },
    save() {
      this.request.post("/user/saveUser", this.form).then(res => {
        if (res.code === '200') {
          this.$message.success("保存成功")

          //触发父级更新User的方法
          this.$emit("refreshUser")

          //更新浏览器存储的用户信息
          this.getUser().then(res =>{
            res.token = JSON.parse(localStorage.getItem("user")).token
            localStorage.setItem("user",JSON.stringify(res))
          })
        } else {
          this.$message.error("保存失败")
        }
      })
    },
    handleAvatarSuccess(res) {
      this.form.avatarUrl = res
    },
  }
}
</script>

<style>
.avatar-uploader {
  text-align: center;
  padding-bottom: 10px;
}

.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: 138px;
  height: 138px;
  line-height: 138px;
  text-align: center;
}

.avatar {
  width: 138px;
  height: 138px;
  display: block;
}
</style>

router/index.js

{
                path: 'person',
                name: 'FrontPerson',
                component: () => import('../views/front/Person.vue')
            },

处理更新头像后不刷新问题

Front.vue

<div style="width: 1000px;margin: 0 auto">
     <router-view @refreshUser="getUser"/>
   </div>




created() {
    this.getUser()
  },




getUser() {
      let username = localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")).username : ""
      //从后台获取数据
      this.request.get("user/findUserName/" + username).then(res => {
        //重新赋值后台的最新数据
        this.user = res.data
      })
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值