mirror of
https://github.com/chansee97/nova-admin.git
synced 2025-09-03 21:29:58 +08:00
feat: adapted mobile screen
This commit is contained in:
parent
1b4639d5d8
commit
3144acbc39
6
pnpm-workspace.yaml
Normal file
6
pnpm-workspace.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
ignoredBuiltDependencies:
|
||||
- '@parcel/watcher'
|
||||
- esbuild
|
||||
- simple-git-hooks
|
||||
- vue-demi
|
||||
- unrs-resolver
|
38
src/layouts/components/common/MobileDrawer.vue
Normal file
38
src/layouts/components/common/MobileDrawer.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import Search from '../header/Search.vue'
|
||||
import Notices from '../header/Notices.vue'
|
||||
import UserCenter from '../header/UserCenter.vue'
|
||||
import Setting from './Setting.vue'
|
||||
|
||||
const showDrawer = defineModel<boolean>('show', { default: false })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-drawer
|
||||
v-model:show="showDrawer"
|
||||
:width="280"
|
||||
placement="right"
|
||||
:mask-closable="true"
|
||||
:close-on-esc="true"
|
||||
>
|
||||
<n-drawer-content :native-scrollbar="false" :body-content-style="{ padding: '0' }">
|
||||
<template #header>
|
||||
<div class="flex">
|
||||
<UserCenter />
|
||||
<div class="ml-auto" />
|
||||
<Search />
|
||||
<Notices />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<slot />
|
||||
|
||||
<template #footer>
|
||||
<DarkModeSwitch />
|
||||
<LangsSwitch />
|
||||
<div class="ml-auto" />
|
||||
<Setting />
|
||||
</template>
|
||||
</n-drawer-content>
|
||||
</n-drawer>
|
||||
</template>
|
@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { useBoolean } from '@/hooks'
|
||||
import { useRouteStore } from '@/store'
|
||||
import { useAppStore, useRouteStore } from '@/store'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const routeStore = useRouteStore()
|
||||
|
||||
// 搜索值
|
||||
@ -143,13 +144,14 @@ function handleMouseEnter(index: number) {
|
||||
|
||||
<template>
|
||||
<CommonWrapper @click="openModal">
|
||||
<icon-park-outline-search /><n-tag round size="small" class="font-mono cursor-pointer">
|
||||
<icon-park-outline-search />
|
||||
<n-tag v-if="!appStore.isMobile" round size="small" class="font-mono cursor-pointer">
|
||||
CtrlK
|
||||
</n-tag>
|
||||
</CommonWrapper>
|
||||
<n-modal
|
||||
v-model:show="showModal"
|
||||
class="w-560px fixed top-60px inset-x-0"
|
||||
class="w-560px fixed top-60px inset-x-0 max-w-full"
|
||||
size="small"
|
||||
preset="card"
|
||||
:segmented="{
|
||||
|
@ -2,6 +2,7 @@ import BackTop from './common/BackTop.vue'
|
||||
import Setting from './common/Setting.vue'
|
||||
import SettingDrawer from './common/SettingDrawer.vue'
|
||||
import Logo from './common/Logo.vue'
|
||||
import MobileDrawer from './common/MobileDrawer.vue'
|
||||
|
||||
import Breadcrumb from './header/Breadcrumb.vue'
|
||||
import CollapaseButton from './header/CollapaseButton.vue'
|
||||
@ -18,6 +19,7 @@ export {
|
||||
CollapaseButton,
|
||||
FullScreen,
|
||||
Logo,
|
||||
MobileDrawer,
|
||||
Notices,
|
||||
Search,
|
||||
Setting,
|
||||
|
@ -20,7 +20,7 @@ function exitFullContent() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-tooltip placement="bottom" trigger="hover">
|
||||
<n-tooltip v-if="!appStore.isMobile" placement="bottom" trigger="hover">
|
||||
<template #trigger>
|
||||
<CommonWrapper @click="enterFullContent">
|
||||
<icon-park-outline-full-screen-one />
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
CollapaseButton,
|
||||
FullScreen,
|
||||
Logo,
|
||||
MobileDrawer,
|
||||
Notices,
|
||||
Search,
|
||||
Setting,
|
||||
@ -14,12 +15,12 @@ import {
|
||||
UserCenter,
|
||||
} from './components'
|
||||
import Content from './Content.vue'
|
||||
|
||||
import { ProLayout, useLayoutMenu } from 'pro-naive-ui'
|
||||
|
||||
const route = useRoute()
|
||||
const appStore = useAppStore()
|
||||
const routeStore = useRouteStore()
|
||||
|
||||
const { layoutMode } = storeToRefs(useAppStore())
|
||||
|
||||
const {
|
||||
@ -31,16 +32,19 @@ const {
|
||||
menus: routeStore.menus,
|
||||
})
|
||||
|
||||
watch(() => route.path, (value) => {
|
||||
watch(() => route.path, (value: string) => {
|
||||
activeKey.value = value
|
||||
}, { immediate: true })
|
||||
|
||||
// 移动端抽屉控制
|
||||
const showMobileDrawer = ref(false)
|
||||
|
||||
const sidebarWidth = ref(240)
|
||||
const sidebarCollapsedWidth = ref(64)
|
||||
|
||||
const hasHorizontalMenu = computed(() => ['horizontal', 'mixed-two-column', 'mixed-sidebar'].includes(layoutMode.value))
|
||||
|
||||
const hidenCollapaseButton = computed(() => ['horizontal'].includes(layoutMode.value))
|
||||
const hidenCollapaseButton = computed(() => ['horizontal'].includes(layoutMode.value) || appStore.isMobile)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -48,7 +52,8 @@ const hidenCollapaseButton = computed(() => ['horizontal'].includes(layoutMode.v
|
||||
<ProLayout
|
||||
v-model:collapsed="appStore.collapsed"
|
||||
:mode="layoutMode"
|
||||
:show-logo="appStore.showLogo"
|
||||
:is-mobile="appStore.isMobile"
|
||||
:show-logo="appStore.showLogo && !appStore.isMobile"
|
||||
:show-footer="appStore.showFooter"
|
||||
:show-tabbar="appStore.showTabs"
|
||||
nav-fixed
|
||||
@ -79,6 +84,22 @@ const hidenCollapaseButton = computed(() => ['horizontal'].includes(layoutMode.v
|
||||
|
||||
<template #nav-right>
|
||||
<div class="h-full flex-y-center gap-1 p-x-xl">
|
||||
<!-- 移动端:只显示菜单按钮 -->
|
||||
<template v-if="appStore.isMobile">
|
||||
<n-button
|
||||
quaternary
|
||||
@click="showMobileDrawer = true"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon size="18">
|
||||
<icon-park-outline-hamburger-button />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</template>
|
||||
|
||||
<!-- 桌面端:显示完整功能组件 -->
|
||||
<template v-else>
|
||||
<Search />
|
||||
<Notices />
|
||||
<FullScreen />
|
||||
@ -86,6 +107,7 @@ const hidenCollapaseButton = computed(() => ['horizontal'].includes(layoutMode.v
|
||||
<LangsSwitch />
|
||||
<Setting />
|
||||
<UserCenter />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -111,5 +133,10 @@ const hidenCollapaseButton = computed(() => ['horizontal'].includes(layoutMode.v
|
||||
<Content />
|
||||
<BackTop />
|
||||
<SettingDrawer />
|
||||
|
||||
<!-- 移动端功能抽屉 -->
|
||||
<MobileDrawer v-model:show="showMobileDrawer">
|
||||
<n-menu v-bind="layout.verticalMenuProps" />
|
||||
</MobileDrawer>
|
||||
</ProLayout>
|
||||
</template>
|
||||
|
@ -17,6 +17,8 @@ const { system, store } = useColorMode({
|
||||
emitAuto: true,
|
||||
})
|
||||
|
||||
const isMobile = useMediaQuery('(max-width: 700px)')
|
||||
|
||||
export const useAppStore = defineStore('app-store', {
|
||||
state: () => {
|
||||
return {
|
||||
@ -50,6 +52,9 @@ export const useAppStore = defineStore('app-store', {
|
||||
fullScreen() {
|
||||
return isFullscreen.value
|
||||
},
|
||||
isMobile() {
|
||||
return isMobile.value
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
// 重置所有设置
|
||||
|
@ -1,8 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/store'
|
||||
import Chart from './components/chart.vue'
|
||||
import Chart2 from './components/chart2.vue'
|
||||
import Chart3 from './components/chart3.vue'
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
id: 0,
|
||||
@ -32,12 +35,15 @@ const tableData = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<n-grid
|
||||
:x-gap="16"
|
||||
:y-gap="16"
|
||||
:cols="12"
|
||||
item-responsive
|
||||
responsive="screen"
|
||||
>
|
||||
<n-gi :span="6">
|
||||
<!-- 统计卡片 - 移动端每行2个,桌面端每行4个 -->
|
||||
<n-gi span="6 m:3">
|
||||
<n-card>
|
||||
<n-space
|
||||
justify="space-between"
|
||||
@ -69,7 +75,7 @@ const tableData = [
|
||||
</template>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="6 m:3">
|
||||
<n-card>
|
||||
<n-space
|
||||
justify="space-between"
|
||||
@ -101,7 +107,7 @@ const tableData = [
|
||||
</template>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="6 m:3">
|
||||
<n-card>
|
||||
<n-space
|
||||
justify="space-between"
|
||||
@ -133,7 +139,7 @@ const tableData = [
|
||||
</template>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="6 m:3">
|
||||
<n-card>
|
||||
<n-space
|
||||
justify="space-between"
|
||||
@ -165,7 +171,8 @@ const tableData = [
|
||||
</template>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="24">
|
||||
<!-- 图表区域 - 全宽显示 -->
|
||||
<n-gi :span="12">
|
||||
<n-card content-style="padding: 0;">
|
||||
<n-tabs
|
||||
type="line"
|
||||
@ -182,7 +189,9 @@ const tableData = [
|
||||
</n-tabs>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="8">
|
||||
|
||||
<!-- 访问来源 - 移动端全宽,桌面端1/3宽 -->
|
||||
<n-gi span="12 m:4">
|
||||
<n-card
|
||||
title="访问来源"
|
||||
:segmented="{
|
||||
@ -192,7 +201,9 @@ const tableData = [
|
||||
<Chart3 />
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="16">
|
||||
|
||||
<!-- 成交记录 - 移动端全宽,桌面端2/3宽 -->
|
||||
<n-gi span="12 m:8">
|
||||
<n-card
|
||||
title="成交记录"
|
||||
:segmented="{
|
||||
@ -210,6 +221,7 @@ const tableData = [
|
||||
<n-table
|
||||
:bordered="false"
|
||||
:single-line="false"
|
||||
:scroll-x="appStore.isMobile ? 600 : undefined"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -243,7 +255,4 @@ const tableData = [
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -9,21 +9,30 @@ const { userInfo } = useAuthStore()
|
||||
<n-grid
|
||||
:x-gap="16"
|
||||
:y-gap="16"
|
||||
:cols="3"
|
||||
item-responsive
|
||||
responsive="screen"
|
||||
>
|
||||
<n-gi :span="16">
|
||||
<!-- 左侧主要内容区 - 移动端全宽,桌面端2/3宽 -->
|
||||
<n-gi span="3 m:2">
|
||||
<n-space
|
||||
vertical
|
||||
:size="16"
|
||||
>
|
||||
<!-- 图表区域 -->
|
||||
<n-card style="--n-padding-left: 0;">
|
||||
<Chart />
|
||||
</n-card>
|
||||
<n-card>
|
||||
|
||||
<!-- 统计卡片区域 -->
|
||||
<n-grid
|
||||
:x-gap="8"
|
||||
:y-gap="8"
|
||||
:x-gap="16"
|
||||
:y-gap="16"
|
||||
:cols="4"
|
||||
item-responsive
|
||||
responsive="screen"
|
||||
>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="2 l:1">
|
||||
<n-card>
|
||||
<n-thing>
|
||||
<template #avatar>
|
||||
@ -41,7 +50,7 @@ const { userInfo } = useAuthStore()
|
||||
</n-thing>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="2 l:1">
|
||||
<n-card>
|
||||
<n-thing>
|
||||
<template #avatar>
|
||||
@ -59,7 +68,7 @@ const { userInfo } = useAuthStore()
|
||||
</n-thing>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="2 l:1">
|
||||
<n-card>
|
||||
<n-thing>
|
||||
<template #avatar>
|
||||
@ -77,7 +86,7 @@ const { userInfo } = useAuthStore()
|
||||
</n-thing>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="6">
|
||||
<n-gi span="2 l:1">
|
||||
<n-card>
|
||||
<n-thing>
|
||||
<template #avatar>
|
||||
@ -96,7 +105,6 @@ const { userInfo } = useAuthStore()
|
||||
</n-card>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</n-card>
|
||||
<n-card title="动态">
|
||||
<template #header-extra>
|
||||
<n-button
|
||||
@ -167,7 +175,9 @@ const { userInfo } = useAuthStore()
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-gi>
|
||||
<n-gi :span="8">
|
||||
|
||||
<!-- 右侧边栏 - 移动端全宽,桌面端1/3宽 -->
|
||||
<n-gi span="3 m:1">
|
||||
<n-space
|
||||
vertical
|
||||
:size="16"
|
||||
@ -226,11 +236,14 @@ const { userInfo } = useAuthStore()
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</n-card>
|
||||
<!-- 订单和待办统计 -->
|
||||
<n-grid
|
||||
:x-gap="8"
|
||||
:y-gap="8"
|
||||
:x-gap="16"
|
||||
:y-gap="16"
|
||||
:cols="2"
|
||||
>
|
||||
<n-gi :span="12">
|
||||
<!-- 移动端和桌面端都是每行2个 -->
|
||||
<n-gi :span="1">
|
||||
<n-card>
|
||||
<n-flex vertical align="center">
|
||||
<n-text depth="3">
|
||||
@ -245,7 +258,7 @@ const { userInfo } = useAuthStore()
|
||||
</n-flex>
|
||||
</n-card>
|
||||
</n-gi>
|
||||
<n-gi :span="12">
|
||||
<n-gi :span="1">
|
||||
<n-card>
|
||||
<n-flex vertical align="center">
|
||||
<n-text depth="3">
|
||||
|
@ -18,7 +18,7 @@ const appName = import.meta.env.VITE_APP_NAME
|
||||
<DarkModeSwitch />
|
||||
<LangsSwitch />
|
||||
</div>
|
||||
<n-el
|
||||
<div
|
||||
class="p-4xl h-full w-full sm:w-450px sm:h-unset"
|
||||
style="background: var(--card-color);box-shadow: var(--box-shadow-1);"
|
||||
>
|
||||
@ -36,7 +36,7 @@ const appName = import.meta.env.VITE_APP_NAME
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
</n-el>
|
||||
</div>
|
||||
|
||||
<div />
|
||||
</n-el>
|
||||
|
Loading…
x
Reference in New Issue
Block a user