Commit c4fec018 by sendya

feat: add fixedHeader

parent 57c1a9cb
<template>
<a-layout-header style="padding: 0px;">
<a-layout-header v-if="!headerBarFixed" :class="[fixedHeader && 'ant-header-fixedHeader']" :style="{ padding: '0', width: fixedHeader ? `calc(100% - ${sidebarOpened ? 256 : 80}px)` : '100%' }">
<div v-if="mode === 'sidemenu'" class="header">
<a-icon
v-if="device==='mobile'"
......@@ -76,18 +76,36 @@
data() {
return {
menus: [],
headerBarFixed: false,
}
},
mounted () {
window.addEventListener('scroll', this.handleScroll)
},
created() {
this.menus = this.mainMenu.find((item) => item.path === '/').children
},
computed: {
...mapState({
mainMenu: state => state.permission.addRouters,
sidebarOpened: state => state.app.sidebar.opened,
fixedHeader: state => state.app.fixedHeader,
swipeDownHiddenHeader: state => state.app.swipeDownHiddenHeader,
}),
},
methods: {
handleScroll () {
if (this.swipeDownHiddenHeader) {
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
if (scrollTop > 100) {
this.headerBarFixed = true
} else {
this.headerBarFixed = false
}
} else {
this.headerBarFixed = false
}
},
toggle() {
this.$emit('toggle')
}
......
......@@ -52,7 +52,7 @@
<global-header :mode="layoutMode" :theme="theme" :collapsed="collapsed" :device="device" @toggle="toggle"/>
<!-- layout content -->
<a-layout-content :style="{ margin: '24px 24px 0', height: '100%' }">
<a-layout-content :style="{ margin: '24px 24px 0', height: '100%', paddingTop: fixedHeader ? '64px' : '0' }">
<slot></slot>
</a-layout-content>
......@@ -96,6 +96,7 @@
mainMenu: state => state.permission.addRouters,
layoutMode: state => state.app.layout,
sidebarOpened: state => state.app.sidebar.opened,
fixedHeader: state => state.app.fixedHeader,
theme: state => state.app.theme,
device: state => state.app.device,
})
......@@ -108,7 +109,7 @@
toggle() {
this.collapsed = !this.collapsed
triggerResize()
this.setSidebar(this.collapsed)
this.setSidebar(!this.collapsed)
},
menuSelect() {
if (this.device !== 'desktop') {
......@@ -166,6 +167,14 @@
background: rgba(0, 0, 0, 0.025);
}
}
.ant-header-fixedHeader {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: 100%;
transition: width .2s;
}
.header {
height: 64px;
......
......@@ -85,6 +85,31 @@
</div>
</a-tooltip>
</div>
<div :style="{ marginTop: '24px' }">
<a-list :split="false">
<a-list-item>
<a-select slot="actions" defaultValue="auto" size="small">
<a-select-option value="fixed">固定</a-select-option>
<a-select-option value="auto">流式</a-select-option>
</a-select>
<a-list-item-meta>
<div slot="title">内容区域宽度</div>
</a-list-item-meta>
</a-list-item>
<a-list-item>
<a-switch slot="actions" size="small" :defaultChecked="fixedHeader" @change="handleFixedHeader" />
<a-list-item-meta>
<div slot="title">固定 Header</div>
</a-list-item-meta>
</a-list-item>
<a-list-item>
<a-switch slot="actions" size="small" :defaultChecked="swipeDownHiddenHeader" @change="handleFixedHeaderHidden" />
<a-list-item-meta>
<div slot="title">下滑时隐藏 Header</div>
</a-list-item-meta>
</a-list-item>
</a-list>
</div>
</div>
<a-divider />
......@@ -143,6 +168,8 @@
layoutMode: state => state.app.layout,
primaryColor: state => state.app.color,
colorWeak: state => state.app.weak,
fixedHeader: state => state.app.fixedHeader,
swipeDownHiddenHeader: state => state.app.swipeDownHiddenHeader,
})
},
mounted () {
......@@ -186,6 +213,12 @@
this.$store.dispatch('ToggleColor', color)
updateTheme(color)
}
},
handleFixedHeader (fixed) {
this.$store.dispatch('ToggleFixedHeader', fixed)
},
handleFixedHeaderHidden (autoHidden) {
this.$store.dispatch('ToggleFixedHeaderHidden', autoHidden)
}
},
}
......
......@@ -4,6 +4,7 @@
* navTheme - sidebar theme ['dark', 'light'] 两种主题
* colorWeak - 色盲模式
* layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局
* fixedHeader - 固定 Header : boolean
*
* storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage)
*
......@@ -13,6 +14,8 @@ export default {
primaryColor: '#1890FF', // primary color of ant design
navTheme: 'dark', // theme for nav menu
layout: 'sidemenu',
fixedHeader: false, // fixed header
swipeDownHiddenHeader: false,
colorWeak: false,
// vue-ls options
storageOptions: {
......
......@@ -13,7 +13,7 @@ import 'ant-design-vue/dist/antd.less'; // or 'ant-design-vue/dist/antd.less'
import '@/permission' // permission control
import '@/utils/filter' // base filter
import { ACCESS_TOKEN, DEFAULT_COLOR, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR_WEAK, SIDEBAR_TYPE } from "@/store/mutation-types"
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"
import config from '@/defaultConfig'
Vue.config.productionTip = false
......@@ -30,6 +30,8 @@ new Vue({
store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, false))
store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme))
store.commit('TOGGLE_LAYOUT_MODE', Vue.ls.get(DEFAULT_LAYOUT_MODE, config.layout))
store.commit('TOGGLE_FIXED_HEADER', Vue.ls.get(DEFAULT_FIXED_HEADER, config.fixedHeader))
store.commit('TOGGLE_FIXED_HEADER_HIDDEN', Vue.ls.get(DEFAULT_FIXED_HEADER_HIDDEN, config.swipeDownHiddenHeader))
store.commit('TOGGLE_WEAK', Vue.ls.get(DEFAULT_COLOR_WEAK, config.colorWeak))
store.commit('TOGGLE_COLOR', Vue.ls.get(DEFAULT_COLOR, config.primaryColor))
store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN))
......
import Vue from 'vue'
import { SIDEBAR_TYPE, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR, DEFAULT_COLOR_WEAK } from "@/store/mutation-types"
import { SIDEBAR_TYPE, DEFAULT_THEME, DEFAULT_LAYOUT_MODE, DEFAULT_COLOR, DEFAULT_COLOR_WEAK, DEFAULT_FIXED_HEADER, DEFAULT_FIXED_HEADER_HIDDEN } from "@/store/mutation-types"
const app = {
state: {
......@@ -10,6 +10,8 @@ const app = {
device: 'desktop',
theme: '',
layout: '',
fixedHeader: false,
swipeDownHiddenHeader: false,
color: null,
weak: false
},
......@@ -35,6 +37,15 @@ const app = {
Vue.ls.set(DEFAULT_LAYOUT_MODE, layout)
state.layout = layout
},
TOGGLE_FIXED_HEADER: (state, fixed) => {
Vue.ls.set(DEFAULT_FIXED_HEADER, fixed)
state.fixedHeader = fixed
},
TOGGLE_FIXED_HEADER_HIDDEN: (state, show) => {
Vue.ls.set(DEFAULT_FIXED_HEADER_HIDDEN, show)
state.swipeDownHiddenHeader = show
},
TOGGLE_COLOR: (state, color) => {
Vue.ls.set(DEFAULT_COLOR, color)
state.color = color
......@@ -60,6 +71,12 @@ const app = {
ToggleLayoutMode({ commit }, mode) {
commit('TOGGLE_LAYOUT_MODE', mode)
},
ToggleFixedHeader({ commit }, fixedHeader) {
commit('TOGGLE_FIXED_HEADER', fixedHeader)
},
ToggleFixedHeaderHidden({ commit }, show) {
commit('TOGGLE_FIXED_HEADER_HIDDEN', show)
},
ToggleColor({ commit }, color) {
commit('TOGGLE_COLOR', color)
},
......
......@@ -3,4 +3,6 @@ export const SIDEBAR_TYPE = 'SIDEBAR_TYPE'
export const DEFAULT_THEME = 'DEFAULT_THEME'
export const DEFAULT_LAYOUT_MODE = 'DEFAULT_LAYOUT_MODE'
export const DEFAULT_COLOR = 'DEFAULT_COLOR'
export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK'
\ No newline at end of file
export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK'
export const DEFAULT_FIXED_HEADER = 'DEFAULT_FIXED_HEADER'
export const DEFAULT_FIXED_HEADER_HIDDEN = 'DEFAULT_FIXED_HEADER_HIDDEN'
\ No newline at end of file
......@@ -19,7 +19,7 @@
<a-form-item
fieldDecoratorId="password"
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}">
<a-input size="large" type="password" placeholder="密码 / admin">
<a-input size="large" type="password" autocomplete="false" placeholder="密码 / admin">
<a-icon slot="prefix" type='lock' :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
......
......@@ -11,7 +11,7 @@
<a-popover placement="right" trigger="click" :visible="state.passwordLevelChecked">
<template slot="content">
<div :style="{ width: '240px' }">
<div :style="{ width: '240px' }" >
<div :class="['user-register', passwordLevelClass]">强度:<span>{{ passwordLevelName }}</span></div>
<a-progress :percent="state.percent" :showInfo="false" :strokeColor=" passwordLevelColor " />
<div style="margin-top: 10px;">
......@@ -21,16 +21,12 @@
</template>
<a-form-item
fieldDecoratorId="password"
:fieldDecoratorOptions="{rules: [
{ required: true, message: '至少6位密码,区分大小写'},
{ validator: this.handlePasswordLevel }
]}"
>
<a-input size="large" type="password" @click="state.passwordLevelChecked = true" autocomplete="false" placeholder="至少6位密码,区分大小写"></a-input>
:fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写'}, { validator: this.handlePasswordLevel }
]}">
<a-input size="large" type="password" @click="handlePasswordInputClick" autocomplete="false" placeholder="至少6位密码,区分大小写"></a-input>
</a-form-item>
</a-popover>
<a-form-item
fieldDecoratorId="password2"
:fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写' }, { validator: this.handlePasswordCheck }]}">
......@@ -89,6 +85,7 @@
</template>
<script>
import { mapState } from 'vuex'
import { getSmsCaptcha } from '@/api/login'
const levelNames = {
......@@ -129,6 +126,9 @@
}
},
computed: {
...mapState({
isMobile: state => state.app.device === 'mobile',
}),
passwordLevelClass () {
return levelClass[this.state.passwordLevel]
},
......@@ -159,14 +159,13 @@
}
this.state.passwordLevel = level
this.state.percent = level * 30
console.log('passwordLevel', this.state.passwordLevel, 'level', level)
if (level >= 2) {
if (level >= 3) {
this.state.percent = 100
}
callback()
} else {
if (level == 0) {
if (level === 0) {
this.state.percent = 10
}
callback(new Error('密码强度不够'))
......@@ -181,6 +180,14 @@
callback()
},
handlePasswordInputClick () {
if (!this.isMobile) {
this.state.passwordLevelChecked = true
return;
}
this.state.passwordLevelChecked = false
},
handleSubmit() {
this.form.validateFields((err, values) => {
if (!err) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment