feat:增加移动端布局
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite --host 0.0.0.0",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 481 KiB |
37
src/layout/components/Mobile/MobileDrawer.vue
Normal file
37
src/layout/components/Mobile/MobileDrawer.vue
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer v-model="appStore.drawerVisible" direction="ltr" size="250px" :with-header="false">
|
||||||
|
<div class="drawer-content">
|
||||||
|
<div class="drawer-user">
|
||||||
|
<el-avatar :src="getAssetsImageFile('avatar.jpg')"/>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="title">{{ appStore.blogTitle }}</div>
|
||||||
|
<div class="sub-title">{{ appStore.blogSubTitle }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-menu router @select="appStore.drawerVisible = false">
|
||||||
|
<el-menu-item index="/overview">
|
||||||
|
<i class="fa fa-fw fa-home" />
|
||||||
|
<span>首页</span>
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
|
<el-menu-item index="/category">
|
||||||
|
<i class="fa fa-fw fa-th" />
|
||||||
|
<span>分类</span>
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
|
<el-menu-item index="/archive">
|
||||||
|
<i class="fa fa-fw fa-archive" />
|
||||||
|
<span class="menu-title">归档</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useAppStore } from '@/store/app'
|
||||||
|
import { getAssetsImageFile } from '@/utils'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
</script>
|
||||||
17
src/layout/components/Mobile/MobileHeader.vue
Normal file
17
src/layout/components/Mobile/MobileHeader.vue
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mobile-header">
|
||||||
|
<el-image :src="getAssetsImageFile('logo.png')" class="mobile-logo"/>
|
||||||
|
<div class="mobile-title">{{ appStore.title }}</div>
|
||||||
|
<el-button type="primary" text @click="appStore.drawerVisible = true">
|
||||||
|
<el-icon size="24"><Menu /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Menu } from '@element-plus/icons-vue'
|
||||||
|
import { useAppStore } from '@/store/app'
|
||||||
|
import { getAssetsImageFile } from '@/utils'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
</script>
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="title-container">
|
<div class="title-container">
|
||||||
<span class="title">{{ blogTitleInfo.title }}</span>
|
<span class="title">{{ appStore.blogTitle }}</span>
|
||||||
<span class="sub-title">{{ blogTitleInfo.subTitle }}</span>
|
<span class="sub-title">{{ appStore.blogSubTitle }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
import { useAppStore } from '@/store/app'
|
||||||
|
const appStore = useAppStore()
|
||||||
const blogTitleInfo = reactive({
|
|
||||||
title: 'NJCxx0822',
|
|
||||||
subTitle: '不要因为别人5%的负面评价而否定自己100%的努力。'
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import { Ribbon } from '@/utils/blog/ribbon'
|
|||||||
import { onMounted, onUnmounted } from 'vue'
|
import { onMounted, onUnmounted } from 'vue'
|
||||||
import { useBlogStore } from '@/store/blog.ts'
|
import { useBlogStore } from '@/store/blog.ts'
|
||||||
import { useAppStore } from '@/store/app.ts'
|
import { useAppStore } from '@/store/app.ts'
|
||||||
|
import { isMobile } from 'vue3-common/utils/layoutUtil'
|
||||||
|
|
||||||
const ribbon = new Ribbon()
|
const ribbon = new Ribbon()
|
||||||
const blogStore = useBlogStore()
|
const blogStore = useBlogStore()
|
||||||
@@ -62,10 +63,12 @@ const handleClick = (event) => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
document.addEventListener('scroll', () => {
|
document.addEventListener('scroll', () => {
|
||||||
const progressBar = document.getElementById('blog_progress') as HTMLProgressElement
|
if (!isMobile()) {
|
||||||
progressBar.max = document.documentElement.scrollHeight - window.innerHeight
|
const progressBar = document.getElementById('blog_progress') as HTMLProgressElement
|
||||||
progressBar.value = window.scrollY
|
progressBar.max = document.documentElement.scrollHeight - window.innerHeight
|
||||||
blogStore.progressValue = `${(progressBar.value / progressBar.max * 100).toFixed(0)}%`
|
progressBar.value = window.scrollY
|
||||||
|
blogStore.progressValue = `${(progressBar.value / progressBar.max * 100).toFixed(0)}%`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener('click', handleClick)
|
document.addEventListener('click', handleClick)
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="blog-container" id="blog-container">
|
<section v-if="appStore.isMobile" class="mobile-layout">
|
||||||
|
<mobile-header />
|
||||||
|
<router-view/>
|
||||||
|
|
||||||
|
<mobile-drawer />
|
||||||
|
|
||||||
|
<footer-bar />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section v-else class="blog-container" id="blog-container">
|
||||||
<tools />
|
<tools />
|
||||||
|
|
||||||
<sidebar />
|
<sidebar />
|
||||||
@@ -13,9 +22,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import MobileHeader from '@/layout/components/Mobile/MobileHeader.vue'
|
||||||
|
import MobileDrawer from '@/layout/components/Mobile/MobileDrawer.vue'
|
||||||
import Tools from '@/layout/components/Tools/index.vue'
|
import Tools from '@/layout/components/Tools/index.vue'
|
||||||
import Sidebar from '@/layout/components/Sidebar/index.vue'
|
import Sidebar from '@/layout/components/Sidebar/index.vue'
|
||||||
import FooterBar from '@/layout/components/FooterBar/index.vue'
|
import FooterBar from '@/layout/components/FooterBar/index.vue'
|
||||||
|
import { onMounted, onUnmounted } from 'vue'
|
||||||
|
import { useAppStore } from '@/store/app'
|
||||||
|
import { isMobile } from 'vue3-common/utils/layoutUtil'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
const checkScreen = () => {
|
||||||
|
appStore.isMobile = isMobile()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
checkScreen()
|
||||||
|
window.addEventListener('resize', checkScreen)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', checkScreen)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import { useDark, useToggle } from '@vueuse/core'
|
|||||||
export const useAppStore = defineStore('ipp', {
|
export const useAppStore = defineStore('ipp', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
isDark: false,
|
isDark: false,
|
||||||
|
isMobile: false,
|
||||||
|
drawerVisible: false,
|
||||||
|
title: '拾光记',
|
||||||
|
blogTitle: 'NJCxx0822',
|
||||||
|
blogSubTitle: '不要因为别人5%的负面评价而否定自己100%的努力。',
|
||||||
version: 'v1.0.0.2025042901'
|
version: 'v1.0.0.2025042901'
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
@@ -36,24 +36,95 @@
|
|||||||
0 3px 1px -2px rgba(0,0,0,0.06),
|
0 3px 1px -2px rgba(0,0,0,0.06),
|
||||||
0 1px 5px 0 rgba(0,0,0,0.12),
|
0 1px 5px 0 rgba(0,0,0,0.12),
|
||||||
0 -1px 0.5px 0 rgba(0,0,0,0.09);
|
0 -1px 0.5px 0 rgba(0,0,0,0.09);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.module-title {
|
.module-title {
|
||||||
background-color: blog.$theme-color;
|
background-color: blog.$theme-color;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 2px solid blog.$theme-color;
|
border: 2px solid blog.$theme-color;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: blog.$large-font-size;
|
font-size: blog.$large-font-size;
|
||||||
font-family: "华文楷体", serif;
|
}
|
||||||
|
|
||||||
|
.card-item {
|
||||||
|
background-color: var(--color-card-bg);
|
||||||
|
border: 1px solid var(--color-border-bg);
|
||||||
|
border-radius: blog.$border-radius;
|
||||||
|
// box-shadow: 3px 3px 3px #CFCFCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-layout {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
.mobile-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.mobile-logo {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-title {
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-content {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-user {
|
||||||
|
padding: 10px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 50px 1fr;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
border-bottom: 1px solid gray;
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
font-size: smaller;
|
||||||
|
color: #666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-item {
|
.el-menu {
|
||||||
background-color: var(--color-card-bg);
|
flex: 1;
|
||||||
border: 1px solid var(--color-border-bg);
|
border: none;
|
||||||
border-radius: blog.$border-radius;
|
|
||||||
// box-shadow: 3px 3px 3px #CFCFCF;
|
.el-menu-item {
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user