mcwl-pc/app/components/Header.vue

337 lines
9.1 KiB
Vue

<script setup lang="ts">
// 输入框搜索
import { headerRole } from "@/constants/index";
import {
Bell,
CirclePlus,
GraduationCap,
HardDriveUpload,
Image,
Monitor,
Workflow
} from "lucide-vue-next";
import { NConfigProvider, NMessageProvider } from "naive-ui";
// import { AtCircle } from '@vicons/ionicons5'
import { NIcon } from "naive-ui";
import { onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const modalStore = useModalStore();
const currentUseRoute = ref("");
const isShowPublishPicture = ref<boolean>(false);
const PublishPictureRef = ref<Payment | null>(null);
const publishPicture = ref({
title: "",
tags: [],
description: "",
imagePaths: [],
});
watch(
() => route.path, // 监听 route.path 的变化
(newPath) => {
currentUseRoute.value = newPath;
},
{ immediate: true } // 立即执行一次
);
function hasItem(path: string, list: any) {
return !list.includes(path);
}
const searchText = ref("");
function onSearch(value: any) {
console.log("搜索:", value);
// 执行搜索逻辑
}
// 用户下拉选项
const notificationOptions = [
{
label: "系统通知",
key: "system",
},
{
label: "互动消息",
key: "interaction",
},
];
function renderIcon(icon: Component) {
return () => {
return h(NIcon, null, {
default: () => h(icon),
});
};
}
// 发布下拉选项
const publishOptions = [
{
label: "模型",
key: "publish-model",
icon: renderIcon(HardDriveUpload),
},
{
label: "图片",
key: "picture",
icon: renderIcon(Image),
},
{
label: "工作流",
key: "publish-workflow",
icon: renderIcon(Workflow),
},
];
const userOptions = ref([
{
label: "我的模型",
key: "model",
},
{
label: "我的作品",
key: "project",
},
{
label: "我的点赞",
key: "like",
},
{
label: "账号设置",
key: "userSettings",
},
{
label: "退出登录",
key: "logout",
},
]);
// 用户下拉选项
async function handleUserSelect(key: string) {
if (key === "logout") {
try {
await request.post("/logout");
userStore.logout();
navigateTo("/model-square");
} catch (error) {
console.error("Logout failed:", error);
}
}
}
// 发布下拉选项
async function handlePublishSelect(key: string) {
if (key === "picture") {
isShowPublishPicture.value = true;
if (PublishPictureRef.value) {
PublishPictureRef.value.isVisible = true;
}
} else {
const baseUrl = window.location.origin;
window.open(`${baseUrl}/${key}?type=add`, "_blank", "noopener,noreferrer");
// router.push({
// path: `/${key}`,
// query: {
// type: 'add',
// },
// })
}
}
function closePublishImg() {
isShowPublishPicture.value = false;
if (PublishPictureRef.value) {
PublishPictureRef.value.isVisible = false;
}
}
function handleLogin() {
modalStore.showLoginModal();
}
const msgList = ref([]);
async function getAllMessage() {
try {
const res = await request.get("/advice/getAllMsg");
if (res.code == 200) {
msgList.value = res.data;
}
} catch (err) {
console.log(err);
}
}
getAllMessage();
// 跳转到消息详情
function toDetail(){
const baseUrl = window.location.origin
window.open(`${baseUrl}/message`, '_blank', 'noopener,noreferrer')
}
onMounted(() => {});
</script>
<template>
<div>
<header
class="sticky top-0 z-50 flex h-12 items-center justify-between border-b border-gray-100 bg-white/80 px-6 backdrop-blur dark:border-dark-700 dark:bg-dark-800/80"
>
<div class="flex items-center gap-6">
<!-- Logo 区域调整 -->
<div class="flex min-w-[130px] items-center gap-3 pr-4">
<div class="flex items-center gap-2">
<NuxtLink to="/" class="text-xl font-semibold tracking-tight no-underline">
<!-- <img src="/vite.png" alt="Logo" class="h-9 w-9" /> -->
魔创未来
</NuxtLink>
<!-- <span class="text-xl font-semibold tracking-tight">魔创未来</span> -->
</div>
</div>
<!-- <HeaderSearchInput /> -->
<HeaderSearchInput
v-if="hasItem(currentUseRoute, headerRole.inputSearch)"
v-model="searchText"
@search="onSearch"
/>
</div>
<!-- Right Actions -->
<NSpace align="center" :size="24">
<!-- PC Client -->
<NButton text class="header-btn-primary">
<Monitor class="h-4 w-4 mr-1" />
<span>PC客户端</span>
</NButton>
<!-- Tutorials -->
<NButton text class="header-btn">
<GraduationCap class="h-4 w-4 mr-1" />
<span>教程专区</span>
</NButton>
<NDropdown
:options="publishOptions"
trigger="hover"
:on-select="handlePublishSelect"
>
<NButton text class="header-btn">
<CirclePlus class="h-4 w-4 mr-1" />
<span>发布</span>
</NButton>
</NDropdown>
<!-- Notifications -->
<!-- :options="notificationOptions" -->
<!-- <NDropdown trigger="click">
<NBadge :value="5" :max="99" processing>
<NButton text circle>
<Bell class="h-5 w-5 mr-1 relative" />
<div class="absolute top-2 right-1 border-solid border-2 border-[#f0f0f0] py-2">
<div class="border-b-solid border-b-2 border-b-[#f0f0f0]">
通知
</div>
<div v-for="(item,index) in 3">
1111
</div>
</div>
</NButton>
</NBadge>
</NDropdown> -->
<div
class="p-1 bg-[#f1f1f6] rounded-full flex items-center justify-center relative group"
>
<Bell class="h-5 w-5relative cursor-pointer" @mouseenter="getAllMessage" />
<div class="pt-4 absolute top-5 -right-4 hidden group-hover:block">
<div
class="border-solid border border-[#f0f0f0] py-2 w-[300px] rounded-lg bg-white"
>
<div
class="border-b-solid border-b border-b-[#f0f0f0] p-2 text-sm font-bold"
>
通知
</div>
<div class="p-2 max-h-[300px] overflow-y-auto">
<div
v-for="(item, index) in msgList"
:key="index"
class="flex items-center my-2 cursor-pointer"
>
<div class="flex-1">
<n-ellipsis
style="max-width: 250px"
:tooltip="false"
class="font-bold text-gray-600"
>
{{ item.content }}
</n-ellipsis>
<div class="text-[12px] text-gray-400">{{ item.createTime }}</div>
</div>
<div class="w-4 flex h-[100%] items-center justify-center">
<div
class="w-2 h-2 bg-[#ea5049] rounded"
v-if="item.isRead === '0'"
></div>
</div>
</div>
</div>
<div class="my-4 text-gray-500 text-sm text-center">
更多通知可点击查看全部~
</div>
<div class="flex justify-center">
<div class="bg-[#4c79ee] w-[270px] h-10 flex items-center justify-center rounded-lg text-white cursor-pointer" @click="toDetail">
查看全部
</div>
</div>
</div>
</div>
</div>
<!-- User -->
<div class="min-w-10">
<client-only>
<NDropdown
v-if="userStore.token"
:options="userOptions"
:on-select="handleUserSelect"
trigger="hover"
>
<NAvatar
class="cursor-pointer w-10 h-10"
round
size="small"
:src="userStore.userInfo.avatar"
/>
</NDropdown>
<div
v-if="!userStore.token"
class="flex text-white bg-[#197dff] rounded-[4px] px-4 py-2 text-xs cursor-pointer hover:bg-[#1a6eff]"
@click="handleLogin"
>
登录/注册
</div>
</client-only>
</div>
</NSpace>
</header>
<div>
<NConfigProvider>
<NMessageProvider>
<Publish-picture
v-if="isShowPublishPicture"
ref="PublishPictureRef"
type="add"
:form-data="publishPicture"
@close-publish-img="closePublishImg"
/>
</NMessageProvider>
</NConfigProvider>
</div>
</div>
</template>
<style scoped>
.header-btn-primary {
@apply border border-solid border-[#3162ff] px-1 py-1 text-[#3162ff] rounded-md hover:text-[#3162ff];
}
.header-btn {
@apply bg-[#f1f1f7] font-bold px-2 py-2 rounded flex items-center hover:text-black hover:bg-[#f1f1f7];
}
</style>