mart-admin/src/views/layout/navBars/breadcrumb/user.vue

288 lines
9.2 KiB
Vue
Raw Normal View History

<template>
<div class="layout-navbars-breadcrumb-user" :style="{ flex: layoutUserFlexNum }">
<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onComponentSizeChange">
<div class="layout-navbars-breadcrumb-user-icon">
<i class="iconfont icon-ziti" :title="$t('message.user.title0')"></i>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="default" :disabled="disabledSize === 'default'">{{ $t('message.user.dropdownDefault') }}</el-dropdown-item>
<el-dropdown-item command="medium" :disabled="disabledSize === 'medium'">{{ $t('message.user.dropdownMedium') }}</el-dropdown-item>
<el-dropdown-item command="small" :disabled="disabledSize === 'small'">{{ $t('message.user.dropdownSmall') }}</el-dropdown-item>
<el-dropdown-item command="mini" :disabled="disabledSize === 'mini'">{{ $t('message.user.dropdownMini') }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange">
<div class="layout-navbars-breadcrumb-user-icon">
<i class="iconfont" :class="disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'" :title="$t('message.user.title1')"></i>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="zh-cn" :disabled="disabledI18n === 'zh-cn'">简体中文</el-dropdown-item>
<el-dropdown-item command="en" :disabled="disabledI18n === 'en'">English</el-dropdown-item>
<el-dropdown-item command="zh-tw" :disabled="disabledI18n === 'zh-tw'">繁體中文</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
<i class="el-icon-search" :title="$t('message.user.title2')"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
<i class="icon-skin iconfont" :title="$t('message.user.title3')"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon">
<el-popover placement="bottom" trigger="click" v-model:visible="isShowUserNewsPopover" :width="300" popper-class="el-popover-pupop-user-news">
<template #reference>
<el-badge :is-dot="true" @click="isShowUserNewsPopover = !isShowUserNewsPopover">
<i class="el-icon-bell" :title="$t('message.user.title4')"></i>
</el-badge>
</template>
<transition name="el-zoom-in-top">
<UserNews v-show="isShowUserNewsPopover" />
</transition>
</el-popover>
</div>
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
<i
class="iconfont"
:title="isScreenfull ? $t('message.user.title5') : $t('message.user.title6')"
:class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"
></i>
</div>
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
<span class="layout-navbars-breadcrumb-user-link">
<img :src="getUserInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" />
{{ getUserInfos.userName === '' ? 'test' : getUserInfos.userName }}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="/home">{{ $t('message.user.dropdown1') }}</el-dropdown-item>
<el-dropdown-item command="/personal">{{ $t('message.user.dropdown2') }}</el-dropdown-item>
<el-dropdown-item command="/404">{{ $t('message.user.dropdown3') }}</el-dropdown-item>
<el-dropdown-item command="/401">{{ $t('message.user.dropdown4') }}</el-dropdown-item>
<el-dropdown-item divided command="logOut">{{ $t('message.user.dropdown5') }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<Search ref="searchRef" />
</div>
</template>
<script lang="ts">
import { ref, getCurrentInstance, computed, reactive, toRefs, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessageBox, ElMessage } from 'element-plus';
import screenfull from 'screenfull';
import { useI18n } from 'vue-i18n';
import { resetRoute } from '/@/router/index.ts';
import { useStore } from '/@/store/index.ts';
import { clearSession, setLocal, getLocal, removeLocal } from '/@/utils/storage.ts';
import UserNews from '/@/views/layout/navBars/breadcrumb/userNews.vue';
import Search from '/@/views/layout/navBars/breadcrumb/search.vue';
export default {
name: 'layoutBreadcrumbUser',
components: { UserNews, Search },
setup() {
const { t } = useI18n();
const { proxy } = getCurrentInstance() as any;
const router = useRouter();
const store = useStore();
const searchRef = ref();
const state = reactive({
isScreenfull: false,
isShowUserNewsPopover: false,
disabledI18n: 'zh-cn',
disabledSize: 'small',
});
// 获取用户信息 vuex
const getUserInfos = computed(() => {
return store.state.userInfos.userInfos;
});
// 获取布局配置信息
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
});
// 设置分割样式
const layoutUserFlexNum = computed(() => {
let { layout, isClassicSplitMenu } = getThemeConfig.value;
let num = '';
if (layout === 'defaults' || (layout === 'classic' && !isClassicSplitMenu) || layout === 'columns') num = 1;
else num = null;
return num;
});
// 全屏点击时
const onScreenfullClick = () => {
if (!screenfull.isEnabled) {
ElMessage.warning('暂不不支持全屏');
return false;
}
screenfull.toggle();
state.isScreenfull = !state.isScreenfull;
};
// 布局配置 icon 点击时
const onLayoutSetingClick = () => {
proxy.mittBus.emit('openSetingsDrawer');
};
// 下拉菜单点击时
const onHandleCommandClick = (path: string) => {
if (path === 'logOut') {
ElMessageBox({
closeOnClickModal: false,
closeOnPressEscape: false,
title: t('message.user.logOutTitle'),
message: t('message.user.logOutMessage'),
showCancelButton: true,
confirmButtonText: t('message.user.logOutConfirm'),
cancelButtonText: t('message.user.logOutCancel'),
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = t('message.user.logOutExit');
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 700);
} else {
done();
}
},
})
.then(() => {
clearSession(); // 清除缓存/token等
resetRoute(); // 删除/重置路由
router.push('/login');
setTimeout(() => {
ElMessage.success(t('message.user.logOutSuccess'));
}, 300);
})
.catch(() => {});
} else {
router.push(path);
}
};
// 菜单搜索点击
const onSearchClick = () => {
searchRef.value.openSearch();
};
// 组件大小改变
const onComponentSizeChange = (size: string) => {
removeLocal('themeConfig');
getThemeConfig.value.globalComponentSize = size;
setLocal('themeConfig', getThemeConfig.value);
proxy.$ELEMENT.size = size;
initComponentSize();
window.location.reload();
};
// 语言切换
const onLanguageChange = (lang: string) => {
removeLocal('themeConfig');
getThemeConfig.value.globalI18n = lang;
setLocal('themeConfig', getThemeConfig.value);
proxy.$i18n.locale = lang;
initI18n();
};
// 初始化言语国际化
const initI18n = () => {
switch (getLocal('themeConfig').globalI18n) {
case 'zh-cn':
state.disabledI18n = 'zh-cn';
break;
case 'en':
state.disabledI18n = 'en';
break;
case 'zh-tw':
state.disabledI18n = 'zh-tw';
break;
}
};
// 初始化全局组件大小
const initComponentSize = () => {
switch (getLocal('themeConfig').globalComponentSize) {
case 'default':
state.disabledSize = 'default';
break;
case 'medium':
state.disabledSize = 'medium';
break;
case 'small':
state.disabledSize = 'small';
break;
case 'mini':
state.disabledSize = 'mini';
break;
}
};
// 页面加载时
onMounted(() => {
if (getLocal('themeConfig')) {
initI18n();
initComponentSize();
}
});
return {
getUserInfos,
onLayoutSetingClick,
onHandleCommandClick,
onScreenfullClick,
onSearchClick,
onComponentSizeChange,
onLanguageChange,
searchRef,
layoutUserFlexNum,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user {
display: flex;
align-items: center;
justify-content: flex-end;
&-link {
height: 100%;
display: flex;
align-items: center;
white-space: nowrap;
&-photo {
width: 25px;
height: 25px;
border-radius: 100%;
}
}
&-icon {
padding: 0 10px;
cursor: pointer;
color: var(--bg-topBarColor);
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&:hover {
background: rgba(0, 0, 0, 0.04);
i {
display: inline-block;
animation: logoAnimation 0.3s ease-in-out;
}
}
}
::v-deep(.el-dropdown) {
color: var(--bg-topBarColor);
}
::v-deep(.el-badge) {
height: 40px;
line-height: 40px;
display: flex;
align-items: center;
}
::v-deep(.el-badge__content.is-fixed) {
top: 12px;
}
}
</style>