修改侧边栏样式
This commit is contained in:
parent
a79b24b463
commit
a8b9f658a0
@ -25,7 +25,7 @@ server {
|
|||||||
# ========== 测试环境 - API 代理 ==========
|
# ========== 测试环境 - API 代理 ==========
|
||||||
location /api-test/ {
|
location /api-test/ {
|
||||||
proxy_redirect off;
|
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_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
@ -43,7 +43,7 @@ server {
|
|||||||
# ========== 生产环境 - API 代理 ==========
|
# ========== 生产环境 - API 代理 ==========
|
||||||
location /api/ {
|
location /api/ {
|
||||||
proxy_redirect off;
|
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_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
|||||||
@ -3,22 +3,38 @@
|
|||||||
<a-layout-sider
|
<a-layout-sider
|
||||||
v-if="!hideSidebar"
|
v-if="!hideSidebar"
|
||||||
v-model:collapsed="collapsed"
|
v-model:collapsed="collapsed"
|
||||||
:width="200"
|
:width="210"
|
||||||
class="custom-sider"
|
class="custom-sider"
|
||||||
>
|
>
|
||||||
<div class="sider-content">
|
<div class="sider-content">
|
||||||
<div class="sider-top">
|
<div class="sider-top">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img v-if="!collapsed" src="../assets/images/logo.png" alt="" />
|
<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>
|
<h2 v-else class="logo-text">CMS</h2>
|
||||||
</div>
|
</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
|
<a-menu
|
||||||
v-model:selectedKeys="selectedKeys"
|
v-model:selectedKeys="selectedKeys"
|
||||||
v-model:openKeys="openKeys"
|
v-model:openKeys="openKeys"
|
||||||
mode="inline"
|
mode="inline"
|
||||||
class="custom-menu"
|
class="custom-menu"
|
||||||
:items="menuItems"
|
:items="filteredMenuItems"
|
||||||
@click="handleMenuClick"
|
@click="handleMenuClick"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -70,6 +86,8 @@ import {
|
|||||||
MenuFoldOutlined,
|
MenuFoldOutlined,
|
||||||
MenuUnfoldOutlined,
|
MenuUnfoldOutlined,
|
||||||
LogoutOutlined,
|
LogoutOutlined,
|
||||||
|
ExperimentOutlined,
|
||||||
|
RightOutlined,
|
||||||
} from "@ant-design/icons-vue"
|
} from "@ant-design/icons-vue"
|
||||||
import { useAuthStore } from "@/stores/auth"
|
import { useAuthStore } from "@/stores/auth"
|
||||||
import { convertMenusToMenuItems } from "@/utils/menu"
|
import { convertMenusToMenuItems } from "@/utils/menu"
|
||||||
@ -101,6 +119,26 @@ const menuItems = computed<MenuProps["items"]>(() => {
|
|||||||
return []
|
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(
|
watch(
|
||||||
() => route.name,
|
() => route.name,
|
||||||
(routeName) => {
|
(routeName) => {
|
||||||
@ -110,7 +148,7 @@ watch(
|
|||||||
const findParentKeys = (
|
const findParentKeys = (
|
||||||
menus: any[],
|
menus: any[],
|
||||||
targetName: string,
|
targetName: string,
|
||||||
parentKeys: string[] = []
|
parentKeys: string[] = [],
|
||||||
): string[] => {
|
): string[] => {
|
||||||
for (const menu of menus) {
|
for (const menu of menus) {
|
||||||
const menuKey = menu.key
|
const menuKey = menu.key
|
||||||
@ -129,14 +167,14 @@ watch(
|
|||||||
}
|
}
|
||||||
const parentKeys = findParentKeys(
|
const parentKeys = findParentKeys(
|
||||||
menuItems.value || [],
|
menuItems.value || [],
|
||||||
routeName as string
|
routeName as string,
|
||||||
)
|
)
|
||||||
if (parentKeys.length > 0) {
|
if (parentKeys.length > 0) {
|
||||||
openKeys.value = parentKeys
|
openKeys.value = parentKeys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleMenuClick = ({ key }: { key: string }) => {
|
const handleMenuClick = ({ key }: { key: string }) => {
|
||||||
@ -179,7 +217,7 @@ const handleMenuClick = ({ key }: { key: string }) => {
|
|||||||
"is3DLabByPath:",
|
"is3DLabByPath:",
|
||||||
is3DLabByPath,
|
is3DLabByPath,
|
||||||
"menuItem:",
|
"menuItem:",
|
||||||
menuItem
|
menuItem,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (is3DLab || is3DLabByPath) {
|
if (is3DLab || is3DLabByPath) {
|
||||||
@ -255,7 +293,6 @@ $primary-light: #40a9ff;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 16px 12px;
|
padding: 16px 12px;
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
|
||||||
img {
|
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 {
|
.sider-bottom {
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
@ -384,13 +507,13 @@ $primary-light: #40a9ff;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.ant-menu-item-selected {
|
&.ant-menu-item-selected {
|
||||||
color: #fff !important;
|
color: $primary !important;
|
||||||
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
|
background: rgba($primary, 0.12) !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
box-shadow: 0 2px 8px rgba($primary, 0.3);
|
box-shadow: none;
|
||||||
|
|
||||||
.anticon {
|
.anticon {
|
||||||
color: #fff;
|
color: $primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
@ -449,8 +572,13 @@ $primary-light: #40a9ff;
|
|||||||
margin: 2px 0;
|
margin: 2px 0;
|
||||||
|
|
||||||
&.ant-menu-item-selected {
|
&.ant-menu-item-selected {
|
||||||
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
|
color: $primary !important;
|
||||||
box-shadow: 0 2px 8px rgba($primary, 0.3);
|
background: rgba($primary, 0.12) !important;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -461,8 +589,12 @@ $primary-light: #40a9ff;
|
|||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.ant-menu-submenu-open > .ant-menu-submenu-title > .ant-menu-submenu-arrow),
|
:deep(
|
||||||
:deep(.ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow) {
|
.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;
|
color: $primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ai-3d-container">
|
<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 -->
|
<!-- Animated Background -->
|
||||||
<div class="bg-animation">
|
<div class="bg-animation">
|
||||||
<div class="bg-gradient bg-gradient-1"></div>
|
<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 generateType = ref<"Normal" | "LowPoly" | "Geometry" | "Sketch">("Normal")
|
||||||
const faceCount = ref(500000)
|
const faceCount = ref(500000)
|
||||||
|
|
||||||
|
// 页面加载状态
|
||||||
|
const pageLoading = ref(true)
|
||||||
|
|
||||||
// 历史记录
|
// 历史记录
|
||||||
const historyList = ref<AI3DTask[]>([])
|
const historyList = ref<AI3DTask[]>([])
|
||||||
const historyLoading = ref(false)
|
const historyLoading = ref(false)
|
||||||
@ -738,7 +753,12 @@ const updateGridWidth = () => {
|
|||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
await fetchHistory()
|
await fetchHistory()
|
||||||
|
} finally {
|
||||||
|
// 确保页面加载状态关闭
|
||||||
|
pageLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 等待 DOM 更新后计算容器宽度
|
// 等待 DOM 更新后计算容器宽度
|
||||||
await nextTick()
|
await nextTick()
|
||||||
@ -810,6 +830,62 @@ $gradient-secondary: linear-gradient(135deg, $primary-light 0%, $primary 100%);
|
|||||||
align-items: stretch;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 简化背景动画 - 保留微妙效果
|
// 简化背景动画 - 保留微妙效果
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user