前端学习(2431):用户退出

    科技2025-07-09  14

     

    app.vue

    <template> <div id="app"> <router-view/> </div> </template> <script> export default { name: 'App' } </script> <style lang="less"> </style>

    index.vue

    <template> <el-container class="layout-container"> <el-aside class="aside" width="auto"> <app-aside class="aside-menu" :is-collapse="isCollapse"></app-aside> </el-aside> <el-container> <el-header class="header"> <div> <i :class="{'el-icon-s-fold':isCollapse, 'el-icon-s-unfold':!isCollapse}" @click="isCollapse=!isCollapse"></i> <span>江苏传智播客科技教育有限公司</span> </div> <el-dropdown> <div class="avatar-wrap"> <img class="avatar" :src="user.photo" alt=""> <span>{{user.name}}</span> <i class="el-icon-arrow-down el-icon&#45;&#45;right"></i> </div> <!--<span> 下拉菜单<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i> </span>--> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>设置</el-dropdown-item> <!--监听加一个修饰符--> <el-dropdown-item @click.native="onLogOut">退出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-header> <el-main class="main"> <router-view /></el-main> </el-container> </el-container> </template> <script> import AppAside from './component/aside' import { getUserProfile } from '@/api/user' export default { name: 'LayoutIndex', components: { AppAside }, component: { AppAside }, data () { return { user: {}, isCollapse: false// 侧边栏展开状态 } }, created () { this.loadUserProfile() }, methods: { loadUserProfile () { // 这个接口需要授权才能使用 getUserProfile().then(res => { console.log(res) this.user = res.data.data }) }, onLogOut () { this.$confirm('确认退出吗', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { window.localStorage.removeItem('user') this.$router.push('login') }).catch(() => { this.$message({ type: 'info', message: '已取消退出' }) }) } } } </script> <style scoped lang="less"> .layout-container{ position: fixed; left:0; right:0; top:0; bottom: 0; } .aside{ width: 100px; background-color: #d3dce6; .aside-menu{ height: 100%; } } .header{ height: 60px; background-color: #b3c0d1; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ccc; } .main{ background-color: #e9eef3; } .avatar-wrap{ display: flex; align-items: center; .avatar{ width: 40px; height: 40px; border-radius: 50%; margin-right: 10px; } } </style>

    main.js

    import Vue from 'vue' import App from './App.vue' import router from './router' import './styles/index.less' // 加载组件库 import ElementUI from 'element-ui' // 加载样式 import 'element-ui/lib/theme-chalk/index.css' Vue.config.productionTip = false // 注册组件库 Vue.use(ElementUI) new Vue({ router, render: h => h(App) }).$mount('#app')

    index.js

    import Vue from 'vue' import VueRouter from 'vue-router' // @表示src路径的别名 好处就是它不受当前文件路径影响 import Login from '@/views/login/index' import Home from '@/views/home/home' import Layout from '@/views/layout/index' Vue.use(VueRouter) // 路由配置表 const routes = [{ path: '/login', name: 'login', component: Login }, { path: '/', /* name: 'layout', */ component: Layout, children: [{ path: '', // path为空 会作为默认子路由 name: 'home', component: Home }] } ] const router = new VueRouter({ routes }) // 路由导航守卫 // 所有页面都会经过这里 router.beforeEach((to, from, next) => { console.log('页面进来了') console.log(to) console.log(from) const user = JSON.parse(window.localStorage.getItem('user')) if (to.path !== '/login') { if (user) { next() } else { next('/login') } } else { next()// 允许通过 } // 允许通过 }) export default router

    user.js

    // 用户登录的请求模块 import request from '@/utils/request' export const login = data => { return request({ method: 'POST', url: '/mp/v1_0/authorizations', data }) } // 获取用户信息 export const getUserProfile = () => { const user = JSON.parse(window.localStorage.getItem('user')) console.log(user) return request({ method: 'GET', url: '/mp/v1_0/user/profile' // axios通过headers /* headers: { Authorization: `Bearer ${user.token}` } */ }) }

    index.vue

    <template> <div class="home-container">首页</div> </template> <script> export default { name: 'HomeIndex', data () { return { } } } </script> <style scoped lang="less"> </style>

    index.vue

    <template> <el-container class="layout-container"> <el-aside class="aside" width="auto"> <app-aside class="aside-menu" :is-collapse="isCollapse"></app-aside> </el-aside> <el-container> <el-header class="header"> <div> <i :class="{'el-icon-s-fold':isCollapse, 'el-icon-s-unfold':!isCollapse}" @click="isCollapse=!isCollapse"></i> <span>江苏传智播客科技教育有限公司</span> </div> <el-dropdown> <div class="avatar-wrap"> <img class="avatar" :src="user.photo" alt=""> <span>{{user.name}}</span> <i class="el-icon-arrow-down el-icon&#45;&#45;right"></i> </div> <!--<span> 下拉菜单<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i> </span>--> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>设置</el-dropdown-item> <el-dropdown-item>退出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-header> <el-main class="main"> <router-view /></el-main> </el-container> </el-container> </template> <script> import AppAside from './component/aside' import { getUserProfile } from '@/api/user' export default { name: 'LayoutIndex', components: { AppAside }, component: { AppAside }, data () { return { user: {}, isCollapse: false// 侧边栏展开状态 } }, created () { this.loadUserProfile() }, methods: { loadUserProfile () { // 这个接口需要授权才能使用 getUserProfile().then(res => { console.log(res) this.user = res.data.data }) } } } </script> <style scoped lang="less"> .layout-container{ position: fixed; left:0; right:0; top:0; bottom: 0; } .aside{ width: 100px; background-color: #d3dce6; .aside-menu{ height: 100%; } } .header{ height: 60px; background-color: #b3c0d1; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ccc; } .main{ background-color: #e9eef3; } .avatar-wrap{ display: flex; align-items: center; .avatar{ width: 40px; height: 40px; border-radius: 50%; margin-right: 10px; } } </style>

    aside.vue

     

    <template> <!-- el-menu-item 的 index 不能重复,确保唯一即可 --> <el-menu class="nav-menu el-menu-vertical-demo" :default-active="$route.path" background-color="#002033" text-color="#fff" active-text-color="#ffd04b" router :collapse="isCollapse" > <el-menu-item index="/"> <i class="el-icon-s-home"></i> <span slot="title">首页</span> </el-menu-item> <el-menu-item index="/article"> <i class="el-icon-document"></i> <span slot="title">内容管理</span> </el-menu-item> <el-menu-item index="/image"> <i class="iconfont iconimage"></i> <span slot="title">素材管理</span> </el-menu-item> <el-menu-item index="/publish"> <i class="iconfont iconpublish"></i> <span slot="title">发布文章</span> </el-menu-item> <el-menu-item index="/comment"> <i class="iconfont iconcomment"></i> <span slot="title">评论管理</span> </el-menu-item> <el-menu-item index="/fans"> <i class="el-icon-setting"></i> <span slot="title">粉丝管理</span> </el-menu-item> <el-menu-item index="/settings"> <i class="el-icon-setting"></i> <span slot="title">个人设置</span> </el-menu-item> </el-menu> </template> <script> export default { name: 'AppAside', data () { return { /* isCollapse: false */ } }, props: ['is-collapse'], methods: { handleOpen (key, keyPath) { console.log(key, keyPath) }, handleClose (key, keyPath) { console.log(key, keyPath) } } } </script> <style scoped lang="less"> .nav-menu { .iconfont { margin-right: 10px; padding-left: 5px; } } </style>

     request.js

    // axios import axios from 'axios' // 创建实例 通过实例发送请求 const request = axios.create({ // 请求的基本路径 baseURL: 'http://ttapi.research.itcast.cn/' }) // 导出 export default request // 请求拦截器 request.interceptors.request.use( function (config) { console.log(config) const user = JSON.parse(window.localStorage.getItem('user')) if (user) { config.headers.Authorization = `Bearer ${user.token}` } return config }, function (error) { return Promise.reject(error) } ) // 响应烂机器 /* import request from 'request.js' request.xxx request({ method:, url:'' }) */

    运行结果

    Processed: 0.011, SQL: 8