You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ocr-web/src/layout/components/Header/index.vue

304 lines
6.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script lang="ts">
import { useUser } from "@/store/modules/user";
import { getImgUrl } from "@/utils/urlUtils";
import { useDialog, useMessage } from "naive-ui";
import { defineComponent, reactive, ref, toRefs, unref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import QuillModal from "./QuillModal.vue";
import RecycleModal from "./RecycleModal.vue";
import SearchModal from "./SearchModal.vue";
import ShortcutModal from "./ShortcutModal.vue";
import UserSettings from "./UserSettings.vue";
export default defineComponent({
name: "PageHeader",
components: {
UserSettings,
QuillModal,
ShortcutModal,
RecycleModal,
SearchModal,
},
props: {
collapsed: {
type: Boolean,
},
inverted: {
type: Boolean,
},
},
emits: ["update:collapsed"],
setup() {
const message = useMessage();
const dialog = useDialog();
const userStore = useUser();
const useInfo = userStore.getUserInfo;
const name = "";
const state = reactive({
username: name ?? "",
fullscreenIcon: "FullscreenOutlined",
});
const router = useRouter();
const route = useRoute();
const routename = ref(route.meta.title);
watch(
() => route.fullPath,
() => {
routename.value = route.meta.title;
}
);
const dropdownSelect = (key) => {
router.push({ name: key });
};
// 退出登录
const doLogout = () => {
dialog.info({
title: "提示",
content: "您确定要退出登录吗",
positiveText: "确定",
negativeText: "取消",
onPositiveClick: () => {
userStore.logout().then(() => {
message.success("成功退出登录");
router
.replace({
name: "Login",
query: {
redirect: route.fullPath,
},
})
.finally(() => location.reload());
});
},
onNegativeClick: () => {},
});
};
const quillModalRef = ref(null);
const shortcutModal = ref(null);
const recycleModalRef = ref(null);
const SearchModalRef = ref(null);
function quillHandler() {
const modal = unref(quillModalRef)! as any;
modal.showModal();
}
function shortcutHandler() {
const modal = unref(shortcutModal)! as any;
modal.showModal();
}
function recycleHandler() {
const modal = unref(recycleModalRef)! as any;
modal.showModal();
}
function searchHandler() {
const modal = unref(SearchModalRef)! as any;
modal.showModal();
}
// 图标列表
const iconList = [
{
icon: "magnifying-1",
handle: searchHandler,
},
{
icon: "shortcut-keys",
handle: shortcutHandler,
},
{
icon: "suspicious-folder",
handle: recycleHandler,
},
{
icon: "memo",
handle: quillHandler,
},
{
icon: "newmessage",
handle: shortcutHandler,
},
];
return {
...toRefs(state),
iconList,
doLogout,
dropdownSelect,
routename,
quillModalRef,
shortcutModal,
recycleModalRef,
SearchModalRef,
searchHandler,
quillHandler,
shortcutHandler,
recycleHandler,
useInfo,
getImgUrl,
};
},
});
</script>
<template>
<div class="layout-header">
<!-- 左侧菜单 -->
<div class="layout-header-left">
<!-- 菜单收起 -->
<div
class="ml-1 layout-header-trigger layout-header-trigger-min"
@click="() => $emit('update:collapsed', !collapsed)"
>
<SvgIcon name="homepage" size="16" />
</div>
<div>当前位置{{ routename }}</div>
</div>
<div class="layout-header-right">
<div
v-for="item in iconList"
:key="item.icon"
class="layout-header-trigger layout-header-trigger-min"
>
<div class="back" @click="item.handle">
<SvgIcon :name="item.icon" size="18" />
</div>
</div>
<!-- 个人中心 -->
<div class="layout-header-trigger layout-header-trigger-min">
<n-avatar :src="getImgUrl(useInfo.usericon)" round />
</div>
<!-- 设置 -->
<UserSettings @logout="doLogout" />
</div>
</div>
<RecycleModal ref="recycleModalRef" />
<QuillModal ref="quillModalRef" />
<ShortcutModal ref="shortcutModal" />
<SearchModal ref="SearchModalRef" />
</template>
<style lang="less" scoped>
.layout-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0;
height: 64px;
transition: all 0.2s ease-in-out;
width: 100%;
z-index: 11;
&-left {
display: flex;
align-items: center;
color: #666666;
.logo {
display: flex;
align-items: center;
justify-content: center;
height: 64px;
line-height: 64px;
overflow: hidden;
white-space: nowrap;
padding-left: 10px;
img {
width: auto;
height: 32px;
margin-right: 10px;
}
.title {
margin-bottom: 0;
}
}
}
&-right {
display: flex;
align-items: center;
margin-right: 20px;
.back {
width: 28px;
height: 28px;
background: #ffffff;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
}
.avatar {
display: flex;
align-items: center;
height: 64px;
}
> * {
cursor: pointer;
}
}
&-trigger {
display: flex;
width: 64px;
height: 64px;
align-items: center;
text-align: center;
cursor: pointer;
transition: all 0.2s ease-in-out;
&:hover {
background: hsla(0, 0%, 100%, 0.08);
}
.anticon {
font-size: 16px;
color: #515a6e;
}
}
&-trigger-min {
width: auto;
padding: 0 5px;
}
}
.layout-header-light {
background: #fff;
color: #515a6e;
.n-icon {
color: #515a6e;
}
.layout-header-left {
::v-deep(
.n-breadcrumb .n-breadcrumb-item:last-child .n-breadcrumb-item__link
) {
color: #515a6e;
}
}
}
.user-dropdown {
display: flex;
flex-direction: row;
align-items: center;
}
</style>