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


    1.1静态页面搭建

    1. <script setup lang="ts">
    2. import Breadcrumb from './breadcrumb/index.vue'
    3. import Setting from './setting/index.vue'
    4. script>
    5. <script lang="ts">
    6. export default {
    7. name: 'Tabbar',
    8. }
    9. script>
    10. <style scoped lang="scss">
    11. .tabbar {
    12. width: 100%;
    13. height: 100%;
    14. display: flex;
    15. justify-content: space-between;
    16. // background-image: linear-gradient(to right, rgb(232, 223, 223), rgb(201, 178, 178), rgb(197, 165, 165));
    17. .tabbar_left {
    18. display: flex;
    19. align-items: center;
    20. margin-left: 20px;
    21. }
    22. .tabbar_right {
    23. display: flex;
    24. align-items: center;
    25. }
    26. }
    27. style>

    面包屑

    1. <script setup lang="ts">
    2. import { useRoute } from 'vue-router'
    3. // import useLayOutSettingStore from '@/store/moudles/setting'
    4. // //获取layout配置相关的仓库
    5. // const LayOutSettingStore = useLayOutSettingStore()
    6. //获取路由对象
    7. const $route = useRoute()
    8. console.log($route.matched, '111')
    9. //点击图标的方法
    10. const changeIcon = () => {
    11. //图标进行切换
    12. LayOutSettingStore.fold = !LayOutSettingStore.fold
    13. }
    14. script>
    15. <script lang="ts">
    16. export default {
    17. name: 'Breadcrumb'
    18. }
    19. script>
    20. <style scoped>style>

    设置

    1. <script setup lang="ts">
    2. import { ref } from 'vue'
    3. // import { useRouter, useRoute } from 'vue-router'
    4. //获取用户相关的小仓库
    5. import useUserStore from '@/store/modules/user'
    6. //获取骨架的小仓库
    7. // import useLayOutSettingStore from '@/store/modules/setting'
    8. // const layoutSettingStore = useLayOutSettingStore()
    9. const userStore = useUserStore()
    10. //获取路由器对象
    11. // let $router = useRouter()
    12. //获取路由对向
    13. // let $route = useRoute()
    14. //收集开关的数据
    15. const dark = ref(false)
    16. //刷新按钮点击回调
    17. const updateRefsh = () => {
    18. layoutSettingStore.refsh = !layoutSettingStore.refsh
    19. }
    20. //全屏按钮点击的回调
    21. const fullScreen = () => {
    22. //DOM对象的一个属性:可以用来判断当前是不是全屏模式[全屏:true,不是全屏:false]
    23. const full = document.fullscreenElement
    24. //切换为全屏模式
    25. if (!full) {
    26. //文档根节点的方法requestFullscreen,实现全屏模式
    27. document.documentElement.requestFullscreen()
    28. } else {
    29. //变为不是全屏模式->退出全屏模式
    30. document.exitFullscreen()
    31. }
    32. }
    33. //退出登录点击回调
    34. const logout = async () => {
    35. //第一件事情:需要向服务器发请求[退出登录接口]******
    36. //第二件事情:仓库当中关于用于相关的数据清空[token|username|avatar]
    37. //第三件事情:跳转到登录页面
    38. //跳转到登录页面
    39. }
    40. //颜色组件组件的数据
    41. const color = ref('rgba(255, 69, 0, 0.68)')
    42. const predefineColors = ref([
    43. '#ff4500',
    44. '#ff8c00',
    45. '#ffd700',
    46. '#90ee90',
    47. '#00ced1',
    48. '#1e90ff',
    49. '#c71585',
    50. 'rgba(255, 69, 0, 0.68)',
    51. 'rgb(255, 120, 0)',
    52. 'hsv(51, 100, 98)',
    53. 'hsva(120, 40, 94, 0.5)',
    54. 'hsl(181, 100%, 37%)',
    55. 'hsla(209, 100%, 56%, 0.73)',
    56. '#c7158577'
    57. ])
    58. //switch开关的chang事件进行暗黑模式的切换
    59. const changeDark = () => {
    60. //获取HTML根节点
    61. const html = document.documentElement
    62. //判断HTML标签是否有类名dark
    63. dark.value ? (html.className = 'dark') : (html.className = '')
    64. }
    65. //主题颜色的设置
    66. const setColor = () => {
    67. //通知js修改根节点的样式对象的属性与属性值
    68. const html = document.documentElement
    69. html.style.setProperty('--el-color-primary', color.value)
    70. }
    71. script>
    72. <script lang="ts">
    73. export default {
    74. name: 'Setting'
    75. }
    76. script>
    77. <style scoped>style>

    1.2菜单折叠效果实现

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

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

    1. <script setup lang="ts">
    2. import Menu from './components/menu/index.vue'
    3. import Logo from './components/logo/index.vue'
    4. import Tabbar from './components/tabbar/index.vue'
    5. //获取用户相关的小仓库
    6. import useUserStore from '@/store/moudules/user'
    7. let userStore = useUserStore()
    8. // 獲取路有對象
    9. import { useRoute } from 'vue-router'
    10. import useLayOutSettingStore from '@/store/moudules/setting'
    11. //获取layout配置仓库
    12. let LayOutSettingStore = useLayOutSettingStore()
    13. //获取路由器
    14. let $route = useRoute()
    15. console.log($route.path)
    16. script>
    17. <script lang="ts">
    18. export default {
    19. name: 'Layout',
    20. }
    21. script>
    22. <style scoped lang="scss">
    23. .layout_container {
    24. width: 100%;
    25. height: 100vh;
    26. .layout_slider {
    27. color: white;
    28. width: $base-menu-width;
    29. height: 100vh;
    30. background: $base-menu-background;
    31. transition: all 0.3s;
    32. .scrollbar {
    33. width: 100%;
    34. height: calc(100vh - $base-menu-logo-height);
    35. .el-menu {
    36. border-right: none;
    37. }
    38. }
    39. }
    40. .layout_tabbar {
    41. position: fixed;
    42. width: calc(100% - $base-menu-width);
    43. height: $base-tabbar-height;
    44. top: 0px;
    45. left: $base-menu-width;
    46. transition: all 0.3s;
    47. &.fold {
    48. width: calc(100vw - $base-menu-min-width);
    49. left: $base-menu-min-width;
    50. background-color: #fff;
    51. }
    52. }
    53. .layout_main {
    54. transition: all 0.3s;
    55. position: absolute;
    56. width: calc(100% - $base-menu-width);
    57. height: calc(100vh - $base-tabbar-height);
    58. left: $base-menu-width;
    59. top: $base-tabbar-height;
    60. padding: 20px;
    61. overflow: auto;
    62. background-color: yellowgreen;
    63. &.fold {
    64. width: calc(100vw - $base-menu-min-width);
    65. left: $base-menu-min-width;
    66. }
    67. }
    68. }
    69. style>

    1.3面包屑的实现

    1. <script setup lang="ts">
    2. import { useRoute, useRouter } from 'vue-router'
    3. import useLayOutSettingStore from '@/store/moudules/setting'
    4. //获取layout配置相关的仓库
    5. let LayOutSettingStore = useLayOutSettingStore()
    6. //获取路由对象
    7. let $route = useRoute()
    8. console.log($route)
    9. console.log($route.matched, '111')
    10. let $router = useRouter()
    11. console.log($router, '111')
    12. //点击图标的方法
    13. const changeIcon = () => {
    14. //图标进行切换
    15. LayOutSettingStore.fold = !LayOutSettingStore.fold
    16. }
    17. script>
    18. <script lang="ts">
    19. export default {
    20. name: 'Breadcrumb',
    21. }
    22. script>
    23. <style scoped>style>

    1.4刷新业务的实现

    设置一个全局变量

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

    1. <script setup lang="ts">
    2. import { watch, ref, nextTick } from 'vue'
    3. import useLayOutSettingStore from '@/store/moudules/setting'
    4. let layOutSettingStore = useLayOutSettingStore()
    5. //控制当前组件是否销毁重建
    6. let flag = ref(true)
    7. //监听仓库内部数据是否发生变化,如果发生变化,说明用户点击过刷新按钮
    8. watch(
    9. () => layOutSettingStore.refsh,
    10. () => {
    11. //点击刷新按钮:路由组件销毁
    12. flag.value = false
    13. nextTick(() => {
    14. flag.value = true
    15. })
    16. },
    17. )
    18. script>
    19. <script lang="ts">
    20. export default {
    21. // eslint-disable-next-line vue/no-reserved-component-names
    22. name: 'Main',
    23. }
    24. script>
    25. <style scoped>
    26. .fade-enter-from {
    27. opacity: 0;
    28. transform: scale(0);
    29. }
    30. .fade-enter-active {
    31. transition: all 0.3s;
    32. }
    33. .fade-enter-to {
    34. opacity: 1;
    35. transform: scale(1);
    36. }
    37. style>

    1.5全屏功能的实现

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

    1.6获取用户信息

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

    1. import axios from 'axios'
    2. import { ElMessage } from 'element-plus'
    3. //引入用户相关的仓库
    4. import useUserStore from '@/store/modules/user'
    5. //创建axios实例
    6. const request = axios.create({
    7. baseURL: import.meta.env.VITE_APP_BASE_URL,
    8. timeout: 5000
    9. })
    10. //请求拦截器
    11. request.interceptors.request.use((config) => {
    12. //获取用户相关的小仓库:获取仓库内部token,登录成功以后携带给服务器
    13. const userStore = useUserStore()
    14. if (userStore.token) {
    15. config.headers.token = userStore.token
    16. }
    17. //config配置对象,headers属性请求头,经常给服务器端携带公共参数
    18. //返回配置对象
    19. return config
    20. })
    21. //响应拦截器
    22. request.interceptors.response.use(
    23. (response) => {
    24. return response.data
    25. },
    26. (error) => {
    27. //处理网络错误
    28. let msg = ''
    29. const status = error.response.status
    30. switch (status) {
    31. case 401:
    32. msg = 'token过期'
    33. break
    34. case 403:
    35. msg = '无权访问'
    36. break
    37. case 404:
    38. msg = '请求地址错误'
    39. break
    40. case 500:
    41. msg = '服务器出现问题'
    42. break
    43. default:
    44. msg = '无网络'
    45. }
    46. ElMessage({
    47. type: 'error',
    48. message: msg
    49. })
    50. return Promise.reject(error)
    51. }
    52. )
    53. export default request

    1.7退出登录业务

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

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

  • 相关阅读:
    PHP面试题大全
    React原理揭秘--setState() 的说明,JSX 语法的转化过程,组件更新机制,组件性能优化,虚拟 DOM 和 Diff 算法
    Web框架开发-Django简介
    利用 Gem5 模拟器创建一个简单的配置脚本——翻译自官网
    HUAWEI永远滴神、华为顶级网络专家总结出了这份网络协议开源手册
    腾讯云GPU云服务器使用Docker 安装 TensorFlow 并设置 GPU/CPU 支持!
    MFC Windows 程序设计[260]之多种控件展示(附源码)
    得不到你的心,就用“分布式锁”锁住你的人
    js遍历数组(用forEach()方法)
    Java实现二叉树的三种遍历方式
  • 原文地址:https://blog.csdn.net/m0_52704461/article/details/133956447