修改侧边栏样式

This commit is contained in:
zhangxiaohua 2026-01-19 11:29:37 +08:00
parent a79b24b463
commit a8b9f658a0
3 changed files with 227 additions and 19 deletions

View File

@ -25,7 +25,7 @@ server {
# ========== 测试环境 - API 代理 ==========
location /api-test/ {
proxy_redirect off;
proxy_pass http://119.29.229.174:3234/;
proxy_pass http://119.29.229.174:3234/api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
@ -43,7 +43,7 @@ server {
# ========== 生产环境 - API 代理 ==========
location /api/ {
proxy_redirect off;
proxy_pass http://119.29.229.174:3234/;
proxy_pass http://119.29.229.174:3234/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

View File

@ -3,22 +3,38 @@
<a-layout-sider
v-if="!hideSidebar"
v-model:collapsed="collapsed"
:width="200"
:width="210"
class="custom-sider"
>
<div class="sider-content">
<div class="sider-top">
<div class="logo">
<img v-if="!collapsed" src="../assets/images/logo.png" alt="" />
<!-- <h2 v-if="!collapsed" class="logo-text">比赛管理系统</h2> -->
<h2 v-else class="logo-text">CMS</h2>
</div>
<!-- 3D建模实验室快捷入口 -->
<div
class="lab-entry"
:class="{ 'lab-entry-collapsed': collapsed }"
@click="open3DLab"
>
<div class="lab-entry-icon">
<experiment-outlined />
</div>
<div v-if="!collapsed" class="lab-entry-content">
<span class="lab-entry-title">3D建模实验室</span>
<span class="lab-entry-desc">AI智能建模</span>
</div>
<div v-if="!collapsed" class="lab-entry-arrow">
<right-outlined />
</div>
</div>
<a-menu
v-model:selectedKeys="selectedKeys"
v-model:openKeys="openKeys"
mode="inline"
class="custom-menu"
:items="menuItems"
:items="filteredMenuItems"
@click="handleMenuClick"
/>
</div>
@ -70,6 +86,8 @@ import {
MenuFoldOutlined,
MenuUnfoldOutlined,
LogoutOutlined,
ExperimentOutlined,
RightOutlined,
} from "@ant-design/icons-vue"
import { useAuthStore } from "@/stores/auth"
import { convertMenusToMenuItems } from "@/utils/menu"
@ -101,6 +119,26 @@ const menuItems = computed<MenuProps["items"]>(() => {
return []
})
// 3D
const filteredMenuItems = computed<MenuProps["items"]>(() => {
const items = menuItems.value || []
return items.filter((item: any) => {
// 3D
const is3DLab =
item?.key?.toLowerCase().includes("3dlab") ||
item?.key?.toLowerCase().includes("3d-lab") ||
item?.label?.includes("3D建模") ||
item?.title?.includes("3D建模")
return !is3DLab
})
})
// 3D
const open3DLab = () => {
const tenantCode = route.params.tenantCode as string
router.push(`/${tenantCode}/workbench/3d-lab`)
}
watch(
() => route.name,
(routeName) => {
@ -110,7 +148,7 @@ watch(
const findParentKeys = (
menus: any[],
targetName: string,
parentKeys: string[] = []
parentKeys: string[] = [],
): string[] => {
for (const menu of menus) {
const menuKey = menu.key
@ -129,14 +167,14 @@ watch(
}
const parentKeys = findParentKeys(
menuItems.value || [],
routeName as string
routeName as string,
)
if (parentKeys.length > 0) {
openKeys.value = parentKeys
}
}
},
{ immediate: true }
{ immediate: true },
)
const handleMenuClick = ({ key }: { key: string }) => {
@ -179,7 +217,7 @@ const handleMenuClick = ({ key }: { key: string }) => {
"is3DLabByPath:",
is3DLabByPath,
"menuItem:",
menuItem
menuItem,
)
if (is3DLab || is3DLabByPath) {
@ -255,7 +293,6 @@ $primary-light: #40a9ff;
align-items: center;
justify-content: center;
padding: 16px 12px;
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
margin-bottom: 8px;
img {
@ -273,6 +310,92 @@ $primary-light: #40a9ff;
}
}
// 3D
.lab-entry {
display: flex;
align-items: center;
gap: 12px;
margin: 8px 0 16px 0;
padding: 12px 14px;
background: linear-gradient(
135deg,
rgba($primary, 0.08) 0%,
rgba($primary, 0.15) 100%
);
border: 1px solid rgba($primary, 0.2);
border-radius: 12px;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
background: linear-gradient(
135deg,
rgba($primary, 0.12) 0%,
rgba($primary, 0.22) 100%
);
border-color: rgba($primary, 0.35);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba($primary, 0.15);
}
.lab-entry-icon {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
border-radius: 10px;
color: #fff;
font-size: 18px;
flex-shrink: 0;
}
.lab-entry-content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
.lab-entry-title {
font-size: 14px;
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
line-height: 1.3;
}
.lab-entry-desc {
font-size: 12px;
color: rgba(0, 0, 0, 0.45);
line-height: 1.2;
}
}
.lab-entry-arrow {
color: rgba(0, 0, 0, 0.35);
font-size: 12px;
transition: all 0.3s;
}
&:hover .lab-entry-arrow {
color: $primary;
transform: translateX(2px);
}
}
.lab-entry-collapsed {
justify-content: center;
padding: 12px;
margin: 8px 4px 16px 4px;
.lab-entry-icon {
width: 32px;
height: 32px;
font-size: 16px;
}
}
//
.sider-bottom {
padding: 12px 16px;
@ -384,13 +507,13 @@ $primary-light: #40a9ff;
}
&.ant-menu-item-selected {
color: #fff !important;
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
color: $primary !important;
background: rgba($primary, 0.12) !important;
font-weight: 500;
box-shadow: 0 2px 8px rgba($primary, 0.3);
box-shadow: none;
.anticon {
color: #fff;
color: $primary;
}
&::after {
@ -449,8 +572,13 @@ $primary-light: #40a9ff;
margin: 2px 0;
&.ant-menu-item-selected {
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
box-shadow: 0 2px 8px rgba($primary, 0.3);
color: $primary !important;
background: rgba($primary, 0.12) !important;
box-shadow: none;
.anticon {
color: $primary;
}
}
}
}
@ -461,8 +589,12 @@ $primary-light: #40a9ff;
transition: all 0.3s;
}
:deep(.ant-menu-submenu-open > .ant-menu-submenu-title > .ant-menu-submenu-arrow),
:deep(.ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow) {
:deep(
.ant-menu-submenu-open > .ant-menu-submenu-title > .ant-menu-submenu-arrow
),
:deep(
.ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow
) {
color: $primary;
}
}

View File

@ -1,5 +1,17 @@
<template>
<div class="ai-3d-container">
<!-- 页面加载中 -->
<div v-if="pageLoading" class="page-loading">
<div class="loading-content">
<div class="loading-logo">
<div class="logo-spinner"></div>
<ThunderboltOutlined class="logo-icon-center" />
</div>
<h3>AI 3D Studio</h3>
<p>正在加载...</p>
</div>
</div>
<!-- Animated Background -->
<div class="bg-animation">
<div class="bg-gradient bg-gradient-1"></div>
@ -420,6 +432,9 @@ const currentSampleIndex = ref(0)
const generateType = ref<"Normal" | "LowPoly" | "Geometry" | "Sketch">("Normal")
const faceCount = ref(500000)
//
const pageLoading = ref(true)
//
const historyList = ref<AI3DTask[]>([])
const historyLoading = ref(false)
@ -738,7 +753,12 @@ const updateGridWidth = () => {
//
onMounted(async () => {
await fetchHistory()
try {
await fetchHistory()
} finally {
//
pageLoading.value = false
}
// DOM
await nextTick()
@ -810,6 +830,62 @@ $gradient-secondary: linear-gradient(135deg, $primary-light 0%, $primary 100%);
align-items: stretch;
}
//
.page-loading {
position: fixed;
inset: 0;
background: $background;
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
.loading-content {
text-align: center;
h3 {
margin: 20px 0 8px;
font-size: 20px;
font-weight: 700;
background: $gradient-primary;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
p {
margin: 0;
font-size: 14px;
color: $text-muted;
}
}
.loading-logo {
position: relative;
width: 80px;
height: 80px;
margin: 0 auto;
.logo-spinner {
position: absolute;
inset: 0;
border: 3px solid rgba($primary, 0.1);
border-top-color: $primary;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.logo-icon-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 32px;
color: $primary;
}
}
}
// ==========================================
// -
// ==========================================