初始版本

This commit is contained in:
2026-04-23 17:14:29 +08:00
parent 0d0683a6e6
commit 6dca87b988
204 changed files with 3894 additions and 52759 deletions

View File

@@ -6,8 +6,7 @@
<div class="flex items-center gap-8 nav-left">
<!-- Logo -->
<NuxtLink to="/" class="flex items-center logo-link cursor-pointer flex-shrink-0">
<img src="/logo.png" alt="websopy" class="logo-img" />
<div class="site-name mx-2">{{ 'websopy' }}</div>
<div class="logo-text">决策咨询网</div>
</NuxtLink>
<!-- PC 导航菜单 -->
@@ -63,26 +62,10 @@
<template #overlay>
<a-menu @click="onUserMenuClick">
<a-menu-item key="profile"><ProfileOutlined style="margin-right: 8px" />个人信息</a-menu-item>
<a-menu-item key="orders"><ShoppingCartOutlined style="margin-right: 8px" />我的订单</a-menu-item>
<a-menu-item key="account-kyc">
<IdcardOutlined style="margin-right: 8px" />
实名认证
</a-menu-item>
<template v-if="isDeveloper">
<a-menu-divider />
<a-menu-item key="developer">🛠 {{ $t('nav.developer') || '开发者中心' }}</a-menu-item>
<a-menu-item key="env-dev" @click.stop="switchEnv('dev')">
<span :class="{ 'font-bold': currentEnv === 'dev' }">🔧 {{ $t('common.devEnv') || '开发环境' }}</span>
<span v-if="currentEnv === 'dev'" class="ml-2 text-green-500"></span>
</a-menu-item>
<a-menu-item key="env-prod" @click.stop="switchEnv('prod')">
<span :class="{ 'font-bold': currentEnv === 'prod' }">🚀 {{ $t('common.prodEnv') || '生产环境' }}</span>
<span v-if="currentEnv === 'prod'" class="ml-2 text-green-500"></span>
</a-menu-item>
</template>
<a-menu-item key="my-suggestions"><MessageOutlined style="margin-right: 8px" />我的建言</a-menu-item>
<template v-if="isSuperAdmin">
<a-menu-divider />
<a-menu-item key="admin"> 台管理</a-menu-item>
<a-menu-item key="admin"> 台管理</a-menu-item>
</template>
<a-menu-divider />
<a-menu-item key="logout">{{ $t('nav.logout') }}</a-menu-item>
@@ -141,37 +124,26 @@ import { getUserInfo } from '@/api/layout'
import type { User } from '@/api/system/user/model'
import { getToken, removeToken } from '@/utils/token-util'
import { clearAuthz, setAuthzFromUser } from '@/utils/permission'
import { UserOutlined, ProfileOutlined, IdcardOutlined, ShoppingCartOutlined } from '@ant-design/icons-vue'
import { UserOutlined, ProfileOutlined, MessageOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { ENV_CONFIG, getCurrentEnv, setCurrentEnv, type EnvKey } from '@/config/setting'
import InviteBell from './invite/InviteBell.vue'
const nav = computed(() => mainNav)
const route = useRoute()
const open = ref(false)
// 环境切换
const currentEnv = ref<EnvKey>(getCurrentEnv())
function switchEnv(env: EnvKey) {
setCurrentEnv(env)
currentEnv.value = env
// 同时设置 Cookie让服务器端代理也能识别环境
const cookieValue = env === 'dev' ? 'dev' : 'prod'
document.cookie = `websopy_api_env=${cookieValue}; path=/; max-age=31536000`
message.success(`已切换到 ${ENV_CONFIG[env].name},正在刷新...`)
setTimeout(() => {
window.location.reload()
}, 500)
}
const selectedKeys = computed(() => {
const hit = nav.value.find((n) => n.to === route.path)
if (hit) return [hit.to]
if (route.path.startsWith('/products')) return ['/products']
if (route.path.startsWith('/ai-agent')) return ['/ai-agent']
if (route.path.startsWith('/news')) return ['/news']
if (route.path.startsWith('/consultation')) return ['/consultation']
if (route.path.startsWith('/reference')) return ['/reference']
if (route.path.startsWith('/expert')) return ['/expert']
if (route.path.startsWith('/think-tank')) return ['/think-tank']
if (route.path.startsWith('/suggestions')) return ['/suggestions']
if (route.path.startsWith('/membership')) return ['/membership']
if (route.path.startsWith('/hanmo')) return ['/hanmo']
if (route.path.startsWith('/about')) return ['/about']
return ['/']
})
@@ -194,7 +166,6 @@ const user = ref<User | null>(null)
const isAuthed = computed(() => !!token.value)
const userName = computed(() => String(user.value?.nickname || user.value?.username || '已登录'))
const isSuperAdmin = computed(() => !!(user.value as any)?.isAdmin)
const isDeveloper = computed(() => (user.value as any)?.type === 2)
const userAvatar = computed(() => {
const candidate =
user.value?.avatarUrl ||
@@ -232,13 +203,7 @@ async function refreshAuth() {
function goConsoleCenter() {
if (!isAuthed.value) return navigateTo('/login')
open.value = false
navigateTo('/console')
}
function goDeveloperCenter() {
if (!isAuthed.value) return navigateTo('/login')
open.value = false
navigateTo('/developer')
navigateTo('/profile')
}
function logout() {
@@ -257,10 +222,8 @@ function logout() {
}
function onUserMenuClick(info: { key: string }) {
if (info.key === 'profile') return navigateTo('/console/account')
if (info.key === 'orders') return navigateTo('/console/orders')
if (info.key === 'account-kyc') return navigateTo('/console/account/kyc')
if (info.key === 'developer') return navigateTo('/developer')
if (info.key === 'profile') return navigateTo('/profile')
if (info.key === 'my-suggestions') return navigateTo('/my/suggestions')
if (info.key === 'admin') return navigateTo('/admin')
if (info.key === 'logout') return logout()
}
@@ -312,16 +275,10 @@ onUnmounted(() => {
display: flex;
align-items: center;
}
.logo-img {
height: 22px;
width: auto;
display: block;
transition: opacity 0.2s;
}
.site-name {
.logo-text {
color: #fff;
font-family: 'Alimama FangYuanTi VF,sans-serif', sans-serif;
font-size: 18px;
font-size: 20px;
font-weight: 700;
letter-spacing: 0.04em;
white-space: nowrap;
@@ -332,10 +289,7 @@ onUnmounted(() => {
background-clip: text;
transition: opacity 0.2s;
}
.logo-link:hover .site-name {
opacity: 0.85;
}
.logo-link:hover .logo-img {
.logo-link:hover .logo-text {
opacity: 0.85;
}
.nav-item-wrapper {