mcwl-pc/app/components/Header.vue

383 lines
11 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: any) => {
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: '0',
},
{
label: '我的作品',
key: '2',
},
{
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)
}
}
else if (key === 'like') {
router.push(`/personal-center?type=${key}`)
}
else {
router.push(`/personal-center?status=${key}`)
}
}
// 发布下拉选项
async function handlePublishSelect(key: string) {
if (!userStore?.userInfo.name)
return
if (!userStore.isLoggedIn) {
modalStore.showLoginModal()
}
else {
if (key === 'picture') {
isShowPublishPicture.value = true
if (PublishPictureRef.value) {
PublishPictureRef.value.isVisible = true
}
}
else {
const baseUrl = window.location.origin
debugger
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">
<div class="flex items-center cursor-pointer" @click="handleTabClick('/')">
<img
src="@/assets/img/logo.png"
alt="魔创未来"
class="h-8 w-8"
>
<span class="text-[#328AFE] text-xl font-bold ml-2">魔创未来</span>
</div>
<NuxtLink to="/" class="text-xl font-semibold tracking-tight no-underline">
<!-- <img src="/vite.png" alt="Logo" class="h-9 w-9" /> -->
<!-- 魔创未来 -->
<!-- <img
src="https://liblibai-web-static.liblib.cloud/liblibai_v4_online/static/_next/static/images/icon-logo.e3ce24f316fb81dbde1cafc3bf956080.svg"
alt=""
/> -->
<!-- <a class="Topbar_iconLogo__RhuYB" style="background-image: url(&quot;https://liblibai-web-static.liblib.cloud/liblibai_v4_online/static/_next/static/images/icon-logo.e3ce24f316fb81dbde1cafc3bf956080.svg&quot;);"></a> -->
</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 -->
<div class="header-btn-primary">
<Monitor class="h-4 w-4 mr-1" />
<span>PC客户端</span>
</div>
<!-- <NButton text class="header-btn-primary">
</NButton> -->
<!-- Tutorials -->
<NButton text class="header-btn">
<GraduationCap class="h-4 w-4 mr-1" />
<span>教程专区</span>
</NButton>
<!-- <div class="header-btn">
<GraduationCap class="h-4 w-4 mr-1" />
<span>教程专区</span>
</div> -->
<NDropdown
:options="publishOptions"
trigger="hover"
:on-select="handlePublishSelect"
>
<NButton text class="header-btn" size="large">
<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> -->
<client-only v-if="userStore.token">
<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-4 text-sm font-bold"
>
通知
</div>
<div class="px-4 py-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
v-if="item.isRead === '0'"
class="w-2 h-2 bg-[#ea5049] rounded"
/>
</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>
</client-only>
<!-- User -->
<div class="min-w-10 flex items-center">
<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-gradient-to-r from-[#197dff] to-[#2c4dff] 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] flex items-center cursor-pointer;
}
.header-btn {
@apply bg-[#f1f1f7] font-bold px-2 py-2 rounded flex items-center hover:text-black hover:bg-[#f1f1f7] focus:text-blue-600;
}
</style>