Skip to content

Commit c4fec01

Browse files
committed
feat: add fixedHeader
1 parent 57c1a9c commit c4fec01

File tree

9 files changed

+109
-18
lines changed

9 files changed

+109
-18
lines changed

src/components/page/GlobalHeader.vue

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<a-layout-header style="padding: 0px;">
2+
<a-layout-header v-if="!headerBarFixed" :class="[fixedHeader && 'ant-header-fixedHeader']" :style="{ padding: '0', width: fixedHeader ? `calc(100% - ${sidebarOpened ? 256 : 80}px)` : '100%' }">
33
<div v-if="mode === 'sidemenu'" class="header">
44
<a-icon
55
v-if="device==='mobile'"
@@ -76,18 +76,36 @@
7676
data() {
7777
return {
7878
menus: [],
79+
headerBarFixed: false,
7980
}
8081
},
82+
mounted () {
83+
window.addEventListener('scroll', this.handleScroll)
84+
},
8185
created() {
8286
this.menus = this.mainMenu.find((item) => item.path === '/').children
8387
},
8488
computed: {
8589
...mapState({
8690
mainMenu: state => state.permission.addRouters,
91+
sidebarOpened: state => state.app.sidebar.opened,
92+
fixedHeader: state => state.app.fixedHeader,
93+
swipeDownHiddenHeader: state => state.app.swipeDownHiddenHeader,
8794
}),
8895
},
8996
methods: {
90-
97+
handleScroll () {
98+
if (this.swipeDownHiddenHeader) {
99+
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
100+
if (scrollTop > 100) {
101+
this.headerBarFixed = true
102+
} else {
103+
this.headerBarFixed = false
104+
}
105+
} else {
106+
this.headerBarFixed = false
107+
}
108+
},
91109
toggle() {
92110
this.$emit('toggle')
93111
}

src/components/page/GlobalLayout.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
<global-header :mode="layoutMode" :theme="theme" :collapsed="collapsed" :device="device" @toggle="toggle"/>
5353

5454
<!-- layout content -->
55-
<a-layout-content :style="{ margin: '24px 24px 0', height: '100%' }">
55+
<a-layout-content :style="{ margin: '24px 24px 0', height: '100%', paddingTop: fixedHeader ? '64px' : '0' }">
5656
<slot></slot>
5757
</a-layout-content>
5858

@@ -96,6 +96,7 @@
9696
mainMenu: state => state.permission.addRouters,
9797
layoutMode: state => state.app.layout,
9898
sidebarOpened: state => state.app.sidebar.opened,
99+
fixedHeader: state => state.app.fixedHeader,
99100
theme: state => state.app.theme,
100101
device: state => state.app.device,
101102
})
@@ -108,7 +109,7 @@
108109
toggle() {
109110
this.collapsed = !this.collapsed
110111
triggerResize()
111-
this.setSidebar(this.collapsed)
112+
this.setSidebar(!this.collapsed)
112113
},
113114
menuSelect() {
114115
if (this.device !== 'desktop') {
@@ -166,6 +167,14 @@
166167
background: rgba(0, 0, 0, 0.025);
167168
}
168169
}
170+
.ant-header-fixedHeader {
171+
position: fixed;
172+
top: 0;
173+
right: 0;
174+
z-index: 9;
175+
width: 100%;
176+
transition: width .2s;
177+
}
169178
170179
.header {
171180
height: 64px;

src/components/setting/SettingDrawer.vue

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,31 @@
8585
</div>
8686
</a-tooltip>
8787
</div>
88+
<div :style="{ marginTop: '24px' }">
89+
<a-list :split="false">
90+
<a-list-item>
91+
<a-select slot="actions" defaultValue="auto" size="small">
92+
<a-select-option value="fixed">固定</a-select-option>
93+
<a-select-option value="auto">流式</a-select-option>
94+
</a-select>
95+
<a-list-item-meta>
96+
<div slot="title">内容区域宽度</div>
97+
</a-list-item-meta>
98+
</a-list-item>
99+
<a-list-item>
100+
<a-switch slot="actions" size="small" :defaultChecked="fixedHeader" @change="handleFixedHeader" />
101+
<a-list-item-meta>
102+
<div slot="title">固定 Header</div>
103+
</a-list-item-meta>
104+
</a-list-item>
105+
<a-list-item>
106+
<a-switch slot="actions" size="small" :defaultChecked="swipeDownHiddenHeader" @change="handleFixedHeaderHidden" />
107+
<a-list-item-meta>
108+
<div slot="title">下滑时隐藏 Header</div>
109+
</a-list-item-meta>
110+
</a-list-item>
111+
</a-list>
112+
</div>
88113
</div>
89114
<a-divider />
90115

@@ -143,6 +168,8 @@
143168
layoutMode: state => state.app.layout,
144169
primaryColor: state => state.app.color,
145170
colorWeak: state => state.app.weak,
171+
fixedHeader: state => state.app.fixedHeader,
172+
swipeDownHiddenHeader: state => state.app.swipeDownHiddenHeader,
146173
})
147174
},
148175
mounted () {
@@ -186,6 +213,12 @@
186213
this.$store.dispatch('ToggleColor', color)
187214
updateTheme(color)
188215
}
216+
},
217+
handleFixedHeader (fixed) {
218+
this.$store.dispatch('ToggleFixedHeader', fixed)
219+
},
220+
handleFixedHeaderHidden (autoHidden) {
221+
this.$store.dispatch('ToggleFixedHeaderHidden', autoHidden)
189222
}
190223
},
191224
}

src/defaultConfig.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* navTheme - sidebar theme ['dark', 'light'] 两种主题
55
* colorWeak - 色盲模式
66
* layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局
7+
* fixedHeader - 固定 Header : boolean
78
*
89
* storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage)
910
*
@@ -13,6 +14,8 @@ export default {
1314
primaryColor: '#1890FF', // primary color of ant design
1415
navTheme: 'dark', // theme for nav menu
1516
layout: 'sidemenu',
17+
fixedHeader: false, // fixed header
18+
swipeDownHiddenHeader: false,
1619
colorWeak: false,
1720
// vue-ls options
1821
storageOptions: {

src/main.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import 'ant-design-vue/dist/antd.less'; // or 'ant-design-vue/dist/antd.less'
1313
import '@/permission' // permission control
1414
import '@/utils/filter' // base filter
1515

16-
import { ACCESS_TOKEN, DEFAULT_COLOR, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR_WEAK, SIDEBAR_TYPE } from "@/store/mutation-types"
16+
import { ACCESS_TOKEN, DEFAULT_COLOR, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR_WEAK, SIDEBAR_TYPE, DEFAULT_FIXED_HEADER, DEFAULT_FIXED_HEADER_HIDDEN } from "@/store/mutation-types"
1717
import config from '@/defaultConfig'
1818

1919
Vue.config.productionTip = false
@@ -30,6 +30,8 @@ new Vue({
3030
store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, false))
3131
store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme))
3232
store.commit('TOGGLE_LAYOUT_MODE', Vue.ls.get(DEFAULT_LAYOUT_MODE, config.layout))
33+
store.commit('TOGGLE_FIXED_HEADER', Vue.ls.get(DEFAULT_FIXED_HEADER, config.fixedHeader))
34+
store.commit('TOGGLE_FIXED_HEADER_HIDDEN', Vue.ls.get(DEFAULT_FIXED_HEADER_HIDDEN, config.swipeDownHiddenHeader))
3335
store.commit('TOGGLE_WEAK', Vue.ls.get(DEFAULT_COLOR_WEAK, config.colorWeak))
3436
store.commit('TOGGLE_COLOR', Vue.ls.get(DEFAULT_COLOR, config.primaryColor))
3537
store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN))

src/store/modules/app.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Vue from 'vue'
2-
import { SIDEBAR_TYPE, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR, DEFAULT_COLOR_WEAK } from "@/store/mutation-types"
2+
import { SIDEBAR_TYPE, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR, DEFAULT_COLOR_WEAK, DEFAULT_FIXED_HEADER, DEFAULT_FIXED_HEADER_HIDDEN } from "@/store/mutation-types"
33

44
const app = {
55
state: {
@@ -10,6 +10,8 @@ const app = {
1010
device: 'desktop',
1111
theme: '',
1212
layout: '',
13+
fixedHeader: false,
14+
swipeDownHiddenHeader: false,
1315
color: null,
1416
weak: false
1517
},
@@ -35,6 +37,15 @@ const app = {
3537
Vue.ls.set(DEFAULT_LAYOUT_MODE, layout)
3638
state.layout = layout
3739
},
40+
TOGGLE_FIXED_HEADER: (state, fixed) => {
41+
Vue.ls.set(DEFAULT_FIXED_HEADER, fixed)
42+
state.fixedHeader = fixed
43+
},
44+
TOGGLE_FIXED_HEADER_HIDDEN: (state, show) => {
45+
Vue.ls.set(DEFAULT_FIXED_HEADER_HIDDEN, show)
46+
state.swipeDownHiddenHeader = show
47+
},
48+
3849
TOGGLE_COLOR: (state, color) => {
3950
Vue.ls.set(DEFAULT_COLOR, color)
4051
state.color = color
@@ -60,6 +71,12 @@ const app = {
6071
ToggleLayoutMode({ commit }, mode) {
6172
commit('TOGGLE_LAYOUT_MODE', mode)
6273
},
74+
ToggleFixedHeader({ commit }, fixedHeader) {
75+
commit('TOGGLE_FIXED_HEADER', fixedHeader)
76+
},
77+
ToggleFixedHeaderHidden({ commit }, show) {
78+
commit('TOGGLE_FIXED_HEADER_HIDDEN', show)
79+
},
6380
ToggleColor({ commit }, color) {
6481
commit('TOGGLE_COLOR', color)
6582
},

src/store/mutation-types.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ export const SIDEBAR_TYPE = 'SIDEBAR_TYPE'
33
export const DEFAULT_THEME = 'DEFAULT_THEME'
44
export const DEFAULT_LAYOUT_MODE = 'DEFAULT_LAYOUT_MODE'
55
export const DEFAULT_COLOR = 'DEFAULT_COLOR'
6-
export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK'
6+
export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK'
7+
export const DEFAULT_FIXED_HEADER = 'DEFAULT_FIXED_HEADER'
8+
export const DEFAULT_FIXED_HEADER_HIDDEN = 'DEFAULT_FIXED_HEADER_HIDDEN'

src/views/user/Login.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<a-form-item
2020
fieldDecoratorId="password"
2121
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}">
22-
<a-input size="large" type="password" placeholder="密码 / admin">
22+
<a-input size="large" type="password" autocomplete="false" placeholder="密码 / admin">
2323
<a-icon slot="prefix" type='lock' :style="{ color: 'rgba(0,0,0,.25)' }"/>
2424
</a-input>
2525
</a-form-item>

src/views/user/Register.vue

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<a-popover placement="right" trigger="click" :visible="state.passwordLevelChecked">
1313
<template slot="content">
14-
<div :style="{ width: '240px' }">
14+
<div :style="{ width: '240px' }" >
1515
<div :class="['user-register', passwordLevelClass]">强度:<span>{{ passwordLevelName }}</span></div>
1616
<a-progress :percent="state.percent" :showInfo="false" :strokeColor=" passwordLevelColor " />
1717
<div style="margin-top: 10px;">
@@ -21,16 +21,12 @@
2121
</template>
2222
<a-form-item
2323
fieldDecoratorId="password"
24-
:fieldDecoratorOptions="{rules: [
25-
{ required: true, message: '至少6位密码,区分大小写'},
26-
{ validator: this.handlePasswordLevel }
27-
]}"
28-
>
29-
<a-input size="large" type="password" @click="state.passwordLevelChecked = true" autocomplete="false" placeholder="至少6位密码,区分大小写"></a-input>
24+
:fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写'}, { validator: this.handlePasswordLevel }
25+
]}">
26+
<a-input size="large" type="password" @click="handlePasswordInputClick" autocomplete="false" placeholder="至少6位密码,区分大小写"></a-input>
3027
</a-form-item>
3128
</a-popover>
3229

33-
3430
<a-form-item
3531
fieldDecoratorId="password2"
3632
:fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写' }, { validator: this.handlePasswordCheck }]}">
@@ -89,6 +85,7 @@
8985
</template>
9086

9187
<script>
88+
import { mapState } from 'vuex'
9289
import { getSmsCaptcha } from '@/api/login'
9390
9491
const levelNames = {
@@ -129,6 +126,9 @@
129126
}
130127
},
131128
computed: {
129+
...mapState({
130+
isMobile: state => state.app.device === 'mobile',
131+
}),
132132
passwordLevelClass () {
133133
return levelClass[this.state.passwordLevel]
134134
},
@@ -159,14 +159,13 @@
159159
}
160160
this.state.passwordLevel = level
161161
this.state.percent = level * 30
162-
console.log('passwordLevel', this.state.passwordLevel, 'level', level)
163162
if (level >= 2) {
164163
if (level >= 3) {
165164
this.state.percent = 100
166165
}
167166
callback()
168167
} else {
169-
if (level == 0) {
168+
if (level === 0) {
170169
this.state.percent = 10
171170
}
172171
callback(new Error('密码强度不够'))
@@ -181,6 +180,14 @@
181180
callback()
182181
},
183182
183+
handlePasswordInputClick () {
184+
if (!this.isMobile) {
185+
this.state.passwordLevelChecked = true
186+
return;
187+
}
188+
this.state.passwordLevelChecked = false
189+
},
190+
184191
handleSubmit() {
185192
this.form.validateFields((err, values) => {
186193
if (!err) {

0 commit comments

Comments
 (0)