前端UI界面美化--初版

This commit is contained in:
Cheng Zhou
2025-12-22 08:38:22 +08:00
parent 1e3e064871
commit 4f510871bf
6 changed files with 871 additions and 154 deletions
+264 -65
View File
@@ -1,52 +1,119 @@
<template>
<el-container class="layout">
<el-header class="header">
<div class="logo">CTMS</div>
<div class="current-study" v-if="study.currentStudy">
<el-tag type="success" size="small">{{ study.currentStudy.name }}</el-tag>
</div>
<div class="user-info">
<StudySelector />
<span>{{ auth.user?.username }}</span>
<el-tag size="small" class="role">{{ auth.user?.role }}</el-tag>
<el-button size="small" type="danger" @click="onLogout">退出登录</el-button>
</div>
</el-header>
<el-container>
<el-aside width="220px" class="aside" v-if="isAdmin || study.currentStudy">
<el-menu router :default-active="$route.path">
<el-menu-item v-if="!isAdmin" index="/workbench">我的工作台</el-menu-item>
<template v-if="isAdmin">
<el-menu-item index="/admin/users">账号治理</el-menu-item>
<el-menu-item index="/admin/projects">项目治理</el-menu-item>
<el-menu-item index="/studies">项目列表PM 视角</el-menu-item>
</template>
<template v-if="study.currentStudy">
<el-menu-item index="/study/home">项目概览</el-menu-item>
<el-menu-item index="/study/milestones">伦理与启动管理</el-menu-item>
<el-menu-item index="/study/subjects">受试者</el-menu-item>
<el-menu-item index="/study/aes">不良事件</el-menu-item>
<el-menu-item index="/study/issues">风险与问题</el-menu-item>
<el-menu-item index="/study/data-queries">数据问题</el-menu-item>
<el-menu-item index="/study/verifications">数据核查</el-menu-item>
<el-sub-menu index="imp">
<template #title>药品</template>
<el-menu-item index="/study/imp/inventory">库存</el-menu-item>
<el-menu-item index="/study/imp/products">产品</el-menu-item>
<el-menu-item index="/study/imp/batches">批次</el-menu-item>
<el-menu-item index="/study/imp/transactions">交易台账</el-menu-item>
</el-sub-menu>
<el-menu-item index="/study/finance">费用</el-menu-item>
<el-menu-item index="/study/faq">知识库</el-menu-item>
<el-menu-item v-if="isAdmin || isPm" index="/study/audit-logs">审计日志</el-menu-item>
</template>
</el-menu>
</el-aside>
<el-main>
<router-view />
</el-main>
<el-container class="layout-container">
<el-aside width="240px" class="layout-aside" v-if="isAdmin || study.currentStudy">
<div class="aside-logo">
<div class="logo-icon"></div>
<span class="logo-text">CTMS</span>
</div>
<el-menu
router
:default-active="$route.path"
class="aside-menu"
>
<el-menu-item v-if="!isAdmin" index="/workbench">
<el-icon><Monitor /></el-icon>
<span>我的工作台</span>
</el-menu-item>
<template v-if="isAdmin">
<div class="menu-divider">管理后台</div>
<el-menu-item index="/admin/users">
<el-icon><User /></el-icon>
<span>账号管理</span>
</el-menu-item>
<el-menu-item index="/admin/projects">
<el-icon><Suitcase /></el-icon>
<span>项目管理</span>
</el-menu-item>
<el-menu-item index="/studies">
<el-icon><List /></el-icon>
<span>项目列表</span>
</el-menu-item>
</template>
<template v-if="study.currentStudy">
<div class="menu-divider">当前项目</div>
<el-menu-item index="/study/home">
<el-icon><House /></el-icon>
<span>项目概览</span>
</el-menu-item>
<el-menu-item index="/study/milestones">
<el-icon><Timer /></el-icon>
<span>里程碑管理</span>
</el-menu-item>
<el-menu-item index="/study/subjects">
<el-icon><UserFilled /></el-icon>
<span>受试者</span>
</el-menu-item>
<el-menu-item index="/study/aes">
<el-icon><Warning /></el-icon>
<span>不良事件</span>
</el-menu-item>
<el-menu-item index="/study/issues">
<el-icon><InfoFilled /></el-icon>
<span>风险与问题</span>
</el-menu-item>
<el-menu-item index="/study/data-queries">
<el-icon><QuestionFilled /></el-icon>
<span>数据问题</span>
</el-menu-item>
<el-menu-item index="/study/verifications">
<el-icon><Checked /></el-icon>
<span>数据核查</span>
</el-menu-item>
<el-sub-menu index="imp">
<template #title>
<el-icon><Management /></el-icon>
<span>药品管理</span>
</template>
<el-menu-item index="/study/imp/inventory">库存</el-menu-item>
<el-menu-item index="/study/imp/products">产品</el-menu-item>
<el-menu-item index="/study/imp/batches">批次</el-menu-item>
<el-menu-item index="/study/imp/transactions">交易台账</el-menu-item>
</el-sub-menu>
<el-menu-item index="/study/finance">
<el-icon><Money /></el-icon>
<span>费用治理</span>
</el-menu-item>
<el-menu-item index="/study/faq">
<el-icon><Collection /></el-icon>
<span>知识库</span>
</el-menu-item>
<el-menu-item v-if="isAdmin || isPm" index="/study/audit-logs">
<el-icon><Memo /></el-icon>
<span>审计日志</span>
</el-menu-item>
</template>
</el-menu>
</el-aside>
<el-container class="main-container">
<el-header class="layout-header">
<div class="header-left">
<div class="breadcrumb-study" v-if="study.currentStudy">
<el-tag effect="plain" class="study-tag">{{ study.currentStudy.name }}</el-tag>
</div>
</div>
<div class="header-right">
<StudySelector />
<div class="user-profile">
<div class="user-avatar">{{ auth.user?.username?.charAt(0).toUpperCase() }}</div>
<div class="user-details">
<span class="username">{{ auth.user?.username }}</span>
<span class="user-role">{{ auth.user?.role }}</span>
</div>
<el-button link type="danger" @click="onLogout" class="logout-btn">退出</el-button>
</div>
</div>
</el-header>
<el-main class="layout-main">
<div class="content-wrapper">
<router-view />
</div>
</el-main>
</el-container>
</el-container>
</el-container>
</template>
<script setup lang="ts">
@@ -55,6 +122,11 @@ import { useRouter } from "vue-router";
import { useAuthStore } from "../store/auth";
import { useStudyStore } from "../store/study";
import StudySelector from "./StudySelector.vue";
import {
Monitor, User, Suitcase, List, House, Timer, UserFilled,
Warning, InfoFilled, QuestionFilled, Checked, Management,
Money, Collection, Memo
} from "@element-plus/icons-vue";
const auth = useAuthStore();
const study = useStudyStore();
@@ -70,32 +142,159 @@ const onLogout = () => {
</script>
<style scoped>
.layout {
min-height: 100vh;
.layout-container {
height: 100vh;
background-color: var(--ctms-bg-base);
}
.header {
.layout-aside {
background-color: #001529;
display: flex;
flex-direction: column;
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
z-index: 10;
}
.aside-logo {
height: 64px;
display: flex;
align-items: center;
padding: 0 24px;
background-color: #002140;
}
.logo-icon {
width: 24px;
height: 24px;
background-color: var(--ctms-primary);
border-radius: 4px;
margin-right: 12px;
}
.logo-text {
color: #fff;
font-size: 20px;
font-weight: 700;
letter-spacing: 1px;
}
.aside-menu {
border-right: none;
background-color: transparent;
flex: 1;
padding: 16px 0;
overflow-y: auto;
}
.menu-divider {
padding: 16px 24px 8px;
font-size: 12px;
color: rgba(255, 255, 255, 0.45);
text-transform: uppercase;
letter-spacing: 1px;
}
:deep(.el-menu-item) {
height: 48px;
line-height: 48px;
margin: 4px 12px;
border-radius: var(--ctms-radius);
color: rgba(255, 255, 255, 0.65) !important;
}
:deep(.el-menu-item:hover) {
color: #fff !important;
background-color: transparent !important;
}
:deep(.el-menu-item.is-active) {
color: #fff !important;
background-color: var(--ctms-primary) !important;
}
:deep(.el-sub-menu__title) {
color: rgba(255, 255, 255, 0.65) !important;
margin: 4px 12px;
}
:deep(.el-sub-menu__title:hover) {
color: #fff !important;
background-color: transparent !important;
}
.layout-header {
background-color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
background: #409eff;
color: #fff;
padding: 0 24px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
height: 64px !important;
z-index: 9;
}
.logo {
font-weight: 600;
font-size: 18px;
}
.user-info {
.header-right {
display: flex;
align-items: center;
gap: 8px;
gap: 24px;
}
.role {
background: #fff;
color: #409eff;
border: none;
.user-profile {
display: flex;
align-items: center;
gap: 12px;
padding-left: 16px;
border-left: 1px solid var(--ctms-border-color);
}
.aside {
border-right: 1px solid #ebeef5;
.user-avatar {
width: 32px;
height: 32px;
background-color: var(--ctms-primary-light);
color: var(--ctms-primary);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
}
.user-details {
display: flex;
flex-direction: column;
}
.username {
font-size: 14px;
font-weight: 500;
color: var(--ctms-text-main);
line-height: 1.2;
}
.user-role {
font-size: 12px;
color: var(--ctms-text-secondary);
}
.logout-btn {
margin-left: 8px;
}
.study-tag {
font-weight: 500;
color: var(--ctms-primary);
border-color: var(--ctms-primary-hover);
background-color: var(--ctms-primary-light);
}
.layout-main {
padding: 0;
overflow-y: auto;
}
.content-wrapper {
padding: var(--ctms-spacing-lg);
min-height: calc(100vh - 64px);
}
</style>