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
})
}