提交merge1.3

This commit is contained in:
2025-12-27 15:30:25 +08:00
parent 8c607c8749
commit 088861f66e
1245 changed files with 220442 additions and 77616 deletions

View File

@@ -1,51 +1,70 @@
<template>
<div class="navbar">
<!-- <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> -->
<!-- <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" /> -->
<!-- <top-nav id="topmenu-container" class="topmenu-container" style="border: 1px solid blue;"/> -->
<div class="right-menu">
<template v-if="appStore.device !== 'mobile'">
<header-search id="header-search" class="right-menu-item" />
<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
<ruo-yi-git id="openhis-git" class="right-menu-item hover-effect" />
</el-tooltip> -->
<!-- <el-tooltip content="文档地址" effect="dark" placement="bottom">
<ruo-yi-doc id="openhis-doc" class="right-menu-item hover-effect" />
</el-tooltip> -->
<!-- <screenfull id="screenfull" class="right-menu-item hover-effect" /> -->
<el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip>
</template>
<div class="avatar-container">
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
<img :src="userStore.avatar" class="user-avatar" />
<span class="nick-name">{{ userStore.nickName }}</span>
<!-- <el-icon><caret-bottom /></el-icon> -->
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/user/profile">
<el-dropdown-item>个人中心</el-dropdown-item>
</router-link>
<el-dropdown-item command="switch">
<span>切换科室</span>
</el-dropdown-item>
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
<span>布局设置</span>
</el-dropdown-item>
<el-dropdown-item divided command="logout">
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<div class="avatar-wrapper">
<el-dropdown
@command="handleCommand"
class="user-info-dropdown hover-effect"
trigger="click"
teleported
popper-class="navbar-dropdown"
:popper-options="{
modifiers: [
{
name: 'offset',
options: {
offset: [0, 12],
},
},
],
}"
>
<div class="user-info">
<img :src="userStore.avatar" class="user-avatar" />
<span class="nick-name">{{ userStore.nickName }}</span>
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/user/profile">
<el-dropdown-item>个人中心</el-dropdown-item>
</router-link>
<!-- <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
<span>布局设置</span>
</el-dropdown-item> -->
<el-dropdown-item divided command="logout">
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span class="divider">|</span>
<el-dropdown
@command="handleOrgSwitch"
trigger="click"
teleported
popper-class="navbar-dropdown"
:placement="'bottom-start'"
>
<span class="org-name">{{ userStore.orgName }}</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="item in orgOptions"
:key="item.orgId"
:command="item.orgId"
:class="{ 'is-active': item.orgId === userStore.orgId }"
>
{{ item.orgName }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span class="divider" />
</div>
</div>
</div>
<el-dialog title="切换科室" v-model="showDialog" width="400px" append-to-body destroy-on-close>
@@ -68,6 +87,7 @@
</template>
<script setup>
import { onMounted } from 'vue';
import { ElMessageBox } from 'element-plus';
import Breadcrumb from '@/components/Breadcrumb';
import TopNav from '@/components/TopNav';
@@ -86,8 +106,39 @@ const settingsStore = useSettingsStore();
const orgOptions = ref([]);
const showDialog = ref(false);
const orgId = ref('');
function toggleSideBar() {
appStore.toggleSideBar();
function loadOrgList() {
getOrg().then((res) => {
orgOptions.value = res.data;
});
}
onMounted(() => {
loadOrgList();
});
function handleOrgSwitch(selectedOrgId) {
if (selectedOrgId === userStore.orgId) {
return;
}
const selectedOrg = orgOptions.value.find((item) => item.orgId === selectedOrgId);
const orgName = selectedOrg ? selectedOrg.orgName : '该科室';
ElMessageBox.confirm(`确定要切换到科室"${orgName}"吗?`, '切换科室', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
orgId.value = selectedOrgId;
switchOrg(selectedOrgId).then((res) => {
if (res.code === 200) {
userStore.logOut().then(() => {
location.href = '/index';
});
}
});
});
}
function handleCommand(command) {
@@ -98,13 +149,6 @@ function handleCommand(command) {
case 'logout':
logout();
break;
case 'switch':
orgId.value = userStore.orgId;
getOrg().then((res) => {
orgOptions.value = res.data;
showDialog.value = true;
});
break;
default:
break;
}
@@ -143,29 +187,35 @@ function setLayout() {
<style lang='scss' scoped>
.navbar {
height: 50px;
overflow: hidden;
overflow: visible;
position: relative;
background-color: transparent;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 10px;
flex-shrink: 0;
min-width: 200px;
z-index: 1002;
.right-menu {
display: flex;
align-items: center;
flex-shrink: 0;
white-space: nowrap;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
display: flex;
align-items: center;
padding: 0 6px;
height: 100%;
font-size: 16px;
color: #606266;
vertical-align: text-bottom;
flex-shrink: 0;
&.hover-effect {
cursor: pointer;
@@ -180,25 +230,70 @@ function setLayout() {
.avatar-container {
margin-right: 0;
margin-left: 5px;
flex-shrink: 0;
position: relative;
z-index: 1003;
display: flex;
align-items: center;
.avatar-wrapper {
display: flex;
align-items: center;
margin-top: 5px;
gap: 8px;
position: relative;
.user-info-dropdown {
display: flex;
align-items: center;
cursor: pointer;
}
.user-info {
display: flex;
align-items: center;
gap: 10px;
}
.user-avatar {
cursor: pointer;
width: 30px;
height: 30px;
border-radius: 6px;
flex-shrink: 0;
}
.nick-name {
font-weight: 500;
color: #606266;
font-size: 14px;
width: 80px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100px;
flex-shrink: 0;
}
.divider {
color: #dcdfe6;
font-size: 14px;
margin: 0 8px;
flex-shrink: 0;
}
.org-name {
font-weight: 500;
color: #606266;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 120px;
flex-shrink: 0;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: #409eff;
}
}
.el-icon {
cursor: pointer;
position: absolute;
@@ -210,5 +305,99 @@ function setLayout() {
}
}
}
@media (max-width: 768px) {
min-width: 150px;
padding-right: 5px;
.right-menu {
.avatar-container {
.avatar-wrapper {
gap: 4px;
.nick-name {
max-width: 60px;
font-size: 12px;
}
.org-name {
max-width: 80px;
font-size: 12px;
}
.divider {
margin: 0 4px;
font-size: 12px;
}
.user-avatar {
width: 24px;
height: 24px;
}
}
}
}
}
@media (max-width: 480px) {
min-width: 120px;
padding-right: 5px;
.right-menu {
.avatar-container {
.avatar-wrapper {
.nick-name {
display: none;
}
.divider {
display: none;
}
.org-name {
max-width: 80px;
font-size: 11px;
}
}
}
}
}
}
</style>
<style lang="scss">
.navbar-dropdown {
margin-bottom: 8px !important;
z-index: 10010 !important;
.el-dropdown-menu {
margin-bottom: 0 !important;
z-index: 10010 !important;
max-height: 300px !important;
overflow-y: auto !important;
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 3px;
&:hover {
background: rgba(0, 0, 0, 0.3);
}
}
&::-webkit-scrollbar-track {
background: transparent;
}
.el-dropdown-menu__item.is-active {
color: #409eff !important;
font-weight: 500 !important;
background-color: #ecf5ff !important;
}
}
}
</style>

View File

@@ -1,5 +1,6 @@
<template>
<div
<<<<<<< HEAD
:class="{ 'has-logo': showLogo }"
:style="{
backgroundColor:
@@ -27,6 +28,39 @@
:base-path="route.path"
/>
</el-menu>
=======
:class="{ 'has-logo': showLogo }"
class="sidebar-wrapper"
:style="{
backgroundColor:
sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground,
}"
>
<!-- <logo v-if="showLogo" :collapse="isCollapse" /> -->
<div class="menu-container">
<div class="menu-scrollbar">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="
sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground
"
:text-color="sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
:unique-opened="true"
:active-text-color="theme"
:collapse-transition="false"
mode="horizontal"
>
<sidebar-item
v-for="(route, index) in sidebarRouters"
:key="route.path + index"
:item="route"
:base-path="route.path"
/>
</el-menu>
</div>
</div>
>>>>>>> v1.3
<navbar @setLayout="setLayout" class="navbar-container" />
<settings ref="settingRef" />
</div>
@@ -69,16 +103,70 @@ function setLayout() {
</script>
<style lang="scss" scoped>
<<<<<<< HEAD
/* 移除滚动条样式 */
=======
.sidebar-wrapper {
display: flex;
flex-direction: row;
align-items: center;
height: 50px;
padding: 0;
width: 100%;
overflow: hidden;
position: relative;
}
.menu-container {
flex: 1;
height: 50px;
min-width: 0;
overflow: hidden;
position: relative;
display: flex;
align-items: center;
}
.menu-scrollbar {
height: 50px;
width: 100%;
overflow-x: auto;
overflow-y: hidden;
display: flex;
align-items: center;
&::-webkit-scrollbar {
height: 4px;
}
&::-webkit-scrollbar:vertical {
display: none;
}
&::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 2px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
}
>>>>>>> v1.3
.el-menu--horizontal {
display: flex !important;
align-items: center !important;
border-bottom: none !important;
background-color: transparent !important;
min-width: auto;
flex-wrap: nowrap;
<<<<<<< HEAD
overflow: hidden !important;
white-space: nowrap;
=======
height: 50px;
>>>>>>> v1.3
& > .el-menu-item,
& > .el-sub-menu {
@@ -87,8 +175,16 @@ function setLayout() {
color: #fff;
padding: 0 15px !important;
font-size: 14px;
<<<<<<< HEAD
min-width: auto !important;
white-space: nowrap;
=======
min-width: 120px !important;
flex-shrink: 0;
white-space: nowrap;
display: flex;
align-items: center;
>>>>>>> v1.3
}
:deep(.svg-icon) {
@@ -98,7 +194,13 @@ function setLayout() {
:deep(.el-sub-menu__title) {
padding-right: 25px !important;
<<<<<<< HEAD
white-space: nowrap;
=======
display: flex;
align-items: center;
height: 50px;
>>>>>>> v1.3
}
:deep(.el-sub-menu__icon-arrow) {
@@ -110,6 +212,7 @@ function setLayout() {
}
}
<<<<<<< HEAD
/* 水平布局,并与 Navbar 正确配合 */
.sidebar-layout {
display: flex;
@@ -132,6 +235,39 @@ function setLayout() {
height: 50px;
padding: 0;
width: 100%;
=======
.navbar-container {
flex-shrink: 0;
height: 50px;
z-index: 1002;
}
/* 响应式处理 */
@media (max-width: 768px) {
.menu-container {
flex: 1;
min-width: 0;
}
.el-menu--horizontal {
& > .el-menu-item,
& > .el-sub-menu {
padding: 0 12px !important;
min-width: 80px !important;
font-size: 12px;
}
}
}
@media (max-width: 480px) {
.el-menu--horizontal {
& > .el-menu-item,
& > .el-sub-menu {
padding: 0 8px !important;
min-width: 60px !important;
font-size: 11px;
}
>>>>>>> v1.3
}
}
</style>

View File

@@ -105,6 +105,7 @@ function setLayout() {
left: 0;
z-index: 1001;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.35);
overflow: visible;
}
.sidebar-container {