Browse Source

图片和菜单

yangrongze
hanyuqing 3 months ago
parent
commit
0fdc892425
  1. BIN
      vue/src/assets/右侧白色.png
  2. BIN
      vue/src/assets/图标1.png
  3. BIN
      vue/src/assets/图标2.png
  4. BIN
      vue/src/assets/图标3.png
  5. BIN
      vue/src/assets/图标4.png
  6. BIN
      vue/src/assets/左二框.png
  7. BIN
      vue/src/assets/左侧栏.png
  8. BIN
      vue/src/assets/打开.png
  9. BIN
      vue/src/assets/搜索.png
  10. BIN
      vue/src/assets/搜索框.png
  11. BIN
      vue/src/assets/收缩.png
  12. BIN
      vue/src/assets/组 10.png
  13. BIN
      vue/src/assets/退出.png
  14. BIN
      vue/src/assets/选中.png
  15. BIN
      vue/src/assets/鼠标滑过状态.png
  16. 676
      vue/src/components/Menu.vue

BIN
vue/src/assets/右侧白色.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

BIN
vue/src/assets/图标1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

BIN
vue/src/assets/图标2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
vue/src/assets/图标3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

BIN
vue/src/assets/图标4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

BIN
vue/src/assets/左二框.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
vue/src/assets/左侧栏.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
vue/src/assets/打开.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

BIN
vue/src/assets/搜索.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

BIN
vue/src/assets/搜索框.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
vue/src/assets/收缩.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

BIN
vue/src/assets/组 10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
vue/src/assets/退出.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

BIN
vue/src/assets/选中.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

BIN
vue/src/assets/鼠标滑过状态.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

676
vue/src/components/Menu.vue

@ -1,428 +1,450 @@
<template>
<div class="sidebar-container" :class="{ 'collapsed': isCollapsed }">
<!-- 折叠按钮 -->
<button @click="toggleCollapse" class="collapse-btn">
<span class="collapse-icon">{{ isCollapsed ? '▶' : '◀' }}</span>
</button>
<!-- 系统标题区域 -->
<div class="sidebar-header">
<h1 class="sidebar-title" v-show="!isCollapsed" @click="goToIndex">
面向疾病预测的知识图谱应用系统
</h1>
<h1 class="sidebar-title-collapsed" v-show="isCollapsed" @click="goToIndex">
医疗知识图谱
</h1>
</div>
<!-- 菜单列表 -->
<nav class="sidebar-nav">
<ul>
<li
v-for="(item, index) in menuItems"
:key="index"
class="menu-item"
<div class="admin-layout">
<aside class="sidebar" :class="{ 'is-collapsed': isCollapsed }">
<div class="sidebar-header">
<div class="header-content">
<div class="header-icon-wrap">
<img src="@/assets/logo.png" class="logo-img"/>
</div>
<div v-if="!isCollapsed" class="header-text-wrap">
<div class="title-line">面向疾病预测的知识图谱</div>
<div class="title-line">应用系统</div>
</div>
</div>
</div>
<nav class="menu-nav">
<div
v-for="(item, index) in menuItems"
:key="index"
class="menu-item"
:class="{ 'is-active': activeIndex === index }"
@click="handleMenuClick(index)"
>
<a
@click.prevent="handleMenuClick(index)"
class="menu-link"
:class="{ 'active': activeIndex === index }"
:title="isCollapsed ? item.name : ''"
>
<span class="menu-icon">{{ item.icon }}</span>
<span v-show="!isCollapsed">{{ item.name }}</span>
</a>
</li>
</ul>
</nav>
<!-- 底部用户信息和退出登录区域 -->
<div class="sidebar-footer">
<div class="user-info">
<div class="user-avatar">
<span class="avatar-text"></span>
<div class="highlight-box">
<div class="menu-content-fixed">
<div class="menu-icon-wrapper">
<img :src="item.icon" class="menu-icon-img"/>
</div>
<span v-if="!isCollapsed" class="menu-text">{{ item.name }}</span>
</div>
<img v-if="activeIndex === index && !isCollapsed" src="@/assets/右侧白色.png" class="active-tag"/>
</div>
</div>
<div v-if="!isCollapsed" class="collapse-handle" @click="isCollapsed = true">
<img src="@/assets/收缩.png" class="collapse-icon-img"/>
</div>
<div class="user-details" v-show="!isCollapsed">
<p class="user-name">管理员</p>
<p class="user-email">admin@example.com</p>
</nav>
<div class="sidebar-footer">
<div v-if="!isCollapsed" class="user-block">
<div class="avatar">用户</div>
<div class="info">
<div class="name">用户名字</div>
<div class="id">8866990099</div>
</div>
<div class="exit-wrap">
<img src="@/assets/退出.png" class="exit-icon" @click="handleLogout" alt="退出"/>
</div>
</div>
<div class="action-buttons" v-show="!isCollapsed">
<button @click="handleProfile" class="profile-btn-inline" title="个人主页">
个人主页
</button>
<button @click="handleLogout" class="logout-btn-inline" title="退出登录">
退出登录
</button>
<div v-else class="expand-handle-circle" @click="isCollapsed = false">
<img src="@/assets/打开.png" class="expand-icon-img-circle"/>
</div>
</div>
</div>
</aside>
<main class="main-body">
<header class="top-nav">
<div class="search-container">
<input type="text" placeholder="搜索......"/>
<img src="@/assets/搜索.png" class="search-btn"/>
</div>
<div class="legend-box">
<span v-for="c in ['#ffcc66','#4d79ff','#8cd98c','#ff8100','#6d31ce']" :key="c" class="leg-item">
<i :style="{background: c}"></i> 指定1
</span>
</div>
</header>
<section class="main-content">
<div class="disease-container">
<div class="disease-header">
<div class="d-title"><img src="@/assets/组 10.png" class="d-icon"/><span>疾病信息</span></div>
<div class="d-count">12</div>
</div>
<div class="disease-body">
<div class="checkbox-list">
<label v-for="i in ['选项一','选项二','选项三']" :key="i">
<input type="checkbox"/><span class="label-text">{{ i }}</span>
</label>
</div>
</div>
</div>
<div class="graph-viewport">
<div class="empty-hint">知识图谱可视化区域</div>
</div>
</section>
</main>
</div>
</template>
<script setup>
import { ref, defineProps, defineEmits } from 'vue';
import { useRouter } from 'vue-router';
import {ref} from 'vue';
import {useRouter} from 'vue-router';
import i1 from '@/assets/图标1.png';
import i2 from '@/assets/图标2.png';
import i3 from '@/assets/图标3.png';
import i4 from '@/assets/图标4.png';
const router = useRouter();
//
const props = defineProps({
//
initialActive: {
type: Number,
default: 0
}
});
//
const emit = defineEmits(['menu-click']);
//
const menuItems = ref([
{
name: '医疗知识图谱',
path: '/kg-display',
icon: '🏥',
},
{
name: '知识图谱构建',
path: '/kg-construction',
icon: '🔧'
},
{
name: '知识图谱问答',
path: '/kg-qa',
icon: '💬'
},
{
name: '知识图谱数据',
path: '/kg-data',
icon: '📊'
}
]);
//
const activeIndex = ref(props.initialActive);
//
const activeIndex = ref(0);
const isCollapsed = ref(false);
//
const toggleCollapse = () => {
isCollapsed.value = !isCollapsed.value;
};
//
const handleMenuClick = (index) => {
activeIndex.value = index;
emit('menu-click', menuItems.value[index]);
const item = menuItems.value[index];
if (item.path) {
router.push(item.path); // 👈
}
};
//
const handleProfile = () => {
// 使Vue Router
router.push('/profile');
};
const menuItems = [
{name: '医疗知识图谱', path: '/kg-display', icon: i1},
{name: '知识图谱构建', path: '/kg-construction', icon: i2},
{name: '知识图谱问答', path: '/kg-qa', icon: i3},
{name: '知识图谱数据', path: '/kg-data', icon: i4}
];
// 退
const handleLogout = () => {
// 使Vue Router
router.push('/login');
};
//
const goToIndex = () => {
router.push('/index');
const handleMenuClick = (i) => {
activeIndex.value = i;
router.push(menuItems[i].path);
};
const handleLogout = () => console.log('logout');
</script>
<style scoped>
.sidebar-container {
width: 240px;
.admin-layout {
display: flex;
width: 100vw;
height: 100vh;
background-color: #1e40af;
color: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
background: #fff;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
-webkit-font-smoothing: antialiased;
}
/* --- 侧边栏 --- */
.sidebar {
width: 200px;
height: 100%;
background: #0a2463;
flex-shrink: 0;
display: flex;
flex-direction: column;
position: relative;
transition: width 0.3s ease;
transition: width 0.3s;
z-index: 100;
}
.sidebar-container.collapsed {
width: 60px;
.sidebar.is-collapsed {
width: 64px;
}
.collapse-btn {
position: absolute;
top: 50%;
right: -15px;
width: 30px;
height: 30px;
background-color: #1e40af;
border: 2px solid white;
border-radius: 50%;
color: white;
cursor: pointer;
.sidebar-header {
padding: 30px 0 20px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transform: translateY(-50%);
}
.collapse-btn:hover {
background-color: #1e3a8a;
.header-content {
display: flex;
align-items: center;
gap: 10px;
width: fit-content;
}
.collapse-icon {
font-size: 14px;
line-height: 1;
.header-icon-wrap {
width: 32px;
height: 32px;
background: #165dff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: hidden;
}
.sidebar-header {
padding: 1.25rem;
border-bottom: 1px solid #1e3a8a;
.logo-img {
width: 22px;
height: 22px;
object-fit: contain;
}
.sidebar-title {
font-size: 1.25rem;
font-weight: bold;
letter-spacing: -0.025em;
transition: opacity 0.3s ease;
cursor: pointer;
.header-text-wrap {
display: flex;
flex-direction: column;
text-align: left;
}
.sidebar-title:hover {
color: #93c5fd;
.title-line {
color: #fff;
font-size: 12px;
font-weight: 600;
line-height: 1.25;
white-space: nowrap;
}
.sidebar-title-collapsed {
font-size: 0.75rem;
font-weight: bold;
text-align: center;
margin: 0;
padding: 0.5rem 0;
writing-mode: vertical-rl;
text-orientation: mixed;
/* --- 菜单导航 --- */
.menu-nav {
flex: 1;
padding-top: 10px;
position: relative;
}
.menu-item {
height: 42px;
display: flex;
align-items: center;
cursor: pointer;
padding: 0 8px;
margin-bottom: 2px;
}
.sidebar-title-collapsed:hover {
color: #93c5fd;
.highlight-box {
width: calc(100% - 16px);
margin: 0 auto;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
position: relative;
transition: all 0.2s;
padding-left: 8px;
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
padding: 1rem 0;
.menu-item.is-active .highlight-box {
background: #165dff !important;
}
.sidebar-nav ul {
padding-left: 0;
margin: 0;
.menu-item:hover .highlight-box {
background: rgba(255, 255, 255, 0.08);
}
.menu-item {
margin-bottom: 0.25rem;
list-style-type: none;
.menu-content-fixed {
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
width: 100%;
}
.menu-link {
.menu-icon-wrapper {
width: 20px;
height: 20px;
background: transparent;
border-radius: 4px;
display: flex;
align-items: center;
padding: 0.75rem 1.25rem;
color: white;
text-decoration: none;
transition: background-color 0.2s;
font-size: 1.1rem;
justify-content: center;
flex-shrink: 0;
}
.menu-link:hover {
background-color: #1e3a8a;
.menu-icon-img {
width: 14px;
height: auto;
object-fit: contain;
}
.menu-link.active {
background-color: #1e3a8a;
border-left: 4px solid #60a5fa;
.menu-item:hover .menu-icon-wrapper {
background: rgba(255, 255, 255, 0.25) !important;
}
.menu-icon {
margin-right: 0.75rem;
color: #93c5fd;
font-size: 1.4rem;
transition: margin 0.3s ease;
.menu-item.is-active .menu-icon-wrapper {
background: #457dff !important;
}
.sidebar-container.collapsed .menu-icon {
margin-right: 0;
justify-content: center;
display: flex;
.menu-text {
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
margin-left: 10px;
font-weight: 400;
}
.active-tag {
position: absolute;
right: 8px;
height: 18px;
}
.collapse-handle {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
}
.menu-link:hover .menu-icon {
color: white;
.collapse-icon-img {
width: 14px;
}
/* --- 用户区域 (重点修改) --- */
.sidebar-footer {
padding: 1rem;
border-top: 1px solid #1e3a8a;
padding: 12px 0 20px 0;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.user-info {
.user-block {
display: flex;
align-items: center;
position: relative;
justify-content: center;
padding: 0.5rem 0;
padding: 0 12px;
}
.sidebar-container.collapsed .user-info {
flex-direction: column;
.avatar {
width: 42px;
height: 42px;
background: rgba(255, 255, 255, 0.15);
border-radius: 50%;
font-size: 12px;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.action-buttons {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
.info {
margin-left: 12px;
display: flex;
flex-direction: column;
opacity: 0;
transition: opacity 0.3s ease, bottom 0.3s ease;
background-color: white;
border-radius: 8px;
padding: 8px 0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
margin-bottom: 10px;
min-width: 120px;
justify-content: center;
}
.user-info:hover .action-buttons {
opacity: 1;
bottom: 100%;
.info .name {
font-size: 12px;
color: #fff;
line-height: 1;
}
.user-avatar {
width: 2rem;
height: 2rem;
border-radius: 50%;
background-color: #274eb8;
.info .id {
font-size: 9px;
color: rgba(255, 255, 255, 0.35);
line-height: 1;
margin-top: 8px; /* 通过增加上边距让id向下移动 */
}
.exit-wrap {
margin-left: auto;
display: flex;
align-items: center;
}
.exit-icon {
width: 16px;
cursor: pointer;
opacity: 0.8;
}
.expand-handle-circle {
display: flex;
justify-content: center;
margin-right: 0.75rem;
padding-bottom: 20px;
cursor: pointer;
}
.avatar-text {
font-size: 0.875rem;
.expand-icon-img-circle {
width: 32px;
height: 32px;
}
.user-details {
/* --- 主体区域 --- */
.main-body {
flex: 1;
display: flex;
flex-direction: column;
background: #fff;
}
.user-name {
font-size: 0.875rem;
font-weight: 500;
margin: 0;
.top-nav {
height: 75px;
padding: 0 30px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #f0f0f0;
}
.user-email {
font-size: 0.75rem;
color: #93c5fd;
margin: 0;
.search-container {
width: 260px;
height: 36px;
background: #f5f7fa;
border-radius: 18px;
display: flex;
align-items: center;
padding: 0 15px;
}
/* 退出登录按钮样式 */
.profile-btn-inline, .logout-btn-inline {
background: transparent;
.search-container input {
border: none;
color: #333;
cursor: pointer;
padding: 10px 16px;
transition: all 0.2s;
display: block;
outline: none;
background: transparent;
width: 100%;
text-align: left;
font-size: 14px;
font-size: 13px;
}
.search-btn {
width: 16px;
}
.legend-box {
display: flex;
gap: 20px;
}
.leg-item {
display: flex;
align-items: center;
font-size: 13px;
}
.leg-item i {
width: 24px;
height: 8px;
border-radius: 4px;
margin-right: 8px;
}
.profile-btn-inline:hover, .logout-btn-inline:hover {
background-color: #f5f7fa;
color: #1e40af;
}
.profile-icon, .logout-icon {
font-size: 1.2rem;
}
/* 响应式调整 */
@media (max-width: 768px) {
.sidebar-container {
width: 70px;
}
.sidebar-container.collapsed {
width: 60px;
}
.collapse-btn {
right: -10px;
width: 25px;
height: 25px;
}
.sidebar-title,
.sidebar-title-collapsed,
.menu-link span:not(.menu-icon),
.user-details {
display: none;
}
.menu-link {
justify-content: center;
padding: 0.5rem;
}
.menu-icon {
margin-right: 0;
font-size: 1.2rem;
}
.menu-link.active {
border-left-width: 2px;
}
.action-buttons {
position: static;
opacity: 1;
transform: none;
background-color: transparent;
padding: 0;
box-shadow: none;
margin-top: 0.5rem;
flex-direction: row;
justify-content: center;
min-width: auto;
}
.user-info:hover .action-buttons {
bottom: auto;
}
.profile-btn-inline, .logout-btn-inline {
padding: 6px 8px;
font-size: 12px;
margin: 0 2px;
display: inline-block;
width: auto;
}
.main-content {
flex: 1;
padding: 20px 30px;
display: flex;
gap: 20px;
}
.disease-container {
width: 360px;
border: 1px solid #f0f0f0;
border-radius: 12px;
overflow: hidden;
}
.disease-header {
height: 50px;
background: #2265f4;
color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
}
.d-icon {
width: 18px;
margin-right: 8px;
}
.graph-viewport {
flex: 1;
border: 1px dashed #e2e8f0;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
}
</style>
Loading…
Cancel
Save