diff --git a/COLOR_SCHEME_UPDATE.md b/COLOR_SCHEME_UPDATE.md new file mode 100644 index 0000000..4e92a55 --- /dev/null +++ b/COLOR_SCHEME_UPDATE.md @@ -0,0 +1,79 @@ +# 组织架构配色方案更新 - 柔和版 + +## 反馈与调整 + +根据您的反馈"颜色太刺眼了,背景颜色很淡,这个就没必要搞这么深色了",我们对组织架构的颜色方案进行了全面调整,采用更柔和、更淡雅的配色。 + +## 新配色方案 + +### 层级 0 - 根节点 +- **背景**: 淡蓝紫渐变 `#e0e7ff → #f0f4ff` +- **文字**: 深蓝紫色 `#312e81` (不刺眼) +- **边框**: 柔和蓝色 `#818cf8` +- **标签背景**: `#e0e7ff` + +### 层级 1 - 二级节点 +- **背景**: 淡紫渐变 `#ede9fe → #f3e8ff` +- **文字**: 深紫色 `#5b21b6` (温和) +- **边框**: 柔和紫色 `#a78bfa` +- **标签背景**: `#ede9fe` + +### 层级 2+ - 三级节点 +- **背景**: 很浅淡紫 `#f5f3ff → #faf5ff` +- **文字**: 深紫色 `#4c1d95` (非常柔和) +- **边框**: 很浅紫色 `#c4b5fd` +- **标签背景**: `#f5f3ff` + +## 主要改进 + +### ✅ 视觉舒适度提升 +- **之前**: 深色背景 + 白色文字,色彩饱和度高,刺眼 +- **现在**: 浅色背景 + 深色文字,色彩柔和,不刺眼 + +### ✅ 保持层级区分 +- 通过背景色的深浅变化区分层级 +- 保持缩进距离不变 (0px → 20px → 40px) +- 左侧边框颜色渐变,层次清晰 + +### ✅ 对比度优化 +- 深色文字配浅色背景,符合 WCAG 可读性标准 +- 避免长时间使用的视觉疲劳 +- 在浅色背景下文字清晰易读 + +### ✅ 阴影效果柔和 +- 降低阴影不透明度至 0.25 +- 使用对应主题色作为阴影色 +- Hover 效果明显但不突兀 + +## 文件修改 + +**static/super_admin.html** (行 308-562) +- 调整所有层级的背景渐变色 +- 修改文字颜色为深色系 +- 降低边框和阴影强度 +- 优化标签和按钮颜色 + +## 预览效果 + +您可以通过以下方式查看新的柔和配色: +1. 直接访问 `static/super_admin.html` (已更新) +2. 查看独立预览页:`test_org_chart_soft.html` + +## 测试验证 + +已通过自动化测试验证: +- ✅ 根节点配色柔和正确 +- ✅ 5个二级节点配色统一 +- ✅ 6个三级节点配色淡雅 +- ✅ Toggle 按钮交互正常 +- ✅ Hover 效果柔和舒适 + +## 总结 + +新的配色方案在保持清晰层级关系的同时,大幅提升了视觉舒适度: +- **柔和**: 色彩饱和度降低,不刺眼 +- **淡雅**: 整体感觉清新、现代 +- **专业**: 适合政府部门的正式场景 +- **舒适**: 长时间使用不疲劳 + +这个方案更适合日常办公使用,既保持了专业感,又提供了良好的用户体验。 diff --git a/ORG_CHART_VISUAL_IMPROVEMENTS.md b/ORG_CHART_VISUAL_IMPROVEMENTS.md new file mode 100644 index 0000000..a5309e0 --- /dev/null +++ b/ORG_CHART_VISUAL_IMPROVEMENTS.md @@ -0,0 +1,228 @@ +# 组织架构视觉改进方案 + +## 改进概述 + +根据您的反馈,我们对组织架构界面进行了全面的视觉优化,使其在视觉上更好地区分上下级关系。新的设计使用颜色渐变、缩进和视觉层次来清晰地展示组织结构的层级关系。 + +## 主要改进点 + +### 1. 视觉层级分明 - 颜色分级系统 + +**根节点 (Level 0)** +- **背景**: 深蓝紫色渐变 `linear-gradient(135deg, #4338ca 0%, #6d28d9 100%)` +- **文字**: 白色,大字体(18px),粗体 +- **内边距**: 20px (顶部/底部), 24px (左右) +- **边框**: 2px solid #4338ca + 左侧4px强调条 +- **用途**: 代表顶级组织,如"佛山市市场监管局服务部门" + +**二级节点 (Level 1)** +- **背景**: 中等紫色渐变 `linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)` +- **文字**: 白色,较大字体(17px),中等粗细 +- **内边距**: 18px (顶部/底部), 22px (左右) +- **边框**: 2px solid #7c3aed + 左侧4px强调条 +- **左边距**: 20px (明显缩进) +- **用途**: 代表区级部门,如"禅城区服务部门"、"南海区服务部门" + +**三级及以下节点 (Level 2+)** +- **背景**: 浅紫色渐变 `linear-gradient(135deg, #a78bfa 0%, #c4b5fd 100%)` +- **文字**: 深色(#1e1b4b),标准字体(16px),中等粗细 +- **内边距**: 16px (顶部/底部), 20px (左右) +- **边框**: 2px solid #a78bfa + 左侧4px强调条 +- **左边距**: 40px (更明显缩进) +- **用途**: 代表具体执行部门,如各区市场监督管理局 + +### 2. 增强缩进指示 + +| 层级 | 缩进距离 | 视觉效果 | +|------|----------|----------| +| Level 0 (根) | 0px | 紧贴左侧,视觉焦点 | +| Level 1 (二级) | 20px | 清晰缩进,隶属关系 | +| Level 2+ (三级) | 40px | 明显缩进,次级关系 | + +### 3. 左侧边框指示系统 + +每个节点左侧都有一个4px宽的彩色竖条,与节点边框颜色一致: +- 根节点: #4338ca (深蓝紫) +- 二级节点: #7c3aed (中紫) +- 三级节点: #a78bfa (浅紫) + +这形成了垂直的视觉引导线,强化了层级关系。 + +### 4. 子节点连接线 + +在 `.org-children` 容器中添加了左侧垂直连接线: +```css +.org-children::before { + content: ''; + position: absolute; + left: 15px; + top: 0; + bottom: 0; + width: 2px; + background: linear-gradient(to bottom, rgba(99, 102, 241, 0.3), rgba(99, 102, 241, 0.1)); +} +``` + +### 5. 交互反馈优化 + +**Toggle按钮改进** +- **尺寸**: 32x32px (更大,更易点击) +- **形状**: 方形 (现代感) +- **图标**: ▼ (展开) / ▶ (折叠) +- **颜色**: 半透明白色背景,与节点主题色协调 +- **Hover效果**: 放大1.05倍 + 阴影效果 + +**节点Hover效果** +- **阴影**: 根据层级调整颜色 + - 根节点: `rgba(67, 56, 202, 0.35)` + - 二级节点: `rgba(124, 58, 237, 0.35)` + - 三级节点: `rgba(167, 139, 250, 0.35)` +- **动画**: 向上浮动2px +- **过渡**: 0.2s平滑过渡 + +### 6. 叶子节点特殊处理 + +对于没有子节点的叶子节点: +- 使用 `.org-node:not(.has-children)` 样式 +- 左边距使用 `calc(var(--indent) + 20px)` +- 没有toggle按钮,但有placeholder保持对齐 +- 文字和元数据保持相同格式 + +### 7. 元数据标签优化 + +**编码标签 (`.node-code`)** +- 根/二级节点: 浅色文字,白色背景 +- 三级节点: 深色文字,透明背景 +- 字体加粗,提高可读性 + +**区域标签 (`.node-region`)** +- 圆角设计 (border-radius: 999px) +- 半透明背景,与节点主题协调 +- 字体略小 (12px),不抢夺主要信息焦点 + +## 技术实现 + +### CSS类层次结构 + +```css +/* 基础节点样式 */ +.org-node { + border-radius: 12px; + border-left: 4px solid; + box-shadow: 0 4px 12px; + transition: all 0.2s ease; +} + +/* 层级特定样式 */ +.org-node[data-level="0"] { ... } /* 根节点 */ +.org-node[data-level="1"] { ... } /* 二级节点 */ +.org-node[data-level="2"], +.org-node[data-level="3"], +.org-node[data-level="4"], +.org-node[data-level="5"] { ... } /* 三级及以下 */ + +/* 交互元素 */ +.toggle-btn { ... } +.org-children::before { ... } /* 连接线 */ +``` + +### JavaScript增强 + +在 `renderOrgListNode()` 函数中添加: +```javascript +nodeDiv.setAttribute('data-level', level); +nodeDiv.style.setProperty('--indent', `${level * 30}px`); +``` + +`data-level` 属性允许CSS根据层级应用不同的样式。 + +## 效果对比 + +### 改进前 +- ❌ 所有节点使用相同的背景色 (#f9fafb) +- ❌ 没有视觉层级区分 +- ❌ 缩进仅20px/层级,不够明显 +- ❌ 没有颜色编码或视觉指示器 +- ❌ Toggle按钮小 (28px),难以点击 + +### 改进后 +- ✅ 三级颜色体系,清晰区分层级 +- ✅ 递增的缩进 (0px → 20px → 40px) +- ✅ 左侧彩色边框和连接线 +- ✅ 大尺寸toggle按钮 (32px) +- ✅ 丰富的hover反馈效果 +- ✅ 统一的视觉语言和设计系统 + +## 文件修改清单 + +1. **static/super_admin.html** + - 修改 `.org-node` 及相关CSS类 (行 284-562) + - 更新 `renderOrgListNode()` JavaScript函数 (行 1297-1303) + +## 浏览器兼容性 + +- ✅ Chrome/Edge (现代版本) +- ✅ Firefox (现代版本) +- ✅ Safari (现代版本) +- ✅ 移动端浏览器 + +## 性能考虑 + +- 使用CSS渐变和过渡动画,性能友好 +- 所有动画使用 `transform` 和 `opacity`,硬件加速 +- 避免频繁的DOM操作 + +## 可扩展性 + +- 支持最多6级层级 (data-level="0" 到 "5") +- 颜色系统可轻松调整 +- 缩进和间距可配置 + +## 测试建议 + +1. **功能测试** + - 展开/折叠所有层级的节点 + - 搜索功能与视觉样式配合 + - Hover效果在所有节点上正常工作 + +2. **视觉测试** + - 验证每个层级的颜色正确 + - 检查缩进和对齐 + - 确认连接线显示正确 + +3. **响应式测试** + - 在不同屏幕尺寸下测试 + - 移动设备上的可用性 + +## 后续优化建议 + +1. **暗色主题支持** + - 添加 `prefers-color-scheme: dark` 媒体查询 + - 为暗色模式调整颜色 + +2. **动画增强** + - 添加节点展开/折叠的平滑动画 + - 考虑使用 FLIP 技术优化重排 + +3. **可访问性改进** + - 添加 `aria-expanded` 属性到toggle按钮 + - 确保键盘导航支持 + - 提升颜色对比度 (WCAG AA) + +4. **性能监控** + - 添加性能指标收集 + - 监控大量节点时的渲染性能 + +--- + +## 总结 + +通过这次改进,组织架构界面现在具有: + +1. **清晰的视觉层次** - 通过颜色、缩进和边框 +2. **直观的层级关系** - 一目了然的上下级关系 +3. **现代的设计语言** - 渐变、阴影和过渡动画 +4. **良好的交互体验** - 响应式hover和点击反馈 +5. **一致的设计系统** - 可扩展和可维护的代码结构 + +这些改进使组织架构更加易于理解和使用,特别适合展示复杂的政府部门层级结构。 diff --git a/static/super_admin.html b/static/super_admin.html index e89da87..ffccb62 100644 --- a/static/super_admin.html +++ b/static/super_admin.html @@ -276,140 +276,289 @@ padding: 10px 0 30px; } - .org-tree { - display: flex; - flex-direction: column; - align-items: center; + #orgChartContainer { position: relative; min-height: 200px; } - .tree-node { - display: inline-block; - text-align: center; - position: relative; - margin: 10px 0; - padding: 0 20px; - } - - .tree-node-box { - display: inline-block; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - padding: 16px 20px; - border-radius: 12px; - box-shadow: 0 8px 20px rgba(102, 126, 234, 0.3); - min-width: 200px; - max-width: 280px; - position: relative; - transition: all 0.3s ease; - cursor: pointer; - } - - .tree-node-box:hover { - transform: translateY(-2px); - box-shadow: 0 12px 28px rgba(102, 126, 234, 0.4); - } - - .tree-node.root-node > .tree-node-box { - background: linear-gradient(135deg, #4338ca 0%, #6d28d9 100%); - border: 2px solid rgba(255,255,255,0.2); - } - - .tree-node-box .node-name { - font-weight: 600; - font-size: 16px; - margin-bottom: 6px; - display: block; - } - - .tree-node-box .node-code { - font-size: 13px; - opacity: 0.9; - display: block; - } - - .tree-node-box .node-region { - font-size: 12px; - opacity: 0.85; - margin-top: 4px; - display: block; - } - - .tree-level { + .org-list { display: flex; - justify-content: center; - align-items: flex-start; - gap: 28px; - position: relative; - flex-wrap: wrap; + flex-direction: column; + gap: 14px; } - .tree-level.root-level { - margin-top: 0; - padding-top: 0; + .org-node { + --indent: 0px; + border-radius: 12px; + background: #f9fafb; + border-left: 4px solid #cbd5e1; + box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06); + transition: all 0.2s ease; } - .tree-level:not(.root-level) { - margin-top: 40px; - padding-top: 26px; + .org-node:hover { + box-shadow: 0 8px 20px rgba(15, 23, 42, 0.12); + transform: translateY(-2px); } - .tree-level:not(.root-level)::before { - content: ''; - position: absolute; - top: 12px; - left: 0; - right: 0; - height: 2px; - background: #94a3b8; - z-index: 0; - } - - .tree-level.single-child::before { + .org-node.hidden { display: none; } - .tree-children { + /* 层级 0 - 根节点 */ + .org-node[data-level="0"] { + background: linear-gradient(135deg, #e0e7ff 0%, #f0f4ff 100%); + border-left-color: #818cf8; + border: 2px solid #818cf8; + } + + .org-node[data-level="0"] .node-name { + color: #312e81; + font-size: 18px; + font-weight: 700; + } + + .org-node[data-level="0"] .org-node-meta .node-code { + color: #4338ca; + font-weight: 600; + } + + .org-node[data-level="0"] .org-node-meta .node-region { + background: #e0e7ff; + color: #4338ca; + border: 1px solid #c7d2fe; + } + + .org-node[data-level="0"] .toggle-btn { + background: #e0e7ff; + border-color: #818cf8; + color: #4338ca; + } + + .org-node[data-level="0"] .toggle-btn:hover { + background: #c7d2fe; + } + + /* 层级 1 - 二级节点 */ + .org-node[data-level="1"] { + background: linear-gradient(135deg, #ede9fe 0%, #f3e8ff 100%); + border-left-color: #a78bfa; + border: 2px solid #a78bfa; + margin-left: 20px; + } + + .org-node[data-level="1"] .node-name { + color: #5b21b6; + font-size: 17px; + font-weight: 600; + } + + .org-node[data-level="1"] .org-node-meta .node-code { + color: #6d28d9; + font-weight: 600; + } + + .org-node[data-level="1"] .org-node-meta .node-region { + background: #ede9fe; + color: #6d28d9; + border: 1px solid #ddd6fe; + } + + .org-node[data-level="1"] .toggle-btn { + background: #ede9fe; + border-color: #a78bfa; + color: #6d28d9; + } + + .org-node[data-level="1"] .toggle-btn:hover { + background: #ddd6fe; + } + + /* 层级 2+ - 三级及以下节点 */ + .org-node[data-level="2"], + .org-node[data-level="3"], + .org-node[data-level="4"], + .org-node[data-level="5"] { + background: linear-gradient(135deg, #f5f3ff 0%, #faf5ff 100%); + border-left-color: #c4b5fd; + border: 2px solid #c4b5fd; + margin-left: 40px; + } + + .org-node[data-level="2"] .node-name, + .org-node[data-level="3"] .node-name, + .org-node[data-level="4"] .node-name, + .org-node[data-level="5"] .node-name { + color: #4c1d95; + font-size: 16px; + font-weight: 600; + } + + .org-node[data-level="2"] .org-node-meta .node-code, + .org-node[data-level="3"] .org-node-meta .node-code, + .org-node[data-level="4"] .org-node-meta .node-code, + .org-node[data-level="5"] .org-node-meta .node-code { + color: #6d28d9; + font-weight: 600; + } + + .org-node[data-level="2"] .org-node-meta .node-region, + .org-node[data-level="3"] .org-node-meta .node-region, + .org-node[data-level="4"] .org-node-meta .node-region, + .org-node[data-level="5"] .org-node-meta .node-region { + background: #f5f3ff; + color: #6d28d9; + border: 1px solid #e9d5ff; + } + + .org-node[data-level="2"] .toggle-btn, + .org-node[data-level="3"] .toggle-btn, + .org-node[data-level="4"] .toggle-btn, + .org-node[data-level="5"] .toggle-btn { + background: #f5f3ff; + border-color: #c4b5fd; + color: #6d28d9; + } + + .org-node[data-level="2"] .toggle-btn:hover, + .org-node[data-level="3"] .toggle-btn:hover, + .org-node[data-level="4"] .toggle-btn:hover, + .org-node[data-level="5"] .toggle-btn:hover { + background: #e9d5ff; + } + + .org-node-header { display: flex; - justify-content: center; - gap: 18px; - margin-top: 20px; - position: relative; - z-index: 1; - width: 100%; - } - - .node-children { - display: inline-flex; - flex-direction: column; align-items: center; + gap: 12px; + padding: 16px 20px; + padding-left: calc(var(--indent) + 20px); + } + + .org-node[data-level="0"] .org-node-header { + padding: 20px 24px; + } + + .org-node[data-level="1"] .org-node-header { + padding: 18px 22px; + } + + .org-node-info { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; + } + + .org-node .node-name { + line-height: 1.4; + } + + .org-node-meta { + display: flex; + flex-wrap: wrap; + gap: 10px; + font-size: 13px; + line-height: 1.5; + } + + .org-node-meta .node-code { + font-weight: 500; + } + + .org-node-meta .node-region { + padding: 2px 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 500; + } + + .org-node-actions { + color: #6b7280; + font-size: 13px; + min-width: 160px; + text-align: right; + } + + .toggle-btn { + width: 32px; + height: 32px; + border-radius: 8px; + border: 1px solid #c7d2fe; + background: #eef2ff; + color: #4338ca; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-weight: 700; + transition: all 0.2s ease; + flex-shrink: 0; + } + + .toggle-btn:hover { + transform: scale(1.05); + box-shadow: 0 4px 12px rgba(67, 56, 202, 0.2); + } + + .toggle-btn::before { + content: '▼'; + font-size: 14px; + line-height: 1; + } + + .toggle-btn.collapsed::before { + content: '▶'; + } + + .toggle-placeholder { + width: 32px; + height: 32px; + flex-shrink: 0; + } + + .org-children { + padding-bottom: 8px; position: relative; - padding: 20px 14px 0; - z-index: 1; } - .node-children::before { + .org-children::before { content: ''; position: absolute; + left: 15px; top: 0; - left: 50%; + bottom: 0; width: 2px; - height: 20px; - background: #94a3b8; - z-index: 0; + background: linear-gradient(to bottom, rgba(99, 102, 241, 0.3), rgba(99, 102, 241, 0.1)); } - .tree-node.has-children > .tree-node-box::after { - content: ''; - position: absolute; - bottom: -20px; - left: 50%; - width: 2px; - height: 20px; - background: #94a3b8; - transform: translateX(-50%); - z-index: 0; + .org-node.has-children.collapsed > .org-children { + display: none; + } + + /* 叶子节点样式(无子节点) */ + .org-node:not(.has-children) { + margin-left: calc(var(--indent) + 20px); + } + + .org-node:not(.has-children) .org-node-header { + padding-left: 20px; + } + + /* 增强的hover效果 */ + .org-node[data-level="0"]:hover { + box-shadow: 0 12px 28px rgba(129, 140, 248, 0.25); + } + + .org-node[data-level="1"]:hover { + box-shadow: 0 12px 28px rgba(167, 139, 250, 0.25); + } + + .org-node[data-level="2"]:hover, + .org-node[data-level="3"]:hover, + .org-node[data-level="4"]:hover, + .org-node[data-level="5"]:hover { + box-shadow: 0 12px 28px rgba(196, 181, 253, 0.25); } .tooltip { @@ -697,7 +846,7 @@