vue3后台管理系统之顶部tabbar组件搭建

1.1静态页面搭建

<template><div class="tabbar"><div class="tabbar_left"><!-- 面包屑 --><Breadcrumb /></div><div class="tabbar_right"><!-- 设置 --><Setting /></div></div>
</template><script setup lang="ts">
import Breadcrumb from './breadcrumb/index.vue'
import Setting from './setting/index.vue'
</script>
<script lang="ts">
export default {name: 'Tabbar',
}
</script>
<style scoped lang="scss">
.tabbar {width: 100%;height: 100%;display: flex;justify-content: space-between;// background-image: linear-gradient(to right, rgb(232, 223, 223), rgb(201, 178, 178), rgb(197, 165, 165));.tabbar_left {display: flex;align-items: center;margin-left: 20px;}.tabbar_right {display: flex;align-items: center;}
}
</style>

面包屑

<template><!-- 顶部左侧静态 --><el-icon style="margin-right: 10px" @click="changeIcon"><!-- <component :is="LayOutSettingStore.fold ? 'Fold' : 'Expand'" /> --></el-icon><!-- 左侧面包屑 --><el-breadcrumb separator-icon="ArrowRight"><!-- 面包动态展示路由名字与标题 --><el-breadcrumb-item v-for="(item, index) in $route.matched" v-show="item.meta.title" :key="index" :to="item.path"><!-- 图标 --><el-icon><component :is="item.meta.icon" /></el-icon><!-- 面包屑展示匹配路由的标题 --><span>{{ item.meta.title }}</span></el-breadcrumb-item></el-breadcrumb>
</template><script setup lang="ts">
import { useRoute } from 'vue-router'
// import useLayOutSettingStore from '@/store/moudles/setting'
// //获取layout配置相关的仓库
// const LayOutSettingStore = useLayOutSettingStore()
//获取路由对象
const $route = useRoute()
console.log($route.matched, '111')//点击图标的方法
const changeIcon = () => {//图标进行切换LayOutSettingStore.fold = !LayOutSettingStore.fold
}
</script>
<script lang="ts">
export default {name: 'Breadcrumb'
}
</script><style scoped></style>

设置

<template><el-button size="small" icon="Refresh" circle @click="updateRefsh" /><el-button size="small" icon="FullScreen" circle @click="fullScreen" /><el-popover placement="bottom" title="主题设置" :width="300" trigger="hover"><!-- 表单元素 --><el-form><el-form-item label="主题颜色"><!-- <el-color-picker v-model="color" size="small" show-alpha :predefine="predefineColors" @change="setColor" /> --></el-form-item><el-form-item label="暗黑模式"><el-switchv-model="dark"class="mt-2"style="margin-left: 24px"inline-promptactive-icon="MoonNight"inactive-icon="Sunny"@change="changeDark"/></el-form-item></el-form><template #reference><el-button size="small" icon="Setting" circle /></template></el-popover><img :src="userStore.avatar" style="width: 24px; height: 24px; margin: 0px 10px; border-radius: 50%" /><!-- 下拉菜单 --><el-dropdown><span class="el-dropdown-link">admin<el-icon class="el-icon--right"><arrow-down /></el-icon></span><template #dropdown><el-dropdown-menu><el-dropdown-item @click="logout">退出登录</el-dropdown-item></el-dropdown-menu></template></el-dropdown>
</template><script setup lang="ts">
import { ref } from 'vue'
// import { useRouter, useRoute } from 'vue-router'
//获取用户相关的小仓库
import useUserStore from '@/store/modules/user'
//获取骨架的小仓库
// import useLayOutSettingStore from '@/store/modules/setting'
// const layoutSettingStore = useLayOutSettingStore()
const userStore = useUserStore()
//获取路由器对象
// let $router = useRouter()
//获取路由对向
// let $route = useRoute()
//收集开关的数据
const dark = ref<boolean>(false)
//刷新按钮点击回调
const updateRefsh = () => {layoutSettingStore.refsh = !layoutSettingStore.refsh
}
//全屏按钮点击的回调
const fullScreen = () => {//DOM对象的一个属性:可以用来判断当前是不是全屏模式[全屏:true,不是全屏:false]const full = document.fullscreenElement//切换为全屏模式if (!full) {//文档根节点的方法requestFullscreen,实现全屏模式document.documentElement.requestFullscreen()} else {//变为不是全屏模式->退出全屏模式document.exitFullscreen()}
}
//退出登录点击回调
const logout = async () => {//第一件事情:需要向服务器发请求[退出登录接口]******//第二件事情:仓库当中关于用于相关的数据清空[token|username|avatar]//第三件事情:跳转到登录页面//跳转到登录页面
}//颜色组件组件的数据
const color = ref('rgba(255, 69, 0, 0.68)')
const predefineColors = ref(['#ff4500','#ff8c00','#ffd700','#90ee90','#00ced1','#1e90ff','#c71585','rgba(255, 69, 0, 0.68)','rgb(255, 120, 0)','hsv(51, 100, 98)','hsva(120, 40, 94, 0.5)','hsl(181, 100%, 37%)','hsla(209, 100%, 56%, 0.73)','#c7158577'
])//switch开关的chang事件进行暗黑模式的切换
const changeDark = () => {//获取HTML根节点const html = document.documentElement//判断HTML标签是否有类名darkdark.value ? (html.className = 'dark') : (html.className = '')
}//主题颜色的设置
const setColor = () => {//通知js修改根节点的样式对象的属性与属性值const html = document.documentElementhtml.style.setProperty('--el-color-primary', color.value)
}
</script><script lang="ts">
export default {name: 'Setting'
}
</script>
<style scoped></style>

1.2菜单折叠效果实现

//小仓库:layout组件相关配置仓库
import { defineStore } from 'pinia'const useLayOutSettingStore = defineStore('SettingStore', {state: () => {return {fold: false, //用户控制菜单折叠还是收起控制refsh: false, //仓库这个属性用于控制刷新效果}},
})export default useLayOutSettingStore

动态判断菜单是否折叠,然后情况修改样式

<template><div class="layout_container"><!-- 左侧导航 --><divclass="layout_slider":class="{ fold: LayOutSettingStore.fold ? true : false }"><Logo /><!-- 展示菜单 --><!-- 滚动组件 --><el-scrollbar class="scrollbar"><!-- 菜单组件--><el-menu:collapse="LayOutSettingStore.fold ? true : false":default-active="$route.path"background-color="#001529"text-color="white"active-text-color="yellowgreen"><!-- 根据路由动态生成菜单 --><Menu :menuList="userStore.menuRoutes"></Menu></el-menu></el-scrollbar></div><!-- 顶部导航 --><divclass="layout_tabbar":class="{ fold: LayOutSettingStore.fold ? true : false }"><Tabbar></Tabbar></div><!-- 内容展示区 --><divclass="layout_main":class="{ fold: LayOutSettingStore.fold ? true : false }"><router-view></router-view></div></div>
</template>
<script setup lang="ts">
import Menu from './components/menu/index.vue'
import Logo from './components/logo/index.vue'
import Tabbar from './components/tabbar/index.vue'
//获取用户相关的小仓库
import useUserStore from '@/store/moudules/user'
let userStore = useUserStore()
// 獲取路有對象
import { useRoute } from 'vue-router'
import useLayOutSettingStore from '@/store/moudules/setting'
//获取layout配置仓库
let LayOutSettingStore = useLayOutSettingStore()
//获取路由器
let $route = useRoute()
console.log($route.path)
</script>
<script lang="ts">
export default {name: 'Layout',
}
</script>
<style scoped lang="scss">
.layout_container {width: 100%;height: 100vh;.layout_slider {color: white;width: $base-menu-width;height: 100vh;background: $base-menu-background;transition: all 0.3s;.scrollbar {width: 100%;height: calc(100vh - $base-menu-logo-height);.el-menu {border-right: none;}}}.layout_tabbar {position: fixed;width: calc(100% - $base-menu-width);height: $base-tabbar-height;top: 0px;left: $base-menu-width;transition: all 0.3s;&.fold {width: calc(100vw - $base-menu-min-width);left: $base-menu-min-width;background-color: #fff;}}.layout_main {transition: all 0.3s;position: absolute;width: calc(100% - $base-menu-width);height: calc(100vh - $base-tabbar-height);left: $base-menu-width;top: $base-tabbar-height;padding: 20px;overflow: auto;background-color: yellowgreen;&.fold {width: calc(100vw - $base-menu-min-width);left: $base-menu-min-width;}}
}
</style>

1.3面包屑的实现

<template><!-- 顶部左侧静态 --><el-icon style="margin-right: 10px" @click="changeIcon"><component:is="LayOutSettingStore.fold ? 'Fold' : 'Expand'"></component></el-icon><!-- 左侧面包屑 --><el-breadcrumb separator-icon="ArrowRight"><!-- 面包动态展示路由名字与标题 --><el-breadcrumb-itemv-for="(item, index) in $route.matched":key="index"v-show="item.meta.title":to="item.path"><!-- 图标 --><el-icon><component :is="item.meta.icon"></component></el-icon><!-- 面包屑展示匹配路由的标题 --><span>{{ item.meta.title }}</span></el-breadcrumb-item></el-breadcrumb>
</template><script setup lang="ts">
import { useRoute, useRouter } from 'vue-router'
import useLayOutSettingStore from '@/store/moudules/setting'
//获取layout配置相关的仓库
let LayOutSettingStore = useLayOutSettingStore()
//获取路由对象
let $route = useRoute()
console.log($route)
console.log($route.matched, '111')
let $router = useRouter()
console.log($router, '111')//点击图标的方法
const changeIcon = () => {//图标进行切换LayOutSettingStore.fold = !LayOutSettingStore.fold
}
</script>
<script lang="ts">
export default {name: 'Breadcrumb',
}
</script><style scoped></style>

1.4刷新业务的实现

设置一个全局变量

//获取骨架的小仓库
import useLayOutSettingStore from '@/store/modules/setting'
const layoutSettingStore = useLayOutSettingStore()
//刷新按钮点击回调
const updateRefsh = () => {layoutSettingStore.refsh = !layoutSettingStore.refsh
}

<template><!-- 路由组件出口的位置 --><router-view v-slot="{ Component }"><transition name="fade"><!-- 渲染layout一级路由组件的子路由 --><component :is="Component" v-if="flag" /></transition></router-view>
</template><script setup lang="ts">
import { watch, ref, nextTick } from 'vue'
import useLayOutSettingStore from '@/store/moudules/setting'
let layOutSettingStore = useLayOutSettingStore()//控制当前组件是否销毁重建
let flag = ref(true)//监听仓库内部数据是否发生变化,如果发生变化,说明用户点击过刷新按钮
watch(() => layOutSettingStore.refsh,() => {//点击刷新按钮:路由组件销毁flag.value = falsenextTick(() => {flag.value = true})},
)
</script>
<script lang="ts">
export default {// eslint-disable-next-line vue/no-reserved-component-namesname: 'Main',
}
</script><style scoped>
.fade-enter-from {opacity: 0;transform: scale(0);
}.fade-enter-active {transition: all 0.3s;
}.fade-enter-to {opacity: 1;transform: scale(1);
}
</style>

1.5全屏功能的实现

//全屏按钮点击的回调
const fullScreen = () => {//DOM对象的一个属性:可以用来判断当前是不是全屏模式[全屏:true,不是全屏:false]const full = document.fullscreenElement//切换为全屏模式if (!full) {//文档根节点的方法requestFullscreen,实现全屏模式document.documentElement.requestFullscreen()} else {//变为不是全屏模式->退出全屏模式document.exitFullscreen()}
}

1.6获取用户信息

//获取用户信息方法async userInfo() {//获取用户信息进行存储仓库当中[用户头像、名字]const result: userInfoReponseData = await reqUserInfo()console.log(result)//如果获取用户信息成功,存储一下用户信息if (result.code == 200) {this.username = result.data.checkUser.usernamethis.avatar = result.data.checkUser.avatar}},

import axios from 'axios'
import { ElMessage } from 'element-plus'
//引入用户相关的仓库
import useUserStore from '@/store/modules/user'
//创建axios实例
const request = axios.create({baseURL: import.meta.env.VITE_APP_BASE_URL,timeout: 5000
})
//请求拦截器
request.interceptors.request.use((config) => {//获取用户相关的小仓库:获取仓库内部token,登录成功以后携带给服务器const userStore = useUserStore()if (userStore.token) {config.headers.token = userStore.token}//config配置对象,headers属性请求头,经常给服务器端携带公共参数//返回配置对象return config
})
//响应拦截器
request.interceptors.response.use((response) => {return response.data},(error) => {//处理网络错误let msg = ''const status = error.response.statusswitch (status) {case 401:msg = 'token过期'breakcase 403:msg = '无权访问'breakcase 404:msg = '请求地址错误'breakcase 500:msg = '服务器出现问题'breakdefault:msg = '无网络'}ElMessage({type: 'error',message: msg})return Promise.reject(error)}
)
export default request

1.7退出登录业务

// 存储
export const SET_TOKEN = (token: string) => {localStorage.setItem('TOKEN', token)
}
// 读取
export const GET_TOKEN = () => {return localStorage.getItem('TOKEN')
}
// 移除token
export const REMOVE_TOKEN = () => {localStorage.removeItem('TOKEN')
}
userLogout() {this.token = ''this.username = ''this.avatar = ''REMOVE_TOKEN()},
//退出登录点击回调
const logout = async () => {//第一件事情:需要向服务器发请求[退出登录接口]******//第二件事情:仓库当中关于用于相关的数据清空[token|username|avatar]//第三件事情:跳转到登录页面//跳转到登录页面userStore.userLogout()$router.push({ path: '/login', query: { redirect: $route.path } })
}

再设置一个退出登录再登录返回原来的路由

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/118009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶的未来展望和挑战

自动驾驶技术是一项引人瞩目的创新&#xff0c;将在未来交通领域产生深远影响。然而&#xff0c;随着技术的不断演进&#xff0c;自动驾驶也面临着一系列挑战和障碍。本文将探讨自动驾驶的未来发展方向、技术面临的挑战&#xff0c;以及自动驾驶对社会和环境的潜在影响。 自动驾…

封装一个vue3 Toast组件,支持组件和api调用

先来看一段代码 components/toast/index.vue <template><div v-if"isShow" class"toast">{{msg}}</div> </template><script setup> import { ref, watch } from vue const props defineProps({show: {type: Boolean,def…

JVM 类的加载子系统

文章目录 类的加载过程加载阶段链接阶段初始化 类的加载器测试代码中获取对应的加载器获取加载器加载的路径不同类对应的加载器自定义加载器自定义加载器的方式 获取类的加载器的方式双亲委派机制双亲委派机制的好处 Java 的 SPI 机制1. 接口定义2. 具体实现3. 配置 META-INF/s…

Spring Cloud Gateway 路由构建器的源码分析

Spring Cloud Gateway 路由构建器的源码分析 文章目录 1. 路由构建器的入口2. 创建路由规则3. 设置路由规则和属性4. 路由过滤器的设置5. 构建和获取路由规则&#xff1a;6. 实例化路由构建器&#xff1a;8. 路由构建器的源码分析8.1 RouteLocator接口8.2 RouteLocatorBuilder…

springBoot与Vue共同搭建webSocket环境

欢迎使用Markdown编辑器 你好&#xff01; 这片文章将教会你从后端springCloud到前端VueEleementAdmin如何搭建Websocket 前端 1. 创建websocket的配置文件在utils文件夹下websocket.js // 暴露自定义websocket对象 export const socket {// 后台请求路径url: ,websocketCo…

Android前台服务和通知

前台服务 Android 13及以上系统需要动态获取通知权限。 //android 13及以上系统动态获取通知权限 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {checkPostNotificationPermission(); } private void checkPostNotificationPermission() {if (ActivityCompat.chec…

信息检索与数据挖掘 | 【实验】排名检索模型

文章目录 &#x1f4da;实验内容&#x1f4da;相关概念&#x1f4da;实验步骤&#x1f407;分词预处理&#x1f407;构建倒排索引表&#x1f407;计算query和各个文档的相似度&#x1f407;queries预处理及检索函数&#x1f525;对输入的文本进行词法分析和标准化处理&#x1f…

【Docker】Dockerfile使用技巧

开启Buildkit BuildKit是Docker官方社区推出的下一代镜像构建神器&#xff0c;可以更加快速&#xff0c;有效&#xff0c;安全地构建docker镜像。 尽管目前BuildKit不是Docker的默认构建工具&#xff0c;但是完全可以考虑将其作为Docker&#xff08;v18.09&#xff09;的首选…

软件工程与计算总结(二十三)软件工程职业基础

本系列最后一更&#xff0c;《软计》系列总结的大结局&#xff01;本栏目告一段落&#xff0c;之后会结合真题和练习题再发布新的总结~ 往期链接&#xff1a; 《软件工程与计算》总结 一.软件工程职业 1.行业的发展 20世纪50年代&#xff1a;计算机还是研究型机器&#xff…

C++中显示构造和隐式构造

截图来源于C primerplus 第六版。

tomcat的负载均衡、动静分离(nginx联动)

动静分离&#xff1a; 访问静态页面和动态页面分开 实现动态和静态页面负载均衡 实验5台虚拟机 一、动态负载均衡 3台虚拟机模拟&#xff1a; 代理服务器&#xff1a;30 tomcat动态页面&#xff1a;21、22 代理服务器&#xff1a; proxy_pass http://tomcat; proxy_set_h…

buuctf[HCTF 2018]WarmUp 1

题目环境&#xff1a; 发现除了表情包&#xff0c;再无其他F12试试发现source.php文件访问这个文件&#xff0c;格式如下&#xff1a;url/source.php回显如下&#xff1a;PHP代码审计&#xff1a; <?php highlight_file(__FILE__); class emmm {public static function ch…

GIS在地质灾害危险性评估与灾后重建中的实践技术应用及python机器学习灾害易发性评价模型建立与优化

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…

C语言进阶第九课 --------动态内存管理

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

k8s-----19、Helm

Helm 1、引入2、概述2.1 重点2.2 V3版本的Helm2.2.1 与之前版本的不同之处2.2.2 V3版本的运行流程 3、安装和配置仓库、一些附带操作3.1 安装3.2 配置仓库3.3 常用命令3.4 添加helm的自动补齐 4、快速部署应用(weave应用)5、 自行创建Chart5.1 Chart目录内容解析5.2 简单安装部…

codeforces (C++ Haunted House)

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、由题目可知&#xff0c;他想让我们判断交换相邻字符位置后将二进制转为十进制后&#xff0c;能否整除2的次方。能整除即输出需要交换的次数&#xff0c;不能则输出-1。&#xff08;例&#xff1a;输入3和010这组数据就…

WebDAV之π-Disk派盘 +Polaris Office

推荐一款可以实现在Windows桌面PC,Mac,Android设备和iOS设备上同步的移动办公软件,还支持通过WebDAV添加葫芦儿派盘。Polaris Office是一款功能全面的办公自动化套件,软件集成了Word、Excel、幻灯片(PPT)、ODT等文档格式,并且可以完美兼容任何Microsoft Office,PDF,TXT或…

html web前端 登录,短信验证码登录

html web前端 登录&#xff0c;短信验证码登录 1&#xff0c;手机号码格式校验 2&#xff0c;按钮点击60秒倒计时&#xff0c;按钮限制点击 3&#xff0c;验证码/或密码长度校验&#xff08;被注释&#xff0c;公司发的验证码长度不一致&#xff0c;不一定是6位&#xff09; 4…

虹科培训 | 虹科携手PLCopen开展IEC 61131-3国际工程师培训

文章来源&#xff1a;虹科工业控制 阅读原文&#xff1a;https://mp.weixin.qq.com/s/MLYhBWiWx7qQSApx_3xhmA &#xff08;一&#xff09;课程背景 什么是IEC 61131-3&#xff1f; IEC 61131-3 是工业自动化行业唯一得到大量应用的组态编程语言国际标准&#xff1b;主导制定…

xcode15一直显示正在连接iOS17真机问题解决

前言 更新xcode15之后&#xff0c;出现了各种报错问题&#xff0c;可谓是一路打怪啊&#xff0c;解决一个报错问题又来一个。没想到到了最后还能出现一个一直显示正在连接iOS17真机的问题 一直显示正在连接iOS17真机的问题 问题截图如下&#xff1a; 解决方法 1. 打开De…