chore: rename some layout components; 🐶
This commit is contained in:
165
src/layouts/header/AdminHeader.vue
Normal file
165
src/layouts/header/AdminHeader.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<a-layout-header :class="[headerTheme, 'admin-header']">
|
||||
<div :class="['admin-header-wide', layout]">
|
||||
<router-link v-if="isMobile || layout === 'head'" to="/" :class="['logo', isMobile ? null : 'pc', headerTheme]">
|
||||
<img width="32" src="@/assets/img/logo.png" />
|
||||
<h1 v-if="!isMobile">{{systemName}}</h1>
|
||||
</router-link>
|
||||
<a-divider v-if="isMobile" type="vertical" />
|
||||
<a-icon v-if="layout === 'side'" class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggleCollapse"/>
|
||||
<div v-if="layout == 'head' && !isMobile" class="admin-header-menu">
|
||||
<i-menu style="height: 64px; line-height: 64px;" @i18nComplete="setRoutesI18n" :i18n="menuI18n" :theme="headerTheme" mode="horizontal" :options="menuData" @select="onSelect"/>
|
||||
</div>
|
||||
<div :class="['admin-header-right', headerTheme]">
|
||||
<header-search class="header-item" />
|
||||
<a-tooltip class="header-item" title="帮助文档" placement="bottom" >
|
||||
<a>
|
||||
<a-icon type="question-circle-o" />
|
||||
</a>
|
||||
</a-tooltip>
|
||||
<header-notice class="header-item"/>
|
||||
<header-avatar class="header-item"/>
|
||||
<a-dropdown class="lang header-item">
|
||||
<div>
|
||||
<a-icon type="global"/> {{langAlias}}
|
||||
</div>
|
||||
<a-menu @click="val => setLang(val.key)" :selected-keys="[lang]" slot="overlay">
|
||||
<a-menu-item v-for=" lang in langList" :key="lang.key">{{lang.key.toLowerCase() + ' ' + lang.name}}</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</a-layout-header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HeaderSearch from './HeaderSearch'
|
||||
import HeaderNotice from './HeaderNotice'
|
||||
import HeaderAvatar from './HeaderlAvatar'
|
||||
import IMenu from '@/components/menu/menu'
|
||||
import {mapState, mapMutations} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'AdminHeader',
|
||||
components: {IMenu, HeaderAvatar, HeaderNotice, HeaderSearch},
|
||||
props: ['collapsed', 'menuData'],
|
||||
inject: ['menuI18n'],
|
||||
data() {
|
||||
return {
|
||||
langList: [
|
||||
{key: 'CN', name: '简体中文', alias: '简体'},
|
||||
{key: 'HK', name: '繁體中文', alias: '繁體'},
|
||||
{key: 'US', name: 'English', alias: 'English'}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('setting', ['theme', 'isMobile', 'layout', 'systemName', 'lang']),
|
||||
headerTheme () {
|
||||
return (this.layout == 'side' && !this.isMobile) ? 'light' : this.theme
|
||||
},
|
||||
langAlias() {
|
||||
let lang = this.langList.find(item => item.key == this.lang)
|
||||
return lang.alias
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleCollapse () {
|
||||
this.$emit('toggleCollapse')
|
||||
},
|
||||
onSelect (obj) {
|
||||
this.$emit('menuSelect', obj)
|
||||
},
|
||||
...mapMutations('setting', ['setLang', 'setRoutesI18n'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.trigger {
|
||||
font-size: 20px;
|
||||
line-height: 64px;
|
||||
padding: 0 24px;
|
||||
cursor: pointer;
|
||||
transition: color .3s;
|
||||
&:hover{
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
.admin-header{
|
||||
padding: 0;
|
||||
-webkit-box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
&.light{
|
||||
background: #fff;
|
||||
}
|
||||
&.dark{
|
||||
background: #001529;
|
||||
.trigger{
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
.admin-header-wide{
|
||||
&.head{
|
||||
max-width: 1400px;
|
||||
margin: auto;
|
||||
}
|
||||
&.side{
|
||||
padding-right: 12px;
|
||||
}
|
||||
.logo {
|
||||
height: 64px;
|
||||
line-height: 58px;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
padding: 0 12px 0 24px;
|
||||
cursor: pointer;
|
||||
font-size: 20px;
|
||||
&.pc{
|
||||
padding: 0 12px 0 0;
|
||||
}
|
||||
img {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
h1{
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
}
|
||||
&.dark h1{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.admin-header-menu{
|
||||
display: inline-block;
|
||||
}
|
||||
.admin-header-right{
|
||||
float: right;
|
||||
display: flex;
|
||||
&.dark{
|
||||
color: #fff;
|
||||
a, i{
|
||||
color: #fff !important;
|
||||
}
|
||||
.header-item:hover{
|
||||
background-color: @primary-color;
|
||||
}
|
||||
}
|
||||
.header-item{
|
||||
padding: 0 12px;
|
||||
cursor: pointer;
|
||||
align-self: center;
|
||||
&:hover{
|
||||
background-color: @gray-3;
|
||||
}
|
||||
i{
|
||||
font-size: 16px;
|
||||
color: rgba(0,0,0,.65);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
88
src/layouts/header/HeaderNotice.vue
Normal file
88
src/layouts/header/HeaderNotice.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<a-dropdown :trigger="['click']" v-model="show">
|
||||
<div slot="overlay">
|
||||
<a-spin :spinning="loading">
|
||||
<a-tabs class="dropdown-tabs" :tabBarStyle="{textAlign: 'center'}" :style="{backgroundColor: 'white', width: '297px'}">
|
||||
<a-tab-pane tab="通知" key="1">
|
||||
<a-list class="tab-pane">
|
||||
<a-list-item>
|
||||
<a-list-item-meta title="你收到了 14 份新周报" description="一年前">
|
||||
<a-avatar style="background-color: white" slot="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png"/>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-list-item-meta title="你推荐的 曲妮妮 已通过第三轮面试" description="一年前">
|
||||
<a-avatar style="background-color: white" slot="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png"/>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item>
|
||||
<a-list-item-meta title="这种模板可以区分多种通知类型" description="一年前">
|
||||
<a-avatar style="background-color: white" slot="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png"/>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="消息" key="2">
|
||||
<a-list class="tab-pane"></a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="待办" key="3">
|
||||
<a-list class="tab-pane"></a-list>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-spin>
|
||||
</div>
|
||||
<span @click="fetchNotice" class="header-notice">
|
||||
<a-badge count="12">
|
||||
<a-icon :class="['header-notice-icon']" type="bell" />
|
||||
</a-badge>
|
||||
</span>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HeaderNotice',
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
show: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
fetchNotice () {
|
||||
if (this.loading) {
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
this.loadding = true
|
||||
setTimeout(() => {
|
||||
this.loadding = false
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.header-notice{
|
||||
display: inline-block;
|
||||
transition: all 0.3s;
|
||||
span {
|
||||
vertical-align: initial;
|
||||
}
|
||||
.header-notice-icon{
|
||||
font-size: 16px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
.dropdown-tabs{
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px;
|
||||
.tab-pane{
|
||||
padding: 0 24px 12px;
|
||||
min-height: 250px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
64
src/layouts/header/HeaderSearch.vue
Normal file
64
src/layouts/header/HeaderSearch.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="header-search">
|
||||
<a-icon type="search" class="search-icon" @click="enterSearchMode"/>
|
||||
<a-auto-complete
|
||||
ref="input"
|
||||
:dataSource="dataSource"
|
||||
:class="['search-input', searchMode ? 'enter' : 'leave']"
|
||||
placeholder="站内搜索"
|
||||
@blur="leaveSearchMode"
|
||||
>
|
||||
</a-auto-complete>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HeaderSearch',
|
||||
data () {
|
||||
return {
|
||||
dataSource: ['选项一', '选项二'],
|
||||
searchMode: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
enterSearchMode () {
|
||||
this.searchMode = true
|
||||
setTimeout(() => this.$refs.input.focus(), 300)
|
||||
},
|
||||
leaveSearchMode () {
|
||||
this.searchMode = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.header-search{
|
||||
.search-icon{
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.search-input{
|
||||
border: 0;
|
||||
border-bottom: 1px rgba(3, 5, 6, 0.23) solid;
|
||||
transition: width 0.3s ease-in-out;
|
||||
input{
|
||||
border: 0;
|
||||
box-shadow: 0 0 0 0;
|
||||
}
|
||||
&.leave{
|
||||
width: 0px;
|
||||
input{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.enter{
|
||||
width: 200px;
|
||||
input:focus{
|
||||
box-shadow: 0 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
56
src/layouts/header/HeaderlAvatar.vue
Normal file
56
src/layouts/header/HeaderlAvatar.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<a-dropdown>
|
||||
<div class="header-avatar" style="cursor: pointer">
|
||||
<a-avatar class="avatar" size="small" shape="circle" :src="user.avatar"/>
|
||||
<span class="name">{{user.name}}</span>
|
||||
</div>
|
||||
<a-menu :class="['avatar-menu']" slot="overlay">
|
||||
<a-menu-item>
|
||||
<a-icon type="user" />
|
||||
<span>个人中心</span>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-icon type="setting" />
|
||||
<span>设置</span>
|
||||
</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item>
|
||||
<router-link to="/login">
|
||||
<a-icon type="poweroff" />
|
||||
<span>退出登录</span>
|
||||
</router-link>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'HeaderAvatar',
|
||||
computed: {
|
||||
...mapState('setting', ['weekMode']),
|
||||
...mapState('account', ['user']),
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.header-avatar{
|
||||
display: inline-flex;
|
||||
.avatar, .name{
|
||||
align-self: center;
|
||||
}
|
||||
.avatar{
|
||||
margin-right: 8px;
|
||||
}
|
||||
.name{
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.avatar-menu{
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user