init
This commit is contained in:
300
src/layout/navBars/breadcrumb/user.vue
Normal file
300
src/layout/navBars/breadcrumb/user.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<div class="layout-navbars-breadcrumb-user pr15" :style="{ flex: layoutUserFlexNum }">
|
||||
<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange">
|
||||
<div class="layout-navbars-breadcrumb-user-icon">
|
||||
<i class="iconfont" :class="state.disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'" :title="$t('user.title1')"></i>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="zh-cn" :disabled="state.disabledI18n === 'zh-cn'">简体中文</el-dropdown-item>
|
||||
<el-dropdown-item command="en" :disabled="state.disabledI18n === 'en'">English</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onLockClick">
|
||||
<el-icon :title="$t('layout.threeLockScreenTime')">
|
||||
<ele-Lock />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" v-if="useFlowJob().jsonFlowEnable()" @click="useFlowJob().onTodoJobClick()">
|
||||
<el-badge :value="useFlowJob().jobLen"
|
||||
:max="999">
|
||||
<el-icon :title="`${useFlowJob().jobLen}` + $t('user.title7')">
|
||||
<ele-ChatLineRound />
|
||||
</el-icon>
|
||||
</el-badge>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
|
||||
<el-icon :title="$t('user.title2')">
|
||||
<ele-Search />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
|
||||
<i class="icon-skin iconfont" :title="$t('user.title3')"></i>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon">
|
||||
<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
|
||||
<template #reference>
|
||||
<el-badge :is-dot="isDot">
|
||||
<el-icon :title="$t('user.title4')">
|
||||
<ele-Bell />
|
||||
</el-icon>
|
||||
</el-badge>
|
||||
</template>
|
||||
<template #default>
|
||||
<UserNews ref="newsRef" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
|
||||
<i
|
||||
class="iconfont"
|
||||
:title="state.isScreenfull ? $t('user.title6') : $t('user.title5')"
|
||||
:class="!state.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="baseURL + userInfos.user.avatar" class="layout-navbars-breadcrumb-user-link-photo mr5" />
|
||||
{{ userInfos.user.username }}
|
||||
<el-icon class="el-icon--right">
|
||||
<ele-ArrowDown />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="/home">{{ $t('user.dropdown1') }}</el-dropdown-item>
|
||||
<el-dropdown-item command="personal">{{ $t('user.dropdown2') }}</el-dropdown-item>
|
||||
<el-dropdown-item divided command="logOut">{{ $t('user.dropdown5') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<Search ref="searchRef" />
|
||||
<global-websocket uri="/admin/ws/info" v-if="websocketEnable" @rollback="rollback" />
|
||||
<global-websocket uri="/jsonflow/ws/info" v-if="useFlowJob().jsonFlowEnable()" @rollback="rollback" />
|
||||
<personal-drawer ref="personalDrawerRef"></personal-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="layoutBreadcrumbUser">
|
||||
import { logout } from '/@/api/login';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import screenfull from 'screenfull';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useUserInfo } from '/@/stores/userInfo';
|
||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||
import other from '/@/utils/other';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
import { Local, Session } from '/@/utils/storage';
|
||||
import { formatAxis } from '/@/utils/formatTime';
|
||||
import { useMsg } from '/@/stores/msg';
|
||||
import { fetchUserMessageList } from '/@/api/admin/message';
|
||||
import {useFlowJob} from "/@/flow/stores/flowJob";
|
||||
|
||||
// 引入组件
|
||||
const GlobalWebsocket = defineAsyncComponent(() => import('/@/components/Websocket/index.vue'));
|
||||
const UserNews = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/userNews.vue'));
|
||||
const Search = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/search.vue'));
|
||||
const PersonalDrawer = defineAsyncComponent(() => import('/@/views/admin/system/user/personal.vue'));
|
||||
|
||||
// 定义变量内容
|
||||
const { locale, t } = useI18n();
|
||||
const router = useRouter();
|
||||
const stores = useUserInfo();
|
||||
const storesThemeConfig = useThemeConfig();
|
||||
const { userInfos } = storeToRefs(stores);
|
||||
const { themeConfig } = storeToRefs(storesThemeConfig);
|
||||
const searchRef = ref();
|
||||
const newsRef = ref();
|
||||
const personalDrawerRef = ref();
|
||||
|
||||
interface State {
|
||||
[key: string]: boolean | string;
|
||||
isScreenfull: boolean;
|
||||
disabledI18n: string;
|
||||
disabledSize: string;
|
||||
}
|
||||
|
||||
const state = reactive<State>({
|
||||
isScreenfull: false,
|
||||
disabledI18n: 'zh-cn',
|
||||
disabledSize: 'large',
|
||||
});
|
||||
|
||||
// 是否开启websocket
|
||||
const websocketEnable = ref(import.meta.env.VITE_WEBSOCKET_ENABLE === 'true');
|
||||
|
||||
// 设置分割样式
|
||||
const layoutUserFlexNum = computed(() => {
|
||||
let num: string | number = '';
|
||||
const { layout, isClassicSplitMenu } = themeConfig.value;
|
||||
const layoutArr: string[] = ['defaults', 'columns'];
|
||||
if (layoutArr.includes(layout) || (layout === 'classic' && !isClassicSplitMenu)) num = '1';
|
||||
else num = '';
|
||||
return num;
|
||||
});
|
||||
// 全屏点击时
|
||||
const onScreenfullClick = () => {
|
||||
if (!screenfull.isEnabled) {
|
||||
ElMessage.warning('暂不不支持全屏');
|
||||
return false;
|
||||
}
|
||||
screenfull.toggle();
|
||||
screenfull.on('change', () => {
|
||||
if (screenfull.isFullscreen) state.isScreenfull = true;
|
||||
else state.isScreenfull = false;
|
||||
});
|
||||
};
|
||||
// 布局配置 icon 点击时
|
||||
const onLayoutSetingClick = () => {
|
||||
mittBus.emit('openSettingsDrawer');
|
||||
};
|
||||
// 下拉菜单点击时
|
||||
const onHandleCommandClick = (path: string) => {
|
||||
if (path === 'logOut') {
|
||||
ElMessageBox({
|
||||
closeOnClickModal: false,
|
||||
closeOnPressEscape: false,
|
||||
title: t('user.logOutTitle'),
|
||||
message: t('user.logOutMessage'),
|
||||
showCancelButton: true,
|
||||
confirmButtonText: t('user.logOutConfirm'),
|
||||
cancelButtonText: t('user.logOutCancel'),
|
||||
buttonSize: 'default',
|
||||
beforeClose: (action, instance, done) => {
|
||||
if (action === 'confirm') {
|
||||
instance.confirmButtonLoading = true;
|
||||
instance.confirmButtonText = t('user.logOutExit');
|
||||
setTimeout(() => {
|
||||
done();
|
||||
setTimeout(() => {
|
||||
instance.confirmButtonLoading = false;
|
||||
}, 300);
|
||||
}, 700);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
},
|
||||
})
|
||||
.then(async () => {
|
||||
// 关闭全部的标签页
|
||||
mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 3, ...router }));
|
||||
// 调用后台接口
|
||||
await logout();
|
||||
// 清除缓存/token等
|
||||
Session.clear();
|
||||
// 使用 reload 时,不需要调用 resetRoute() 重置路由
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(() => {});
|
||||
} else if (path === 'personal') {
|
||||
// 打开个人页面
|
||||
personalDrawerRef.value.open();
|
||||
} else {
|
||||
router.push(path);
|
||||
}
|
||||
};
|
||||
// 菜单搜索点击
|
||||
const onSearchClick = () => {
|
||||
searchRef.value.openSearch();
|
||||
};
|
||||
// 语言切换
|
||||
const onLanguageChange = (lang: string) => {
|
||||
Local.remove('themeConfig');
|
||||
themeConfig.value.globalI18n = lang;
|
||||
Local.set('themeConfig', themeConfig.value);
|
||||
locale.value = lang;
|
||||
other.useTitle();
|
||||
initI18nOrSize('globalI18n', 'disabledI18n');
|
||||
};
|
||||
// 锁屏
|
||||
const onLockClick = () => {
|
||||
themeConfig.value.isLockScreen = true;
|
||||
themeConfig.value.lockScreenTime = 0;
|
||||
Local.set('themeConfig', themeConfig.value);
|
||||
};
|
||||
|
||||
// 初始化组件大小/i18n
|
||||
const initI18nOrSize = (value: string, attr: string) => {
|
||||
state[attr] = Local.get('themeConfig')[value];
|
||||
};
|
||||
|
||||
// 获取到消息
|
||||
const rollback = (msg: string) => {
|
||||
useMsg().setMsg({ label: 'websocket消息', value: msg, time: formatAxis(new Date()) });
|
||||
};
|
||||
|
||||
// 获取是否显示未读
|
||||
const isDot = ref(false);
|
||||
const getIsDot = () => {
|
||||
fetchUserMessageList({ category: '1', readFlag: '0' }).then((res) => {
|
||||
isDot.value = res.data.total !== 0;
|
||||
});
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
if (Local.get('themeConfig')) {
|
||||
initI18nOrSize('globalComponentSize', 'disabledSize');
|
||||
initI18nOrSize('globalI18n', 'disabledI18n');
|
||||
}
|
||||
useFlowJob().topJobList()
|
||||
|
||||
getIsDot();
|
||||
});
|
||||
</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(--next-bg-topBarColor);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
background: var(--next-color-user-hover);
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-dropdown) {
|
||||
color: var(--next-bg-topBarColor);
|
||||
}
|
||||
|
||||
:deep(.el-badge) {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.el-badge__content.is-fixed) {
|
||||
top: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user