方案B业务流程导向菜单优化: - "患者管理" → "患者中心",吸收日常监测/诊断/知情同意/咨询 - "诊疗服务" → "随访关怀",只保留随访相关 - 告警规则/危急值阈值 → 系统管理 - 文章分类/标签菜单软删除,合并为文章管理页内 Tab 变更文件: - 迁移 164: 重命名目录+移动叶子菜单+重建 menu_roles - ArticleManageList.tsx: 分类/标签管理合并为页内 Tab - 讨论记录 + 可视化原型 HTML Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1184 lines
43 KiB
HTML
1184 lines
43 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>HMS 菜单优化原型对比</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
||
:root {
|
||
--sidebar-w: 280px;
|
||
--header-h: 56px;
|
||
--blue: #1677ff;
|
||
--blue-bg: #e6f4ff;
|
||
--gray-1: #1d2129;
|
||
--gray-2: #4e5969;
|
||
--gray-3: #86909c;
|
||
--gray-4: #c9cdd4;
|
||
--gray-5: #e5e6eb;
|
||
--gray-6: #f2f3f5;
|
||
--gray-7: #f7f8fa;
|
||
--red: #f53f3f;
|
||
--orange: #ff7d00;
|
||
--green: #00b42a;
|
||
--purple: #722ed1;
|
||
--radius: 6px;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
||
background: var(--gray-7);
|
||
color: var(--gray-1);
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* ===== Top Control Bar ===== */
|
||
.control-bar {
|
||
height: var(--header-h);
|
||
background: #fff;
|
||
border-bottom: 1px solid var(--gray-5);
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 24px;
|
||
gap: 16px;
|
||
position: relative;
|
||
z-index: 100;
|
||
}
|
||
|
||
.control-bar .logo {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: var(--blue);
|
||
white-space: nowrap;
|
||
margin-right: 8px;
|
||
}
|
||
|
||
.scheme-tabs {
|
||
display: flex;
|
||
gap: 4px;
|
||
background: var(--gray-6);
|
||
border-radius: 8px;
|
||
padding: 3px;
|
||
}
|
||
|
||
.scheme-tab {
|
||
padding: 6px 16px;
|
||
border-radius: 6px;
|
||
font-size: 13px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
border: none;
|
||
background: transparent;
|
||
color: var(--gray-2);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.scheme-tab:hover { color: var(--gray-1); }
|
||
.scheme-tab.active {
|
||
background: #fff;
|
||
color: var(--blue);
|
||
font-weight: 500;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
|
||
}
|
||
|
||
.scheme-tab .badge {
|
||
display: inline-block;
|
||
font-size: 10px;
|
||
padding: 1px 6px;
|
||
border-radius: 10px;
|
||
margin-left: 6px;
|
||
font-weight: 500;
|
||
}
|
||
.badge-current { background: var(--gray-5); color: var(--gray-3); }
|
||
.badge-recommend { background: #e8ffea; color: var(--green); }
|
||
.badge-minimal { background: #fff7e6; color: var(--orange); }
|
||
.badge-advanced { background: #f5e8ff; color: var(--purple); }
|
||
|
||
.role-tabs {
|
||
display: flex;
|
||
gap: 4px;
|
||
background: var(--gray-6);
|
||
border-radius: 8px;
|
||
padding: 3px;
|
||
}
|
||
|
||
.role-tab {
|
||
padding: 6px 12px;
|
||
border-radius: 6px;
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
border: none;
|
||
background: transparent;
|
||
color: var(--gray-2);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.role-tab:hover { color: var(--gray-1); }
|
||
.role-tab.active {
|
||
background: var(--blue);
|
||
color: #fff;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.toggle-group {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-left: auto;
|
||
font-size: 12px;
|
||
color: var(--gray-2);
|
||
}
|
||
|
||
.toggle-switch {
|
||
width: 36px;
|
||
height: 20px;
|
||
background: var(--gray-4);
|
||
border-radius: 10px;
|
||
position: relative;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.toggle-switch.active { background: var(--blue); }
|
||
|
||
.toggle-switch::after {
|
||
content: '';
|
||
width: 16px;
|
||
height: 16px;
|
||
background: #fff;
|
||
border-radius: 50%;
|
||
position: absolute;
|
||
top: 2px;
|
||
left: 2px;
|
||
transition: transform 0.2s;
|
||
box-shadow: 0 1px 2px rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.toggle-switch.active::after { transform: translateX(16px); }
|
||
|
||
/* ===== Main Layout ===== */
|
||
.main-layout {
|
||
display: flex;
|
||
height: calc(100vh - var(--header-h));
|
||
}
|
||
|
||
/* ===== Sidebar ===== */
|
||
.sidebar {
|
||
width: var(--sidebar-w);
|
||
background: #fff;
|
||
border-right: 1px solid var(--gray-5);
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex-shrink: 0;
|
||
transition: width 0.2s;
|
||
}
|
||
|
||
.sidebar-header {
|
||
padding: 16px 16px 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.sidebar-header .app-icon {
|
||
width: 32px;
|
||
height: 32px;
|
||
background: linear-gradient(135deg, var(--blue), #4096ff);
|
||
border-radius: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #fff;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.sidebar-header .app-name {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--gray-1);
|
||
}
|
||
|
||
.sidebar-search {
|
||
padding: 0 12px 8px;
|
||
}
|
||
|
||
.sidebar-search input {
|
||
width: 100%;
|
||
padding: 6px 10px;
|
||
border: 1px solid var(--gray-5);
|
||
border-radius: var(--radius);
|
||
font-size: 12px;
|
||
outline: none;
|
||
background: var(--gray-7);
|
||
transition: border 0.2s;
|
||
}
|
||
|
||
.sidebar-search input:focus {
|
||
border-color: var(--blue);
|
||
background: #fff;
|
||
}
|
||
|
||
.sidebar-search input::placeholder { color: var(--gray-4); }
|
||
|
||
.sidebar-menu {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: 4px 8px 16px;
|
||
}
|
||
|
||
.sidebar-menu::-webkit-scrollbar { width: 4px; }
|
||
.sidebar-menu::-webkit-scrollbar-track { background: transparent; }
|
||
.sidebar-menu::-webkit-scrollbar-thumb { background: var(--gray-4); border-radius: 2px; }
|
||
|
||
/* Menu Group */
|
||
.menu-group {
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.menu-group-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 8px 8px 4px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.menu-group-header .group-icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
color: var(--gray-3);
|
||
}
|
||
|
||
.menu-group-header .group-title {
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
color: var(--gray-3);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
flex: 1;
|
||
}
|
||
|
||
.menu-group-header .group-arrow {
|
||
font-size: 10px;
|
||
color: var(--gray-4);
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.menu-group-header .group-arrow.collapsed { transform: rotate(-90deg); }
|
||
|
||
.menu-group-header .group-count {
|
||
font-size: 10px;
|
||
color: var(--gray-4);
|
||
background: var(--gray-6);
|
||
padding: 1px 6px;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.menu-group-items {
|
||
overflow: hidden;
|
||
transition: max-height 0.3s ease;
|
||
}
|
||
|
||
.menu-group-items.collapsed { max-height: 0 !important; }
|
||
|
||
/* Menu Item */
|
||
.menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 8px 12px;
|
||
border-radius: var(--radius);
|
||
cursor: pointer;
|
||
transition: all 0.15s;
|
||
font-size: 13px;
|
||
color: var(--gray-2);
|
||
position: relative;
|
||
}
|
||
|
||
.menu-item:hover {
|
||
background: var(--gray-7);
|
||
color: var(--gray-1);
|
||
}
|
||
|
||
.menu-item.active {
|
||
background: var(--blue-bg);
|
||
color: var(--blue);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.menu-item .item-icon {
|
||
width: 18px;
|
||
height: 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.menu-item .item-label { flex: 1; }
|
||
|
||
.menu-item .item-tag {
|
||
font-size: 10px;
|
||
padding: 1px 6px;
|
||
border-radius: 4px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.tag-new { background: #e8ffea; color: var(--green); }
|
||
.tag-moved { background: #e6f4ff; color: var(--blue); }
|
||
.tag-frozen { background: var(--gray-6); color: var(--gray-3); }
|
||
.tag-config { background: #fff7e6; color: var(--orange); }
|
||
|
||
.menu-item.frozen {
|
||
opacity: 0.4;
|
||
cursor: default;
|
||
}
|
||
|
||
.menu-item.frozen:hover { background: transparent; }
|
||
|
||
/* Sub-group (3rd level) */
|
||
.sub-group {
|
||
margin: 2px 0;
|
||
}
|
||
|
||
.sub-group-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 6px 12px 4px 24px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.sub-group-header .sub-title {
|
||
font-size: 12px;
|
||
color: var(--gray-3);
|
||
font-weight: 500;
|
||
flex: 1;
|
||
}
|
||
|
||
.sub-group-header .sub-arrow {
|
||
font-size: 9px;
|
||
color: var(--gray-4);
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.sub-group-header .sub-arrow.collapsed { transform: rotate(-90deg); }
|
||
|
||
.sub-group-items {
|
||
overflow: hidden;
|
||
transition: max-height 0.25s ease;
|
||
padding-left: 12px;
|
||
}
|
||
|
||
.sub-group-items.collapsed { max-height: 0 !important; }
|
||
|
||
.sub-group-items .menu-item {
|
||
padding-left: 28px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
/* ===== Content Area ===== */
|
||
.content-area {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 32px;
|
||
}
|
||
|
||
.comparison-card {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
padding: 32px;
|
||
max-width: 680px;
|
||
width: 100%;
|
||
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
|
||
}
|
||
|
||
.comparison-card h2 {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin-bottom: 16px;
|
||
color: var(--gray-1);
|
||
}
|
||
|
||
.stat-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 12px;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.stat-item {
|
||
background: var(--gray-7);
|
||
border-radius: 8px;
|
||
padding: 12px 16px;
|
||
text-align: center;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 24px;
|
||
font-weight: 700;
|
||
color: var(--blue);
|
||
}
|
||
|
||
.stat-value.green { color: var(--green); }
|
||
.stat-value.orange { color: var(--orange); }
|
||
.stat-value.red { color: var(--red); }
|
||
|
||
.stat-label {
|
||
font-size: 11px;
|
||
color: var(--gray-3);
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.change-metrics {
|
||
margin-top: 16px;
|
||
}
|
||
|
||
.change-metric {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 8px 0;
|
||
border-bottom: 1px solid var(--gray-6);
|
||
font-size: 13px;
|
||
}
|
||
|
||
.change-metric:last-child { border-bottom: none; }
|
||
|
||
.change-metric .metric-label {
|
||
color: var(--gray-2);
|
||
flex: 1;
|
||
}
|
||
|
||
.change-metric .metric-value {
|
||
font-weight: 600;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.metric-improve { color: var(--green); }
|
||
.metric-worsen { color: var(--red); }
|
||
.metric-same { color: var(--gray-3); }
|
||
|
||
.diff-legend {
|
||
margin-top: 20px;
|
||
padding-top: 16px;
|
||
border-top: 1px solid var(--gray-5);
|
||
}
|
||
|
||
.diff-legend h4 {
|
||
font-size: 13px;
|
||
color: var(--gray-2);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.legend-items {
|
||
display: flex;
|
||
gap: 16px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.legend-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
font-size: 12px;
|
||
color: var(--gray-2);
|
||
}
|
||
|
||
.legend-dot {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.dot-new { background: var(--green); }
|
||
.dot-moved { background: var(--blue); }
|
||
.dot-frozen { background: var(--gray-4); }
|
||
.dot-config { background: var(--orange); }
|
||
|
||
/* Highlight animation */
|
||
@keyframes highlight-in {
|
||
from { background: #fffbe6; }
|
||
to { background: transparent; }
|
||
}
|
||
|
||
.menu-item.highlight { animation: highlight-in 2s ease; }
|
||
|
||
/* Sidebar collapsed state */
|
||
.sidebar.collapsed {
|
||
width: 64px;
|
||
}
|
||
|
||
.sidebar.collapsed .sidebar-header .app-name,
|
||
.sidebar.collapsed .sidebar-search,
|
||
.sidebar.collapsed .menu-item .item-label,
|
||
.sidebar.collapsed .menu-item .item-tag,
|
||
.sidebar.collapsed .menu-group-header .group-title,
|
||
.sidebar.collapsed .menu-group-header .group-arrow,
|
||
.sidebar.collapsed .menu-group-header .group-count,
|
||
.sidebar.collapsed .sub-group-header,
|
||
.sidebar.collapsed .sub-group-items {
|
||
display: none;
|
||
}
|
||
|
||
.sidebar.collapsed .menu-group-header {
|
||
justify-content: center;
|
||
padding: 8px 0;
|
||
}
|
||
|
||
.sidebar.collapsed .menu-item {
|
||
justify-content: center;
|
||
padding: 10px 0;
|
||
}
|
||
|
||
.sidebar.collapsed .menu-group-items {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- Control Bar -->
|
||
<div class="control-bar">
|
||
<div class="logo">HMS 菜单优化原型</div>
|
||
<div class="scheme-tabs" id="schemeTabs">
|
||
<button class="scheme-tab active" data-scheme="current">
|
||
当前方案
|
||
<span class="badge badge-current">现状</span>
|
||
</button>
|
||
<button class="scheme-tab" data-scheme="a">
|
||
方案 A
|
||
<span class="badge badge-minimal">最小改动</span>
|
||
</button>
|
||
<button class="scheme-tab" data-scheme="b">
|
||
方案 B
|
||
<span class="badge badge-recommend">推荐</span>
|
||
</button>
|
||
<button class="scheme-tab" data-scheme="c">
|
||
方案 C
|
||
<span class="badge badge-advanced">激进</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div style="width:1px;height:24px;background:var(--gray-5);margin:0 4px;"></div>
|
||
|
||
<div class="role-tabs" id="roleTabs">
|
||
<button class="role-tab active" data-role="admin">管理员</button>
|
||
<button class="role-tab" data-role="doctor">医生</button>
|
||
<button class="role-tab" data-role="nurse">护士</button>
|
||
<button class="role-tab" data-role="health_manager">健康管理师</button>
|
||
<button class="role-tab" data-role="operator">运营</button>
|
||
</div>
|
||
|
||
<div class="toggle-group">
|
||
<span>三级折叠</span>
|
||
<div class="toggle-switch active" id="toggleCollapse" onclick="toggleCollapse()"></div>
|
||
<span style="margin-left:12px">侧边栏</span>
|
||
<div class="toggle-switch" id="toggleSidebar" onclick="toggleSidebar()"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Main -->
|
||
<div class="main-layout">
|
||
<div class="sidebar" id="sidebar">
|
||
<div class="sidebar-header">
|
||
<div class="app-icon">H</div>
|
||
<div class="app-name">HMS 健康管理</div>
|
||
</div>
|
||
<div class="sidebar-search">
|
||
<input type="text" placeholder="搜索菜单..." id="searchInput" oninput="filterMenu(this.value)">
|
||
</div>
|
||
<div class="sidebar-menu" id="menuContainer"></div>
|
||
</div>
|
||
|
||
<div class="content-area" id="contentArea"></div>
|
||
</div>
|
||
|
||
<script>
|
||
// ============================================================
|
||
// Menu Data Definitions
|
||
// ============================================================
|
||
|
||
const ICONS = {
|
||
dashboard: '📊', patient: '👤', tag: '🏷️', doctor: '👨⚕️',
|
||
schedule: '📅', appointment: '📋', followup: '🔄', template: '📝',
|
||
consultation: '💬', inbox: '📥', diagnosis: '🩺', consent: '📄',
|
||
monitor: '📈', alert: '🚨', alertRule: '⚙️', device: '📟',
|
||
gateway: '📡', threshold: '📉', article: '📰', category: '📂',
|
||
articleTag: '🔖', points: '⭐', product: '🎁', order: '🛒',
|
||
event: '🎪', media: '🖼️', banner: '🎨', chat: '🤖', prompt: '💡',
|
||
analysis: '🔍', knowledge: '📚', usage: '📉', config: '⚙️',
|
||
user: '👥', role: '🔐', org: '🏢', workflow: '🔄', message: '✉️',
|
||
settings: '🛠️', plugin: '🧩', oauth: '🔗', statistics: '📊',
|
||
realtime: '📡', alertDash: '🔔', daily: '📋', care: '❤️',
|
||
family: '👨👩👧', medication: '💊', dialysis: '🩸', shift: '🕐',
|
||
home: '🏠', vitals: '💓', healthData: '📈',
|
||
};
|
||
|
||
function icon(name) { return ICONS[name] || '📁'; }
|
||
|
||
// Role definitions: which paths each role can see
|
||
const ROLES = {
|
||
current: {
|
||
admin: '*',
|
||
doctor: ['/', '/health/statistics', '/health/patients', '/health/doctors',
|
||
'/health/follow-up-tasks', '/health/follow-up-templates', '/health/consultations',
|
||
'/health/action-inbox', '/health/diagnoses', '/health/consents',
|
||
'/health/daily-monitoring', '/health/alert-dashboard', '/health/alerts',
|
||
'/health/ai-analysis', '/health/ai-usage', '/ai/chat', '/messages'],
|
||
nurse: ['/', '/health/statistics', '/health/patients',
|
||
'/health/follow-up-tasks', '/health/consultations', '/health/action-inbox',
|
||
'/health/diagnoses', '/health/consents', '/health/daily-monitoring',
|
||
'/health/alert-dashboard', '/health/alerts', '/messages'],
|
||
health_manager: ['/', '/health/statistics', '/health/patients', '/health/doctors',
|
||
'/health/tags', '/health/follow-up-tasks', '/health/follow-up-templates',
|
||
'/health/consultations', '/health/action-inbox', '/health/diagnoses',
|
||
'/health/consents', '/health/daily-monitoring', '/health/realtime-monitor',
|
||
'/health/alert-dashboard', '/health/alerts', '/health/alert-rules',
|
||
'/health/devices', '/health/critical-value-thresholds',
|
||
'/health/ai-prompts', '/health/ai-analysis', '/health/ai-knowledge',
|
||
'/health/ai-usage', '/health/ai-config', '/ai/chat', '/messages'],
|
||
operator: ['/', '/health/statistics', '/health/patients', '/health/tags',
|
||
'/health/devices', '/health/alert-dashboard', '/health/alerts',
|
||
'/health/articles', '/health/article-categories', '/health/article-tags',
|
||
'/health/points-rules', '/health/points-products', '/health/points-orders',
|
||
'/health/offline-events', '/health/media-library', '/health/banners',
|
||
'/health/ai-usage', '/messages'],
|
||
},
|
||
};
|
||
|
||
// ============================================================
|
||
// Scheme Definitions
|
||
// ============================================================
|
||
|
||
function buildCurrentScheme() {
|
||
return [
|
||
{ title: '工作台', icon: icon('home'), items: [
|
||
{ label: '工作台', path: '/', icon: icon('dashboard') },
|
||
{ label: '统计报表', path: '/health/statistics', icon: icon('statistics') },
|
||
]},
|
||
{ title: '患者管理', icon: icon('patient'), items: [
|
||
{ label: '患者管理', path: '/health/patients', icon: icon('patient') },
|
||
{ label: '标签管理', path: '/health/tags', icon: icon('tag') },
|
||
{ label: '医护管理', path: '/health/doctors', icon: icon('doctor') },
|
||
]},
|
||
{ title: '诊疗服务', icon: '🏥', items: [
|
||
{ label: '排班管理', path: '/health/schedules', icon: icon('schedule'), frozen: true },
|
||
{ label: '预约排班', path: '/health/appointments', icon: icon('appointment'), frozen: true },
|
||
{ label: '随访管理', path: '/health/follow-up-tasks', icon: icon('followup') },
|
||
{ label: '随访模板管理', path: '/health/follow-up-templates', icon: icon('template') },
|
||
{ label: '咨询管理', path: '/health/consultations', icon: icon('consultation') },
|
||
{ label: '行动收件箱', path: '/health/action-inbox', icon: icon('inbox') },
|
||
{ label: '诊断记录', path: '/health/diagnoses', icon: icon('diagnosis') },
|
||
{ label: '知情同意', path: '/health/consents', icon: icon('consent') },
|
||
{ label: '日常监测', path: '/health/daily-monitoring', icon: icon('daily') },
|
||
]},
|
||
{ title: '健康监测', icon: icon('monitor'), items: [
|
||
{ label: '实时监控', path: '/health/realtime-monitor', icon: icon('realtime') },
|
||
{ label: '告警仪表盘', path: '/health/alert-dashboard', icon: icon('alertDash') },
|
||
{ label: '告警列表', path: '/health/alerts', icon: icon('alert') },
|
||
{ label: '告警规则', path: '/health/alert-rules', icon: icon('alertRule') },
|
||
{ label: '设备管理', path: '/health/devices', icon: icon('device') },
|
||
{ label: 'BLE 网关', path: '/health/ble-gateways', icon: icon('gateway') },
|
||
{ label: '危急值阈值', path: '/health/critical-value-thresholds', icon: icon('threshold') },
|
||
]},
|
||
{ title: '运营管理', icon: '📢', items: [
|
||
{ label: '资讯管理', path: '/health/articles', icon: icon('article') },
|
||
{ label: '文章分类', path: '/health/article-categories', icon: icon('category') },
|
||
{ label: '文章标签', path: '/health/article-tags', icon: icon('articleTag') },
|
||
{ label: '积分规则', path: '/health/points-rules', icon: icon('points') },
|
||
{ label: '商品管理', path: '/health/points-products', icon: icon('product') },
|
||
{ label: '订单管理', path: '/health/points-orders', icon: icon('order') },
|
||
{ label: '线下活动', path: '/health/offline-events', icon: icon('event') },
|
||
{ label: '媒体库', path: '/health/media-library', icon: icon('media') },
|
||
{ label: '轮播图管理', path: '/health/banners', icon: icon('banner') },
|
||
]},
|
||
{ title: 'AI 助手', icon: '🤖', items: [
|
||
{ label: 'AI 客服', path: '/ai/chat', icon: icon('chat') },
|
||
{ label: 'AI Prompt 管理', path: '/health/ai-prompts', icon: icon('prompt') },
|
||
{ label: 'AI 分析历史', path: '/health/ai-analysis', icon: icon('analysis') },
|
||
{ label: 'AI 知识库', path: '/health/ai-knowledge', icon: icon('knowledge') },
|
||
{ label: 'AI 用量统计', path: '/health/ai-usage', icon: icon('usage') },
|
||
{ label: 'AI 配置', path: '/health/ai-config', icon: icon('config') },
|
||
]},
|
||
{ title: '系统管理', icon: '⚙️', items: [
|
||
{ label: '用户管理', path: '/users', icon: icon('user') },
|
||
{ label: '权限管理', path: '/roles', icon: icon('role') },
|
||
{ label: '组织架构', path: '/organizations', icon: icon('org') },
|
||
{ label: '工作流', path: '/workflow', icon: icon('workflow') },
|
||
{ label: '消息中心', path: '/messages', icon: icon('message') },
|
||
{ label: '系统设置', path: '/settings', icon: icon('settings') },
|
||
{ label: '插件管理', path: '/plugins/admin', icon: icon('plugin') },
|
||
{ label: 'OAuth 合作方', path: '/health/oauth-clients', icon: icon('oauth') },
|
||
]},
|
||
];
|
||
}
|
||
|
||
function buildSchemeA() {
|
||
// Minimal changes: move daily-monitoring to 健康监测, merge article cats/tags into tab
|
||
return [
|
||
{ title: '工作台', icon: icon('home'), items: [
|
||
{ label: '工作台', path: '/', icon: icon('dashboard') },
|
||
{ label: '统计报表', path: '/health/statistics', icon: icon('statistics') },
|
||
]},
|
||
{ title: '患者管理', icon: icon('patient'), items: [
|
||
{ label: '患者管理', path: '/health/patients', icon: icon('patient') },
|
||
{ label: '标签管理', path: '/health/tags', icon: icon('tag') },
|
||
{ label: '医护管理', path: '/health/doctors', icon: icon('doctor') },
|
||
]},
|
||
{ title: '诊疗服务', icon: '🏥', items: [
|
||
{ label: '排班管理', path: '/health/schedules', icon: icon('schedule'), frozen: true },
|
||
{ label: '预约排班', path: '/health/appointments', icon: icon('appointment'), frozen: true },
|
||
{ label: '随访管理', path: '/health/follow-up-tasks', icon: icon('followup') },
|
||
{ label: '随访模板管理', path: '/health/follow-up-templates', icon: icon('template') },
|
||
{ label: '咨询管理', path: '/health/consultations', icon: icon('consultation') },
|
||
{ label: '行动收件箱', path: '/health/action-inbox', icon: icon('inbox') },
|
||
{ label: '诊断记录', path: '/health/diagnoses', icon: icon('diagnosis') },
|
||
]},
|
||
{ title: '健康监测', icon: icon('monitor'), items: [
|
||
{ label: '实时监控', path: '/health/realtime-monitor', icon: icon('realtime') },
|
||
{ label: '告警仪表盘', path: '/health/alert-dashboard', icon: icon('alertDash') },
|
||
{ label: '告警列表', path: '/health/alerts', icon: icon('alert') },
|
||
{ label: '告警规则', path: '/health/alert-rules', icon: icon('alertRule') },
|
||
{ label: '日常监测', path: '/health/daily-monitoring', icon: icon('daily'), tag: 'moved', tagText: '从诊疗服务移入' },
|
||
{ label: '设备管理', path: '/health/devices', icon: icon('device') },
|
||
{ label: 'BLE 网关', path: '/health/ble-gateways', icon: icon('gateway') },
|
||
{ label: '危急值阈值', path: '/health/critical-value-thresholds', icon: icon('threshold') },
|
||
]},
|
||
{ title: '运营管理', icon: '📢', items: [
|
||
{ label: '资讯管理', path: '/health/articles', icon: icon('article'), tag: 'merged', tagText: '含分类/标签Tab' },
|
||
{ label: '积分规则', path: '/health/points-rules', icon: icon('points') },
|
||
{ label: '商品管理', path: '/health/points-products', icon: icon('product') },
|
||
{ label: '订单管理', path: '/health/points-orders', icon: icon('order') },
|
||
{ label: '线下活动', path: '/health/offline-events', icon: icon('event') },
|
||
{ label: '媒体库', path: '/health/media-library', icon: icon('media') },
|
||
{ label: '轮播图管理', path: '/health/banners', icon: icon('banner') },
|
||
]},
|
||
{ title: 'AI 助手', icon: '🤖', items: [
|
||
{ label: 'AI 客服', path: '/ai/chat', icon: icon('chat') },
|
||
{ label: 'AI Prompt 管理', path: '/health/ai-prompts', icon: icon('prompt') },
|
||
{ label: 'AI 分析历史', path: '/health/ai-analysis', icon: icon('analysis') },
|
||
{ label: 'AI 知识库', path: '/health/ai-knowledge', icon: icon('knowledge') },
|
||
{ label: 'AI 用量统计', path: '/health/ai-usage', icon: icon('usage') },
|
||
{ label: 'AI 配置', path: '/health/ai-config', icon: icon('config') },
|
||
]},
|
||
{ title: '系统管理', icon: '⚙️', items: [
|
||
{ label: '用户管理', path: '/users', icon: icon('user') },
|
||
{ label: '权限管理', path: '/roles', icon: icon('role') },
|
||
{ label: '组织架构', path: '/organizations', icon: icon('org') },
|
||
{ label: '工作流', path: '/workflow', icon: icon('workflow') },
|
||
{ label: '消息中心', path: '/messages', icon: icon('message') },
|
||
{ label: '系统设置', path: '/settings', icon: icon('settings') },
|
||
{ label: '插件管理', path: '/plugins/admin', icon: icon('plugin') },
|
||
{ label: 'OAuth 合作方', path: '/health/oauth-clients', icon: icon('oauth') },
|
||
]},
|
||
];
|
||
}
|
||
|
||
function buildSchemeB() {
|
||
// Recommended: Patient center + follow-up care + config items to system
|
||
return [
|
||
{ title: '工作台', icon: icon('home'), items: [
|
||
{ label: '工作台', path: '/', icon: icon('dashboard') },
|
||
{ label: '统计报表', path: '/health/statistics', icon: icon('statistics') },
|
||
]},
|
||
{ title: '患者中心', icon: '🫀', tag: 'new', tagText: '原"患者管理"扩充', items: [
|
||
{ label: '患者管理', path: '/health/patients', icon: icon('patient') },
|
||
{ label: '日常监测', path: '/health/daily-monitoring', icon: icon('daily'), tag: 'moved', tagText: '从诊疗服务移入' },
|
||
{ label: '诊断记录', path: '/health/diagnoses', icon: icon('diagnosis'), tag: 'moved', tagText: '从诊疗服务移入' },
|
||
{ label: '知情同意', path: '/health/consents', icon: icon('consent'), tag: 'moved', tagText: '从诊疗服务移入' },
|
||
{ label: '咨询管理', path: '/health/consultations', icon: icon('consultation'), tag: 'moved', tagText: '从诊疗服务移入' },
|
||
{ label: '标签管理', path: '/health/tags', icon: icon('tag') },
|
||
{ label: '医护管理', path: '/health/doctors', icon: icon('doctor') },
|
||
]},
|
||
{ title: '随访关怀', icon: '🤝', tag: 'new', tagText: '原"诊疗服务"瘦身', items: [
|
||
{ label: '行动收件箱', path: '/health/action-inbox', icon: icon('inbox'), tag: 'reorder', tagText: '提到首位' },
|
||
{ label: '随访任务', path: '/health/follow-up-tasks', icon: icon('followup') },
|
||
{ label: '随访模板', path: '/health/follow-up-templates', icon: icon('template') },
|
||
{ label: '排班管理', path: '/health/schedules', icon: icon('schedule'), frozen: true },
|
||
{ label: '预约排班', path: '/health/appointments', icon: icon('appointment'), frozen: true },
|
||
]},
|
||
{ title: '监测告警', icon: icon('monitor'), items: [
|
||
{ label: '实时监控', path: '/health/realtime-monitor', icon: icon('realtime') },
|
||
{ label: '告警仪表盘', path: '/health/alert-dashboard', icon: icon('alertDash') },
|
||
{ label: '告警列表', path: '/health/alerts', icon: icon('alert') },
|
||
{ label: '设备管理', path: '/health/devices', icon: icon('device') },
|
||
{ label: 'BLE 网关', path: '/health/ble-gateways', icon: icon('gateway') },
|
||
]},
|
||
{ title: '运营管理', icon: '📢', items: [
|
||
{ label: '资讯管理', path: '/health/articles', icon: icon('article'), tag: 'merged', tagText: '含分类/标签Tab' },
|
||
{ label: '积分规则', path: '/health/points-rules', icon: icon('points') },
|
||
{ label: '商品管理', path: '/health/points-products', icon: icon('product') },
|
||
{ label: '订单管理', path: '/health/points-orders', icon: icon('order') },
|
||
{ label: '线下活动', path: '/health/offline-events', icon: icon('event') },
|
||
{ label: '媒体库', path: '/health/media-library', icon: icon('media') },
|
||
{ label: '轮播图管理', path: '/health/banners', icon: icon('banner') },
|
||
]},
|
||
{ title: 'AI 助手', icon: '🤖', items: [
|
||
{ label: 'AI 客服', path: '/ai/chat', icon: icon('chat') },
|
||
{ label: 'AI Prompt 管理', path: '/health/ai-prompts', icon: icon('prompt') },
|
||
{ label: 'AI 分析历史', path: '/health/ai-analysis', icon: icon('analysis') },
|
||
{ label: 'AI 知识库', path: '/health/ai-knowledge', icon: icon('knowledge') },
|
||
{ label: 'AI 用量统计', path: '/health/ai-usage', icon: icon('usage') },
|
||
{ label: 'AI 配置', path: '/health/ai-config', icon: icon('config') },
|
||
]},
|
||
{ title: '系统管理', icon: '⚙️', items: [
|
||
{ label: '用户管理', path: '/users', icon: icon('user') },
|
||
{ label: '权限管理', path: '/roles', icon: icon('role') },
|
||
{ label: '组织架构', path: '/organizations', icon: icon('org') },
|
||
{ label: '告警规则', path: '/health/alert-rules', icon: icon('alertRule'), tag: 'config', tagText: '配置项归入系统' },
|
||
{ label: '危急值阈值', path: '/health/critical-value-thresholds', icon: icon('threshold'), tag: 'config', tagText: '配置项归入系统' },
|
||
{ label: '工作流', path: '/workflow', icon: icon('workflow') },
|
||
{ label: '消息中心', path: '/messages', icon: icon('message') },
|
||
{ label: '系统设置', path: '/settings', icon: icon('settings') },
|
||
{ label: '插件管理', path: '/plugins/admin', icon: icon('plugin') },
|
||
{ label: 'OAuth 合作方', path: '/health/oauth-clients', icon: icon('oauth') },
|
||
]},
|
||
];
|
||
}
|
||
|
||
function buildSchemeC() {
|
||
// Advanced: Patient-centric with patient detail tabs
|
||
return [
|
||
{ title: '首页', icon: icon('home'), items: [
|
||
{ label: '工作台', path: '/', icon: icon('dashboard') },
|
||
{ label: '统计报表', path: '/health/statistics', icon: icon('statistics') },
|
||
]},
|
||
{ title: '患者中心', icon: '🫀', tag: 'new', tagText: '核心入口,详情页含Tab', items: [
|
||
{ label: '患者管理', path: '/health/patients', icon: icon('patient') },
|
||
{ label: '标签管理', path: '/health/tags', icon: icon('tag') },
|
||
{ label: '医护管理', path: '/health/doctors', icon: icon('doctor') },
|
||
{ label: '—— 患者详情页内 Tab ——', icon: '↳', disabled: true },
|
||
{ label: '体征数据', path: '/health/patients/:id/vitals', icon: icon('vitals'), tag: 'tab', tagText: '详情页Tab' },
|
||
{ label: '随访记录', path: '/health/patients/:id/followup', icon: icon('followup'), tag: 'tab', tagText: '详情页Tab' },
|
||
{ label: '咨询记录', path: '/health/patients/:id/consultation', icon: icon('consultation'), tag: 'tab', tagText: '详情页Tab' },
|
||
{ label: '诊断记录', path: '/health/patients/:id/diagnosis', icon: icon('diagnosis'), tag: 'tab', tagText: '详情页Tab' },
|
||
{ label: '知情同意', path: '/health/patients/:id/consent', icon: icon('consent'), tag: 'tab', tagText: '详情页Tab' },
|
||
]},
|
||
{ title: '排班与随访', icon: '📋', tag: 'new', tagText: '护士/健康管理师高频', items: [
|
||
{ label: '行动收件箱', path: '/health/action-inbox', icon: icon('inbox') },
|
||
{ label: '随访任务', path: '/health/follow-up-tasks', icon: icon('followup') },
|
||
{ label: '随访模板', path: '/health/follow-up-templates', icon: icon('template') },
|
||
{ label: '排班管理', path: '/health/schedules', icon: icon('schedule'), frozen: true },
|
||
{ label: '预约排班', path: '/health/appointments', icon: icon('appointment'), frozen: true },
|
||
]},
|
||
{ title: '监测中心', icon: icon('monitor'), items: [
|
||
{ label: '实时监控', path: '/health/realtime-monitor', icon: icon('realtime') },
|
||
{ label: '日常监测', path: '/health/daily-monitoring', icon: icon('daily'), tag: 'moved', tagText: '移入监测中心' },
|
||
{ label: '告警仪表盘', path: '/health/alert-dashboard', icon: icon('alertDash') },
|
||
{ label: '告警列表', path: '/health/alerts', icon: icon('alert') },
|
||
{ label: '告警规则', path: '/health/alert-rules', icon: icon('alertRule') },
|
||
{ label: '危急值阈值', path: '/health/critical-value-thresholds', icon: icon('threshold') },
|
||
{ label: '设备管理', path: '/health/devices', icon: icon('device') },
|
||
{ label: 'BLE 网关', path: '/health/ble-gateways', icon: icon('gateway') },
|
||
]},
|
||
{ title: '运营中心', icon: '📢', items: [
|
||
{ label: '资讯管理', path: '/health/articles', icon: icon('article'), tag: 'merged', tagText: '含分类/标签Tab' },
|
||
{ label: '积分规则', path: '/health/points-rules', icon: icon('points') },
|
||
{ label: '商品管理', path: '/health/points-products', icon: icon('product') },
|
||
{ label: '订单管理', path: '/health/points-orders', icon: icon('order') },
|
||
{ label: '线下活动', path: '/health/offline-events', icon: icon('event') },
|
||
{ label: '媒体库', path: '/health/media-library', icon: icon('media') },
|
||
{ label: '轮播图管理', path: '/health/banners', icon: icon('banner') },
|
||
]},
|
||
{ title: 'AI 助手', icon: '🤖', items: [
|
||
{ label: 'AI 客服', path: '/ai/chat', icon: icon('chat') },
|
||
{ label: 'AI Prompt 管理', path: '/health/ai-prompts', icon: icon('prompt') },
|
||
{ label: 'AI 分析历史', path: '/health/ai-analysis', icon: icon('analysis') },
|
||
{ label: 'AI 知识库', path: '/health/ai-knowledge', icon: icon('knowledge') },
|
||
{ label: 'AI 用量统计', path: '/health/ai-usage', icon: icon('usage') },
|
||
{ label: 'AI 配置', path: '/health/ai-config', icon: icon('config') },
|
||
]},
|
||
{ title: '系统管理', icon: '⚙️', items: [
|
||
{ label: '用户管理', path: '/users', icon: icon('user') },
|
||
{ label: '权限管理', path: '/roles', icon: icon('role') },
|
||
{ label: '组织架构', path: '/organizations', icon: icon('org') },
|
||
{ label: '工作流', path: '/workflow', icon: icon('workflow') },
|
||
{ label: '消息中心', path: '/messages', icon: icon('message') },
|
||
{ label: '系统设置', path: '/settings', icon: icon('settings') },
|
||
{ label: '插件管理', path: '/plugins/admin', icon: icon('plugin') },
|
||
{ label: 'OAuth 合作方', path: '/health/oauth-clients', icon: icon('oauth') },
|
||
]},
|
||
];
|
||
}
|
||
|
||
// Role visibility for each scheme (inherit from current, add overrides)
|
||
function getRolePaths(scheme, role) {
|
||
// For all schemes, use the same role paths as current (paths don't change, just grouping)
|
||
return ROLES.current[role] || ROLES.current.admin;
|
||
}
|
||
|
||
function isPathVisible(scheme, role, path) {
|
||
if (role === 'admin') return true;
|
||
const paths = getRolePaths(scheme, role);
|
||
if (paths === '*') return true;
|
||
// For moved items in scheme B/C, check by path
|
||
return paths.includes(path);
|
||
}
|
||
|
||
// ============================================================
|
||
// Render Engine
|
||
// ============================================================
|
||
|
||
let currentScheme = 'current';
|
||
let currentRole = 'admin';
|
||
let collapseEnabled = true;
|
||
|
||
const schemes = {
|
||
current: buildCurrentScheme,
|
||
a: buildSchemeA,
|
||
b: buildSchemeB,
|
||
c: buildSchemeC,
|
||
};
|
||
|
||
const schemeNames = {
|
||
current: '当前方案',
|
||
a: '方案 A(最小改动)',
|
||
b: '方案 B(业务流程导向 · 推荐)',
|
||
c: '方案 C(患者中心化)',
|
||
};
|
||
|
||
function render() {
|
||
const menuData = schemes[currentScheme]();
|
||
const container = document.getElementById('menuContainer');
|
||
const contentArea = document.getElementById('contentArea');
|
||
|
||
// Filter by role
|
||
const filtered = menuData.map(group => {
|
||
const filteredItems = group.items.filter(item => {
|
||
if (item.disabled) return true; // show disabled dividers
|
||
return isPathVisible(currentScheme, currentRole, item.path);
|
||
});
|
||
// Only show groups that have visible items
|
||
const hasVisible = filteredItems.some(i => !i.disabled);
|
||
if (!hasVisible && currentRole !== 'admin') return null;
|
||
return { ...group, items: filteredItems };
|
||
}).filter(Boolean);
|
||
|
||
// Build sidebar HTML
|
||
let html = '';
|
||
let totalItems = 0;
|
||
|
||
filtered.forEach((group, gi) => {
|
||
const visibleCount = group.items.filter(i => !i.disabled).length;
|
||
totalItems += visibleCount;
|
||
|
||
html += `<div class="menu-group">`;
|
||
html += `<div class="menu-group-header" onclick="toggleGroup(this, ${gi})">`;
|
||
html += ` <span class="group-icon">${group.icon}</span>`;
|
||
html += ` <span class="group-title">${group.title}</span>`;
|
||
if (group.tag === 'new') {
|
||
html += `<span class="item-tag tag-new">新</span>`;
|
||
}
|
||
html += ` <span class="group-count">${visibleCount}</span>`;
|
||
html += ` <span class="group-arrow">▼</span>`;
|
||
html += `</div>`;
|
||
html += `<div class="menu-group-items" id="group-${gi}" style="max-height:1000px">`;
|
||
|
||
group.items.forEach(item => {
|
||
if (item.disabled) {
|
||
html += `<div class="menu-item" style="opacity:0.3;cursor:default;font-size:11px;color:var(--gray-3)">${item.icon} ${item.label}</div>`;
|
||
return;
|
||
}
|
||
|
||
const classes = ['menu-item'];
|
||
if (item.frozen) classes.push('frozen');
|
||
|
||
let tagHtml = '';
|
||
if (item.tag === 'moved') tagHtml = `<span class="item-tag tag-moved">移入</span>`;
|
||
else if (item.tag === 'new') tagHtml = `<span class="item-tag tag-new">新</span>`;
|
||
else if (item.tag === 'config') tagHtml = `<span class="item-tag tag-config">配置</span>`;
|
||
else if (item.tag === 'merged') tagHtml = `<span class="item-tag tag-moved">合并</span>`;
|
||
else if (item.tag === 'tab') tagHtml = `<span class="item-tag tag-new">Tab</span>`;
|
||
else if (item.tag === 'reorder') tagHtml = `<span class="item-tag tag-moved">置顶</span>`;
|
||
else if (item.frozen) tagHtml = `<span class="item-tag tag-frozen">冻结</span>`;
|
||
|
||
const title = item.tagText ? ` title="${item.tagText}"` : '';
|
||
|
||
html += `<div class="${classes.join(' ')}"${title} onclick="selectItem(this, '${item.path}')">`;
|
||
html += ` <span class="item-icon">${item.icon}</span>`;
|
||
html += ` <span class="item-label">${item.label}</span>`;
|
||
html += tagHtml;
|
||
html += `</div>`;
|
||
});
|
||
|
||
html += `</div></div>`;
|
||
});
|
||
|
||
container.innerHTML = html;
|
||
|
||
// Build content area stats
|
||
const allItems = menuData.flatMap(g => g.items.filter(i => !i.disabled && !i.frozen));
|
||
const frozenItems = menuData.flatMap(g => g.items.filter(i => i.frozen));
|
||
const activeCount = allItems.length;
|
||
const dirCount = menuData.length;
|
||
|
||
const maxDirItems = Math.max(...menuData.map(g => g.items.length));
|
||
|
||
// Count changes from current
|
||
let changes = [];
|
||
if (currentScheme === 'a') {
|
||
changes = [
|
||
{ label: '日常监测移入健康监测', type: 'improve' },
|
||
{ label: '文章分类/标签合并为Tab', type: 'improve' },
|
||
{ label: '总菜单项 -2', type: 'improve' },
|
||
];
|
||
} else if (currentScheme === 'b') {
|
||
changes = [
|
||
{ label: '患者管理→患者中心(+4项)', type: 'improve' },
|
||
{ label: '诊疗服务→随访关怀(-4项)', type: 'improve' },
|
||
{ label: '告警规则/阈值→系统管理', type: 'improve' },
|
||
{ label: '文章分类/标签合并为Tab', type: 'improve' },
|
||
{ label: '行动收件箱提到首位', type: 'improve' },
|
||
];
|
||
} else if (currentScheme === 'c') {
|
||
changes = [
|
||
{ label: '患者详情页升级多Tab枢纽', type: 'improve' },
|
||
{ label: '日常监测移入监测中心', type: 'improve' },
|
||
{ label: '文章分类/标签合并为Tab', type: 'improve' },
|
||
{ label: '医生核心操作仅需2个目录', type: 'improve' },
|
||
{ label: '需重构患者详情页架构', type: 'worsen' },
|
||
];
|
||
} else {
|
||
changes = [
|
||
{ label: '7个顶级目录', type: 'same' },
|
||
{ label: '诊疗服务9项(最臃肿)', type: 'worsen' },
|
||
{ label: '运营管理9项', type: 'worsen' },
|
||
{ label: '医生需穿越4个目录', type: 'worsen' },
|
||
];
|
||
}
|
||
|
||
const balanceScore = currentScheme === 'current' ? 5.2 :
|
||
currentScheme === 'a' ? 6.5 :
|
||
currentScheme === 'b' ? 8.0 : 7.5;
|
||
|
||
const efficiencyScore = currentScheme === 'current' ? 4.0 :
|
||
currentScheme === 'a' ? 5.5 :
|
||
currentScheme === 'b' ? 7.5 : 8.5;
|
||
|
||
let contentHtml = `<div class="comparison-card">`;
|
||
contentHtml += `<h2>${schemeNames[currentScheme]}</h2>`;
|
||
|
||
contentHtml += `<div class="stat-grid">`;
|
||
contentHtml += `<div class="stat-item"><div class="stat-value">${dirCount}</div><div class="stat-label">顶级目录</div></div>`;
|
||
contentHtml += `<div class="stat-item"><div class="stat-value">${activeCount}</div><div class="stat-label">活跃菜单项</div></div>`;
|
||
contentHtml += `<div class="stat-item"><div class="stat-value">${frozenItems.length}</div><div class="stat-label">冻结项</div></div>`;
|
||
contentHtml += `</div>`;
|
||
|
||
contentHtml += `<div class="stat-grid">`;
|
||
contentHtml += `<div class="stat-item"><div class="stat-value">${maxDirItems}</div><div class="stat-label">最大目录项数</div></div>`;
|
||
contentHtml += `<div class="stat-item"><div class="stat-value green">${balanceScore}</div><div class="stat-label">均衡性 /10</div></div>`;
|
||
contentHtml += `<div class="stat-item"><div class="stat-value ${efficiencyScore >= 7 ? 'green' : efficiencyScore >= 5 ? 'orange' : 'red'}">${efficiencyScore}</div><div class="stat-label">导航效率 /10</div></div>`;
|
||
contentHtml += `</div>`;
|
||
|
||
contentHtml += `<div class="change-metrics">`;
|
||
changes.forEach(c => {
|
||
const cls = c.type === 'improve' ? 'metric-improve' : c.type === 'worsen' ? 'metric-worsen' : 'metric-same';
|
||
const arrow = c.type === 'improve' ? '↑' : c.type === 'worsen' ? '↓' : '→';
|
||
contentHtml += `<div class="change-metric"><span class="metric-label">${c.label}</span><span class="metric-value ${cls}">${arrow}</span></div>`;
|
||
});
|
||
contentHtml += `</div>`;
|
||
|
||
// Legend for tags
|
||
const hasTags = currentScheme !== 'current';
|
||
if (hasTags) {
|
||
contentHtml += `<div class="diff-legend"><h4>标记说明</h4><div class="legend-items">`;
|
||
contentHtml += `<div class="legend-item"><span class="legend-dot dot-moved"></span>移入/重组</div>`;
|
||
contentHtml += `<div class="legend-item"><span class="legend-dot dot-new"></span>新增/Tab</div>`;
|
||
contentHtml += `<div class="legend-item"><span class="legend-dot dot-config"></span>配置项归入</div>`;
|
||
contentHtml += `<div class="legend-item"><span class="legend-dot dot-frozen"></span>冻结</div>`;
|
||
contentHtml += `</div></div>`;
|
||
}
|
||
|
||
contentHtml += `</div>`;
|
||
contentArea.innerHTML = contentHtml;
|
||
}
|
||
|
||
function toggleGroup(header, gi) {
|
||
const items = document.getElementById(`group-${gi}`);
|
||
const arrow = header.querySelector('.group-arrow');
|
||
if (items.classList.contains('collapsed')) {
|
||
items.classList.remove('collapsed');
|
||
items.style.maxHeight = items.scrollHeight + 'px';
|
||
arrow.classList.remove('collapsed');
|
||
} else {
|
||
items.classList.add('collapsed');
|
||
arrow.classList.add('collapsed');
|
||
}
|
||
}
|
||
|
||
function selectItem(el, path) {
|
||
document.querySelectorAll('.menu-item.active').forEach(e => e.classList.remove('active'));
|
||
el.classList.add('active');
|
||
}
|
||
|
||
function filterMenu(query) {
|
||
const q = query.toLowerCase().trim();
|
||
document.querySelectorAll('.menu-item').forEach(item => {
|
||
const label = item.querySelector('.item-label');
|
||
if (!label) return;
|
||
const text = label.textContent.toLowerCase();
|
||
item.style.display = (!q || text.includes(q)) ? '' : 'none';
|
||
});
|
||
}
|
||
|
||
function toggleCollapse() {
|
||
collapseEnabled = !collapseEnabled;
|
||
document.getElementById('toggleCollapse').classList.toggle('active', collapseEnabled);
|
||
if (!collapseEnabled) {
|
||
// Expand all groups
|
||
document.querySelectorAll('.menu-group-items').forEach(el => {
|
||
el.classList.remove('collapsed');
|
||
el.style.maxHeight = el.scrollHeight + 'px';
|
||
});
|
||
document.querySelectorAll('.group-arrow').forEach(el => el.classList.remove('collapsed'));
|
||
}
|
||
}
|
||
|
||
function toggleSidebar() {
|
||
const sidebar = document.getElementById('sidebar');
|
||
const toggle = document.getElementById('toggleSidebar');
|
||
sidebar.classList.toggle('collapsed');
|
||
toggle.classList.toggle('active');
|
||
}
|
||
|
||
// Scheme tabs
|
||
document.getElementById('schemeTabs').addEventListener('click', e => {
|
||
const tab = e.target.closest('.scheme-tab');
|
||
if (!tab) return;
|
||
document.querySelectorAll('.scheme-tab').forEach(t => t.classList.remove('active'));
|
||
tab.classList.add('active');
|
||
currentScheme = tab.dataset.scheme;
|
||
render();
|
||
});
|
||
|
||
// Role tabs
|
||
document.getElementById('roleTabs').addEventListener('click', e => {
|
||
const tab = e.target.closest('.role-tab');
|
||
if (!tab) return;
|
||
document.querySelectorAll('.role-tab').forEach(t => t.classList.remove('active'));
|
||
tab.classList.add('active');
|
||
currentRole = tab.dataset.role;
|
||
render();
|
||
});
|
||
|
||
// Initial render
|
||
render();
|
||
</script>
|
||
</body>
|
||
</html>
|