后台管理系统开发(页面布局 前端篇)

71 阅读1分钟

实现效果

image.png

image.png

image.png

image.png

image.png

响应布局

JS 层面响应

使用 vueuse 提供的 hooks 简单封装 useBreakpoints

import { breakpointsTailwind } from '@vueuse/core';

export const useLayout = () => {
  const breakpoints = useBreakpoints(breakpointsTailwind);

  // 手机
  const tablet = breakpoints.smaller('md');

  // 桌面
  const desktop = breakpoints.greater('md');

  return {
    isTablet: tablet,
    isDesktop: desktop,
  };
};

CS 层面响应

使用 unocss lg: sm: 控制 padding margin ... 响应样式

<div class="p-1 lg:px-4">
 ...
</div>

默认布局[layouts/default.vue]

<!--
 * @FileDescription: 默认布局
 * @Author: tuuuuuun
 * @Date: 2024/1/26 15:24
-->
<script lang="ts" setup>
  import DefaultPageHeader from './components/DefaultPageHeader.vue';
  import DefaultHeader from './components/DefaultHeader.vue';
  import DefaultFooter from './components/DefaultFooter.vue';
  import DefaultDynamicSide from '~/layouts/components/DefaultDynamicSide.vue';
</script>

<template>
  <a-layout class="default-layouts">
    <!--  侧边栏    -->
    <DefaultDynamicSide class="default-side" />

    <!--  页面主体内容    -->
    <a-layout-content class="default-content">
      <!-- 页面头部   -->
      <DefaultHeader class="default-header" />

      <!--    页面主体头部    -->
      <DefaultPageHeader class="default-page-header" />

      <!--    页面主体内容    -->
      <div class="default-main">
        <div class="default-main-content">
          <slot />
        </div>

        <DefaultFooter />
      </div>
    </a-layout-content>
  </a-layout>
</template>

<style lang="scss" scoped>
  .default-layouts {
    background: var(--color-bg-2);
    color: var(--color-text-1);
    @apply h-screen overflow-hidden;

    .default-content {
      @apply overflow-hidden h-screen flex flex-col;
      background: var(--color-bg-1);

      // 头部样式
      .default-header {
        height: 4rem;
        @apply drop-shadow-sm;
        background-color: var(--color-menu-light-bg);
      }

      .default-page-header {
        background-color: var(--color-menu-light-bg);
      }

      // 主要内容
      .default-main {
        @apply flex-1 flex-shrink flex flex-col;
        @apply w-full h-0 overflow-y-auto;
        @apply p-2.5 lg:p-4  pb-2 rounded;
        background-color: var(--color-neutral-1);

        .default-main-content {
          @apply flex-1 mr-4 lg:mr-6;
        }

        // 底部
        .default-footer {
          @apply w-full text-center pt-6;
        }
      }
    }

    .default-side {
      background: var(--color-bg-1);
    }
  }
</style>

侧边栏

<!--
 * @FileDescription: 默认布局-侧边栏
 * @Author: tuuuuuun
 * @Date: 2024/1/26 15:24
-->
<script lang="ts" setup>
  import DefaultSide from '~/layouts/components/DefaultSide.vue';

  // 主要实现
  const { isTablet } = useLayout();
  
  // 自定义的全局
  const globalState = useGlobalState();
  const { sideCollapsed, menuSideWidth } = storeToRefs(globalState);
</script>

<template>
  <a-drawer
    v-if="isTablet"
    :footer="false"
    :header="false"
    :placement="'left'"
    :visible="!sideCollapsed"
    class="dynamic-side"
    unmount-on-close
    @cancel="globalState.onToggleCollapse"
  >
    // 菜单
    <DefaultSide :collapsed="false" />
  </a-drawer>

  <a-layout-sider v-else :collapsed="sideCollapsed" :width="menuSideWidth">
    // 菜单
    <DefaultSide :collapsed="sideCollapsed" />
  </a-layout-sider>
</template>

<style scoped></style>