Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
O
office-web-js
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
qinjianhui
office-web-js
Commits
b2d6e92b
Commit
b2d6e92b
authored
Jan 16, 2023
by
qinjianhui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 手机版 header 菜单
parent
b50cfdfc
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
408 additions
and
149 deletions
+408
-149
src/components/HeaderNav.vue
+159
-0
src/components/HeaderNavMobile.vue
+220
-0
src/components/HomePageHeader.vue
+10
-149
src/main.js
+6
-0
src/styles/icon.scss
+13
-0
No files found.
src/components/HeaderNav.vue
0 → 100644
View file @
b2d6e92b
<
template
>
<nav
class=
"header-nav"
>
<div
v-for=
"(n, i) in nav"
:key=
"i"
class=
"header-nav-item"
:class=
"
{ active: isRouteActive(n) }"
>
<template
v-if=
"n.children && n.children.length"
>
<span
class=
"header-nav-title"
>
{{
n
.
title
}}
</span>
<ul
class=
"header-nav-children"
>
<li
v-for=
"(nn, j) in n.children"
:key=
"j"
class=
"header-nav-child"
:class=
"
{ active: isRouteActive(nn) }"
>
<router-link
class=
"header-nav-title header-nav-link"
:to=
"nn.route"
>
{{
nn
.
title
}}
</router-link
>
</li>
</ul>
</
template
>
<router-link
v-else
class=
"header-nav-title header-nav-link"
:to=
"n.route"
>
{{ n.title }}
</router-link
>
</div>
</nav>
</template>
<
script
>
export
default
{
name
:
'HeaderNav'
,
props
:
{
nav
:
{
type
:
Array
,
required
:
true
,
},
},
methods
:
{
isRouteActive
(
nav
)
{
const
path
=
this
.
$route
.
path
if
(
nav
.
route
===
path
)
return
true
if
(
nav
.
children
?.
length
)
{
return
nav
.
children
.
some
((
e
)
=>
e
.
route
===
path
)
}
},
},
}
</
script
>
<
style
lang=
"scss"
>
.header-nav
{
display
:
flex
;
height
:
100%
;
}
@mixin
header-nav-item-active
(
$
x
)
{
&
::before
,
&
::after
{
content
:
''
;
display
:
block
;
width
:
50%
;
transform
:
scaleX
(
$
x
);
height
:
4px
;
background-color
:
var
(
--primary-color
);
position
:
absolute
;
top
:
0
;
transition
:
transform
0.3s
;
}
&
::before
{
left
:
0
;
transform-origin
:
100%
;
}
&
::after
{
right
:
0
;
transform-origin
:
0
;
}
&
:hover
{
&::before,
&::after
{
transform
:
scaleX
(
1
);
}
}
}
.header-nav-item
{
width
:
120px
;
height
:
100%
;
position
:
relative
;
&:hover
{
.header-nav-children
{
display
:
flex
;
}
}
&
.active
{
&
>
.header-nav-title
{
@include
header-nav-item-active(1);
color
:
var
(
--primary-color
);
}
}
&
>
.header-nav-title
{
@include
header-nav-item-active(0);
}
}
.header-nav-children
{
position
:
absolute
;
top
:
100%
;
left
:
0
;
width
:
100%
;
margin
:
0
;
padding
:
0
;
display
:
none
;
flex-direction
:
column
;
background-color
:
#000
;
color
:
#fff
;
}
.header-nav-child
{
width
:
100%
;
height
:
60px
;
margin
:
0
;
padding
:
0
;
list-style-type
:
none
;
&.active
{
color
:
var
(
--primary-color
);
}
}
.header-nav-title
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
width
:
100%
;
height
:
100%
;
&:hover
{
color
:
var
(
--primary-color
);
}
}
.header-nav-link
{
color
:
inherit
;
text-decoration
:
none
;
cursor
:
pointer
;
transition
:
0.3s
;
}
</
style
>
src/components/HeaderNavMobile.vue
0 → 100644
View file @
b2d6e92b
<
template
>
<div
class=
"header-nav-mobile"
>
<a
class=
"header-nav-mobile-trigger icon-menu"
href=
"javascript:;"
@
click=
"toggleShow"
></a>
<transition
name=
"header-nav-mobile"
>
<div
v-show=
"showing"
class=
"header-nav-mobile-overlay"
@
click=
"toggleShow"
>
<ul
class=
"header-nav-mobile-items"
@
click
.
stop
>
<li
v-for=
"(r, i) in nav"
:key=
"i"
class=
"header-nav-mobile-item"
:class=
"
{ active: isRouteActive(r) }"
>
<template
v-if=
"r.children && r.children.length"
>
<a
class=
"header-nav-mobile-link"
href=
"javascript:;"
@
click=
"toggleExpand(r)"
>
{{
r
.
title
}}
<span
class=
"expand-icon"
>
{{
expandMap
[
r
.
title
]
?
'-'
:
'+'
}}
</span></a
>
<ul
v-show=
"expandMap[r.title]"
class=
"header-nav-mobile-children"
>
<li
v-for=
"(rr, j) in r.children"
:key=
"j"
class=
"header-nav-mobile-child"
:class=
"
{ active: isRouteActive(rr) }"
>
<router-link
class=
"header-nav-mobile-link"
:to=
"rr.route"
@
click=
"toggleShow"
>
{{
rr
.
title
}}
</router-link
>
</li>
</ul>
</
template
>
<router-link
v-else
class=
"header-nav-mobile-link"
:to=
"r.route"
@
click=
"toggleShow"
>
{{ r.title }}
</router-link
>
</li>
</ul>
</div>
</transition>
</div>
</template>
<
script
>
export
default
{
name
:
'HeaderNavMobile'
,
props
:
{
nav
:
{
type
:
Array
,
required
:
true
,
},
},
data
()
{
return
{
showing
:
false
,
expandMap
:
{},
}
},
watch
:
{
nav
:
{
immediate
:
true
,
handler
()
{
this
.
buildExpandMap
()
},
},
$route
()
{
this
.
buildExpandMap
()
},
},
methods
:
{
toggleShow
()
{
this
.
showing
=
!
this
.
showing
},
toggleExpand
(
r
)
{
this
.
expandMap
[
r
.
title
]
=
!
this
.
expandMap
[
r
.
title
]
},
isRouteActive
(
nav
)
{
const
path
=
this
.
$route
.
path
if
(
nav
.
route
===
path
)
return
true
if
(
nav
.
children
?.
length
)
{
return
nav
.
children
.
some
((
e
)
=>
e
.
route
===
path
)
}
},
buildExpandMap
()
{
const
m
=
{}
this
.
nav
.
forEach
((
r
)
=>
{
if
(
r
.
children
?.
length
)
{
m
[
r
.
title
]
=
this
.
isRouteActive
(
r
)
}
})
this
.
expandMap
=
m
},
},
}
</
script
>
<
style
lang=
"scss"
>
.header-nav-mobile-trigger
{
display
:
block
;
width
:
25px
;
height
:
25px
;
}
.header-nav-mobile-enter-active
,
.header-nav-mobile-leave-active
{
transition
:
0.3s
;
}
.header-nav-mobile-enter
,
.header-nav-mobile-leave-to
{
transform
:
translateX
(
-300px
);
}
.header-nav-mobile-overlay
{
position
:
fixed
;
top
:
0
;
left
:
0
;
width
:
100vw
;
height
:
100vh
;
z-index
:
99999
;
}
.header-nav-mobile-items
{
box-sizing
:
border-box
;
width
:
300px
;
height
:
100%
;
background-color
:
#000
;
margin
:
0
;
padding
:
30px
20px
;
}
.header-nav-mobile-item
,
.header-nav-mobile-child
{
list-style-type
:
none
;
line-height
:
50px
;
letter-spacing
:
4px
;
&.active
>
.header-nav-mobile-link
{
color
:
var
(
--primary-color
);
}
}
.header-nav-mobile-item.active
{
.header-nav-mobile-link
{
position
:
relative
;
&::after
{
position
:
absolute
;
top
:
100%
;
left
:
0
;
content
:
''
;
display
:
block
;
width
:
80px
;
height
:
2px
;
background-color
:
var
(
--primary-color
);
}
}
}
.header-nav-mobile-item
{
font-size
:
16px
;
color
:
#fff
;
}
.header-nav-mobile-child
{
font-size
:
14px
;
color
:
#999
;
}
.header-nav-mobile-children
{
margin
:
0
;
padding
:
0
;
}
.header-nav-mobile-link
{
display
:
block
;
width
:
100%
;
height
:
100%
;
color
:
inherit
;
text-decoration
:
none
;
cursor
:
pointer
;
border-bottom
:
solid
1px
#2c2c2c
;
}
.header-nav-mobile-item
>
.header-nav-mobile-link
{
display
:
flex
;
.expand-icon
{
margin-left
:
auto
;
margin-right
:
20px
;
}
}
.header-nav-mobile-child
>
.header-nav-mobile-link
{
padding-left
:
10px
;
&::after
{
display
:
none
!important
;
}
}
</
style
>
src/components/HomePageHeader.vue
View file @
b2d6e92b
...
...
@@ -9,43 +9,17 @@
/>
</router-link>
</div>
<nav
class=
"header-nav"
>
<div
v-for=
"(n, i) in nav"
:key=
"i"
class=
"header-nav-item"
:class=
"
{ active: isRouteActive(n) }"
>
<template
v-if=
"n.children && n.children.length"
>
<span
class=
"header-nav-title"
>
{{
n
.
title
}}
</span>
<ul
class=
"header-nav-children"
>
<li
v-for=
"(nn, j) in n.children"
:key=
"j"
class=
"header-nav-child"
:class=
"
{ active: isRouteActive(nn) }"
>
<router-link
class=
"header-nav-title header-nav-link"
:to=
"nn.route"
>
{{
nn
.
title
}}
</router-link
>
</li>
</ul>
</
template
>
<router-link
v-else
class=
"header-nav-title header-nav-link"
:to=
"n.route"
>
{{ n.title }}
</router-link
>
</div>
</nav>
<HeaderNavMobile
v-if=
"$isMobile"
:nav=
"nav"
/>
<HeaderNav
v-else
:nav=
"nav"
/>
</header>
</
template
>
<
script
>
import
HeaderNav
from
'./HeaderNav.vue'
import
HeaderNavMobile
from
'./HeaderNavMobile.vue'
export
default
{
name
:
'HomePageHeader'
,
components
:
{
HeaderNav
,
HeaderNavMobile
},
data
()
{
return
{
nav
:
[
...
...
@@ -66,15 +40,6 @@ export default {
],
}
},
methods
:
{
isRouteActive
(
nav
)
{
const
path
=
this
.
$route
.
path
if
(
nav
.
route
===
path
)
return
true
if
(
nav
.
children
?.
length
)
{
return
nav
.
children
.
some
((
e
)
=>
e
.
route
===
path
)
}
},
},
}
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
@@ -111,118 +76,14 @@ export default {
height
:
80%
;
}
.header-nav
{
display
:
flex
;
height
:
100%
;
}
@mixin
header-nav-item-active
(
$
x
)
{
&
::before
,
&
::after
{
content
:
''
;
display
:
block
;
width
:
50%
;
transform
:
scaleX
(
$
x
);
height
:
4px
;
background-color
:
var
(
--primary-color
);
position
:
absolute
;
top
:
0
;
transition
:
transform
0.3s
;
}
&
::before
{
left
:
0
;
transform-origin
:
100%
;
}
&
::after
{
right
:
0
;
transform-origin
:
0
;
}
&
:hover
{
&::before,
&::after
{
transform
:
scaleX
(
1
);
}
}
}
.header-nav-item
{
width
:
120px
;
height
:
100%
;
position
:
relative
;
&:hover
{
.header-nav-children
{
display
:
flex
;
}
}
&
.active
{
&
>
.header-nav-title
{
@include
header-nav-item-active(1);
color
:
var
(
--primary-color
);
}
}
&
>
.header-nav-title
{
@include
header-nav-item-active(0);
}
}
.header-nav-children
{
.header-nav-mobile
{
position
:
absolute
;
top
:
100%
;
left
:
0
;
width
:
100%
;
margin
:
0
;
padding
:
0
;
display
:
none
;
flex-direction
:
column
;
background-color
:
#000
;
color
:
#fff
;
}
.header-nav-child
{
width
:
100%
;
height
:
60px
;
margin
:
0
;
padding
:
0
;
list-style-type
:
none
;
&.active
{
color
:
var
(
--primary-color
);
}
}
.header-nav-title
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
width
:
100%
;
height
:
100%
;
&:hover
{
color
:
var
(
--primary-color
);
}
}
.header-nav-link
{
color
:
inherit
;
text-decoration
:
none
;
cursor
:
pointer
;
transition
:
0.3s
;
left
:
20px
;
}
@media
screen
and
(
max-width
:
1000px
)
{
.home-page-header
{
justify-content
:
flex-start
;
padding-left
:
5%
;
}
.header-nav
{
display
:
none
;
.header-logo
{
margin-right
:
0
;
}
}
</
style
>
src/main.js
View file @
b2d6e92b
...
...
@@ -24,6 +24,12 @@ router.afterEach((to) => {
}
})
const
isMobile
=
()
=>
window
.
innerWidth
<=
1000
Vue
.
util
.
defineReactive
(
Vue
.
prototype
,
'$isMobile'
,
isMobile
())
window
.
addEventListener
(
'resize'
,
()
=>
{
Vue
.
prototype
.
$isMobile
=
isMobile
()
})
new
Vue
({
router
,
store
,
...
...
src/styles/icon.scss
View file @
b2d6e92b
...
...
@@ -33,4 +33,16 @@
.icon-thumb-gold-bg-gray
{
background-size
:
100%
;
background-image
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAABOCAYAAACOqiAdAAAAAXNSR0IArs4c6QAABTRJREFUeAHtm3lPG0cUwGdm18dibGNcc5Qj0Cq0TZ2mimhC2kbNF2hV9dPxPdI/qlaqlBApEVLUNqSlIkkDNYcDBd/37kxnnMyyIMD2Y21WeFYyb473dp5/vNmdy3hxcfE+UlfHBEjHFsqgSUCBAwaCAqfAAQkAzVTEKXBAAkAzFXEKHJAA0ExFnAIHJAA0UxGnwAEJAM1UxClwQAJAMxVxQHA60K5nZgQxNGuuTsZoOm7QslFBA5Ws/l5m3ZdMmYywnjlyrCFPgzNQxXe78tPCAMtHpd9htI9G6qmpKfPlzFP/vad5MlySdb2Unu6q89Wfv3BCc4IxaCFys/bgJsEUO8t7lfYsuDFrIx6m2WEJok6M8p4+mSrhcE6WCaizjb8nZL6X0rNddbqxNi1B1MhA8UHwh4cm0qgou1u9fydMD+IiHaG7MYSubYp0Ly9PRpyOTBKnb0YliLQ2vSmhibKsltiXdSFaDMl0L6UnwU2aL8YwsuzekNLntp1QnK9SjJh6xkk449a6/dwqkkg2j2NlWecV6bmIC6CqL0b3EhLQf/qVLZn2kvQcuGlzbRwxJv1i69rVHS8Bk75IB2X+wuWYuWF30wIZPijjcPXCnTrBAU+BG2CFIB9m2GO3tEe7qeDoKXC8m77PfXr3lsR0U5/zZDf1HLhxa2NKOCWunJbYq6Bg423Oe389E3HXG0/m+PwzLBFtaR/0fDYg225H2oPMdpRb6UyYr0ZGrc2RVnrOej7QJVGWHQrySbssr5Bw4V//RzuoOcGSpSfLAC2F+GQ/eaQWY1ZDgXpRixW2ycxeA/utI/UuZFwFF2N7Q2PW+sx5/GJIM//033pG24Am2vGjWvDUNk0+i8XL1pb+4T+r/vmXDeZzDaBnuqqA0MDBym+Bb5Z3yWRG5N24MLO0ycba1a+rP34p3tpu3FPcw9WIczpFkW5WSKjgLJNpg5bCBJnNtsVyUZbE93MkkXmtf3pkMi/1j8saHqyUSPR0uIySAVYOOee7hpWP3q79cmsp+N0jE+ltxvPxlg/zXQNXIpHcUvDbx4dNHaacy0Ji5eO5b2HtsLZ16oWeTInPWZpiyX2EbsU+qT35zGCl5ktHLH5eqz3++Fng7l9n2bZT56mu2o7D7epQPhxM8y6/ZHy/VCSxA2k3QTeuGKjkl3movLTgJBDRLVeCX/3BEG52z+Yzz3xtr/VJvU7lpQcngGRQvMSHJvYzMWru2tO6ToFJ/b4AJ75sEQ/l5ZfmS1cBmYbKvgHXwD57+kaQpUGBSbu+ASe/sFtSgQOSVOAUOCABoJmKOAUOSABopiJOgQMSAJqpiFPggASAZiriFDggAaBZ30ScxvceJCPr3dqczENk34AL0Yy9/WgSowaB5bTpC3AhVPZHaI4feX178fN29jliWdap7Atw1+uPknJXjQNi29rsm05BHdfv2i7X8YYuIi82ZT6vPrwRo7v2HsO+PrGVJ+c/4dk1cNzp0Hz11xsnARN1sjxBd0a5niHzbkhCGDasXDiEimHHIUVUR4Hqim9h1Y02ugZOp7XgCErZp49Oc1ZsFBvo8Jczp+l1VH7CdrNJAtXfA/eWy3jw3C8G4UvXwHX0RbusnNHG0iv+O8+LOOLa6U5XwVXwYJkfP7V/g9BlHmfcnp9Wwv56WRsq8BdB+gAnTjyKccYNWla5Cu6VntwUn5atXgKFvhiOdOP/pMABqSpwChyQANBMRZwCByQANFMRp8ABCQDNVMQpcEACQDMVcQockADQTEWcAgckADRTEQcE9z9gH3lSlhK6vQAAAABJRU5ErkJggg==)
;
}
.icon-close
{
background-size
:
100%
;
background-image
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAWJJREFUOBGVkkdOA0EQRS2WYBwAm+Akke7GliuwZ8+KI7BGIExYECUyLEgincO8Z7mEB0e+9Nw1VdV/2j2VajQa67ANhdQ/xZ45qMNaip9dULdQHNaL3hI8gdrSqAh3PiHXgWb0lCFMLojzzQMQFMATqXuY7nUyahV4BnUOuUQvCc1uQD1Ahxk5TV5AnUHSJBwpTME1qEeYaatVeX61gE4hG7WuKw2aXYHSbBZqECYnxP1NwpnGSQgz7+MD1DFkom+olQ0T4MWHvNieJiN9XD1++0YvdrxPf2eJN8/De+so/p3LVuzslDp3dMnQqEncyRFxGvLg4CnNyl22/qZoWIBPUIeQjipxDrwn5QeoRC2xUliEMDkgHks08EBOMwdROZhJMxJL8AVqHzpMwpRaFhxI5WxVmzWCZfgGVYeeJn/MHEz1BjWPG4k94tFoHrTSmwG/qNrRaBU2YGiTeAl7NNuElR9wOxcdDOaDOAAAAABJRU5ErkJggg==)
;
}
.icon-menu
{
background-size
:
100%
;
background-repeat
:
no-repeat
;
background-position
:
center
;
background-image
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAcCAYAAAATFf3WAAAAyklEQVRYR+2WMQ6BQRCFvzmHgkaidgI3UEjcQUSBygV0NOIQhIQTcAK1kpM8GcV/gbHJSHb62fn2vZ2ZNUltYAN0yBUvYGmSTsAoF1tDc/4LwNwWJ7W2wbIKGFSgKhgUkKrgTxSU1M+46szs4ZtkDmyjNy2Uv3DAGzAoVCB67N0BJ8Ae0jWMgOm3iyX1AN/JmeJtZs86ZqKWVAWrglEFovn536CkLrDLOAeBmW+SCzCMWlEo/+qAB2BcqED02KMDtoB1xu8WsErfJB+rXD/DrYeGMwAAAABJRU5ErkJggg==)
;
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment