From dd0b2729907b18dce32ff5952e3935c9eaac90f6 Mon Sep 17 00:00:00 2001 From: root <295172551@qq.com> Date: Mon, 4 Aug 2025 22:53:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=A1=A8=E6=A0=BC=E5=8A=9F=E8=83=BD=20-=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=B3=E9=94=AE=E8=8F=9C=E5=8D=95=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=E9=80=89=E6=8B=A9=E5=99=A8=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B7=B1=E8=89=B2=E4=B8=BB=E9=A2=98=E6=98=BE=E7=A4=BA=E6=95=88?= =?UTF-8?q?=E6=9E=9C=20-=20=E4=BF=AE=E5=A4=8D=E8=A1=A8=E6=A0=BC=E9=AB=98?= =?UTF-8?q?=E5=BA=A6=E9=80=82=E9=85=8D=E6=80=A7=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=93=8D=E5=BA=94=E5=BC=8F=E9=AB=98=E5=BA=A6?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20-=20=E5=A2=9E=E5=BC=BA=E9=A2=9C=E8=89=B2?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8=E7=9A=84=E5=8F=AF=E8=A7=81=E6=80=A7?= =?UTF-8?q?=E5=92=8C=E4=BA=A4=E4=BA=92=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protocol-logs/ProtocolLogsTable.tsx | 192 +++++++++++++++++- .../OnlineProtocolLogsView.tsx | 6 +- .../protocol-logs/HistoryProtocolLogsView.tsx | 6 +- src/modify.md | 111 ++++++++++ 4 files changed, 305 insertions(+), 10 deletions(-) diff --git a/src/X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx b/src/X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx index f1436df..87762ad 100644 --- a/src/X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx +++ b/src/X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx @@ -1,10 +1,11 @@ -import React, { useState } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { ProtocolLogDto, protocolLogsService } from '@/services/protocolLogsService'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Drawer, DrawerContent, DrawerHeader } from '@/components/ui/drawer'; -import { Eye, X, Loader2 } from 'lucide-react'; + +import { Eye, X, Loader2, Palette, Type, RotateCcw } from 'lucide-react'; import { cn } from '@/lib/utils'; import { DensityType } from '@/components/ui/TableToolbar'; import { getProtocolLayerLabel } from '@/constants/protocolLayerOptions'; @@ -18,6 +19,12 @@ interface ProtocolLogsTableProps { density: DensityType; } +// 行样式接口 +interface RowStyle { + backgroundColor?: string; + color?: string; +} + export default function ProtocolLogsTable({ protocolLogs, loading, @@ -29,6 +36,100 @@ export default function ProtocolLogsTable({ const [loadingMessageDetail, setLoadingMessageDetail] = useState(false); const { toast } = useToast(); + // 右键菜单状态 + const [contextMenu, setContextMenu] = useState<{ + visible: boolean; + x: number; + y: number; + rowId: string; + }>({ + visible: false, + x: 0, + y: 0, + rowId: '', + }); + + // 行样式状态 + const [rowStyles, setRowStyles] = useState>({}); + + // 颜色选项 - 优化深色主题下的可见性 + const backgroundColorOptions = [ + { name: '浅红色', value: '#fef2f2', borderColor: '#fecaca' }, + { name: '浅橙色', value: '#fff7ed', borderColor: '#fed7aa' }, + { name: '浅黄色', value: '#fefce8', borderColor: '#fde68a' }, + { name: '浅绿色', value: '#f0fdf4', borderColor: '#bbf7d0' }, + { name: '浅蓝色', value: '#eff6ff', borderColor: '#bfdbfe' }, + { name: '浅紫色', value: '#faf5ff', borderColor: '#ddd6fe' }, + { name: '浅灰色', value: '#f9fafb', borderColor: '#d1d5db' }, + ]; + + const textColorOptions = [ + { name: '黑色', value: '#000000' }, + { name: '红色', value: '#dc2626' }, + { name: '橙色', value: '#ea580c' }, + { name: '黄色', value: '#ca8a04' }, + { name: '绿色', value: '#16a34a' }, + { name: '蓝色', value: '#2563eb' }, + { name: '紫色', value: '#7c3aed' }, + { name: '灰色', value: '#6b7280' }, + ]; + + // 处理右键菜单 + const handleContextMenu = (event: React.MouseEvent, rowId: string) => { + event.preventDefault(); + setContextMenu({ + visible: true, + x: event.clientX, + y: event.clientY, + rowId, + }); + }; + + // 关闭右键菜单 + const closeContextMenu = () => { + setContextMenu(prev => ({ ...prev, visible: false })); + }; + + // 设置背景颜色 + const setBackgroundColor = (rowId: string, color: string) => { + setRowStyles(prev => ({ + ...prev, + [rowId]: { ...prev[rowId], backgroundColor: color } + })); + closeContextMenu(); + }; + + // 设置字体颜色 + const setTextColor = (rowId: string, color: string) => { + setRowStyles(prev => ({ + ...prev, + [rowId]: { ...prev[rowId], color: color } + })); + closeContextMenu(); + }; + + // 清空行样式 + const clearRowStyle = (rowId: string) => { + setRowStyles(prev => { + const newStyles = { ...prev }; + delete newStyles[rowId]; + return newStyles; + }); + closeContextMenu(); + }; + + // 点击外部关闭右键菜单 + useEffect(() => { + const handleClickOutside = () => { + closeContextMenu(); + }; + + if (contextMenu.visible) { + document.addEventListener('click', handleClickOutside); + return () => document.removeEventListener('click', handleClickOutside); + } + }, [contextMenu.visible]); + // 密度样式映射 - 更紧凑的样式 const densityStyles = { relaxed: 'py-2 px-2', @@ -280,7 +381,7 @@ export default function ProtocolLogsTable({ {/* 可滚动的表体 */} -
+
{loading ? ( @@ -302,7 +403,12 @@ export default function ProtocolLogsTable({ ) : ( protocolLogs.map((log, index) => ( - + handleContextMenu(event, log.id)} + > {visibleColumns.map((column) => ( + + {/* 右键菜单 */} + {contextMenu.visible && ( +
+ {/* 背景颜色选择 */} +
+
+ + 背景颜色 +
+
+ {backgroundColorOptions.map((color) => ( + + ))} +
+
+ + {/* 字体颜色选择 */} +
+
+ + 字体颜色 +
+
+ {textColorOptions.map((color) => ( + + ))} +
+
+ + {/* 分隔线 */} +
+ + {/* 清空样式 */} + +
+ )} ); } \ No newline at end of file diff --git a/src/X1.WebUI/src/pages/online-protocol-logs/OnlineProtocolLogsView.tsx b/src/X1.WebUI/src/pages/online-protocol-logs/OnlineProtocolLogsView.tsx index b63ed6b..7c9bef8 100644 --- a/src/X1.WebUI/src/pages/online-protocol-logs/OnlineProtocolLogsView.tsx +++ b/src/X1.WebUI/src/pages/online-protocol-logs/OnlineProtocolLogsView.tsx @@ -15,14 +15,14 @@ import { Badge } from '@/components/ui/badge'; import { ChevronDown, X } from 'lucide-react'; const defaultColumns = [ - { key: 'layerType', title: 'Layer Type', visible: true }, { key: 'time', title: 'Time', visible: true }, { key: 'plmn', title: 'PLMN', visible: true }, - { key: 'info', title: 'Info', visible: true }, - { key: 'ueid', title: 'UEID', visible: true }, { key: 'imsi', title: 'IMSI', visible: true }, + { key: 'ueid', title: 'UEID', visible: true }, { key: 'cellID', title: 'CellID', visible: true }, { key: 'direction', title: 'Direction', visible: true }, + { key: 'info', title: 'Info', visible: true }, + { key: 'layerType', title: 'Layer', visible: true }, { key: 'message', title: 'Message', visible: true }, { key: 'MessageDetailJson', title: 'Detail', visible: true }, ]; diff --git a/src/X1.WebUI/src/pages/protocol-logs/HistoryProtocolLogsView.tsx b/src/X1.WebUI/src/pages/protocol-logs/HistoryProtocolLogsView.tsx index febe503..434b19e 100644 --- a/src/X1.WebUI/src/pages/protocol-logs/HistoryProtocolLogsView.tsx +++ b/src/X1.WebUI/src/pages/protocol-logs/HistoryProtocolLogsView.tsx @@ -15,14 +15,14 @@ import { Badge } from '@/components/ui/badge'; import { ChevronDown, X } from 'lucide-react'; const defaultColumns = [ - { key: 'layerType', title: 'Layer Type', visible: true }, { key: 'time', title: 'Time', visible: true }, { key: 'plmn', title: 'PLMN', visible: true }, - { key: 'info', title: 'Info', visible: true }, - { key: 'ueid', title: 'UEID', visible: true }, { key: 'imsi', title: 'IMSI', visible: true }, + { key: 'ueid', title: 'UEID', visible: true }, { key: 'cellID', title: 'CellID', visible: true }, { key: 'direction', title: 'Direction', visible: true }, + { key: 'info', title: 'Info', visible: true }, + { key: 'layerType', title: 'Layer', visible: true }, { key: 'message', title: 'Message', visible: true }, { key: 'MessageDetailJson', title: 'Detail', visible: true }, ]; diff --git a/src/modify.md b/src/modify.md index 5528a1c..f3d8609 100644 --- a/src/modify.md +++ b/src/modify.md @@ -2,6 +2,117 @@ ## 2024年修改记录 +### 协议日志表格右键菜单功能 + +#### 修改文件: +`X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx` + +#### 修改内容: + +1. **功能描述**: + - 为协议日志表格添加了右键菜单功能 + - 支持选择背景颜色和字体颜色 + - 提供清空样式功能 + +2. **新增功能**: + - **右键菜单触发**:在表格行上右键点击可打开菜单 + - **背景颜色选择**:提供7种浅色背景选项(浅红、浅橙、浅黄、浅绿、浅蓝、浅紫、浅灰) + - **字体颜色选择**:提供8种字体颜色选项(黑、红、橙、黄、绿、蓝、紫、灰) + - **清空样式**:一键清除当前行的所有自定义样式 + +3. **技术实现**: + - 添加了 `RowStyle` 接口定义行样式结构 + - 使用 `useState` 管理行样式状态 `rowStyles` + - 实现了右键菜单状态管理 `contextMenu` + - 添加了颜色选项配置数组 + - 实现了样式设置和清空的相关函数 + +4. **UI设计**: + - 使用网格布局展示颜色选择器 + - 背景颜色显示为彩色方块 + - 字体颜色显示为带字母A的彩色方块 + - 添加了悬停效果和过渡动画 + - 使用图标区分不同功能区域 + +5. **交互体验**: + - 右键菜单在鼠标位置显示 + - 点击外部自动关闭菜单 + - 颜色选择器支持悬停预览 + - 样式变更即时生效 + +6. **代码结构**: + ```tsx + // 行样式接口 + interface RowStyle { + backgroundColor?: string; + color?: string; + } + + // 右键菜单状态 + const [contextMenu, setContextMenu] = useState<{ + visible: boolean; + x: number; + y: number; + rowId: string; + }>(); + + // 行样式状态 + const [rowStyles, setRowStyles] = useState>({}); + ``` + +#### 修改时间: +2024年 + +#### 修改原因: +增强协议日志表格的交互功能,允许用户通过右键菜单自定义行的背景颜色和字体颜色,提升数据可视化和用户体验。 + +--- + +### 协议日志表格高度适配性优化 + +#### 修改文件: +`X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx` + +#### 修改内容: + +1. **问题描述**: + - 原代码使用固定的 `max-h-[600px]` 高度设置 + - 导致在不同屏幕尺寸下无法良好适配 + - 在小屏幕设备上可能出现显示问题 + +2. **解决方案**: + - 将固定高度 `max-h-[600px]` 替换为响应式高度设置 + - 使用 `calc()` 函数结合视口高度(vh)进行动态计算 + - 添加最小高度限制确保在小屏幕上的可用性 + +3. **具体修改**: + ```tsx + // 修改前 +
+ + // 修改后 +
+ ``` + +4. **新高度设置说明**: + - `h-[calc(100vh-400px)]`:设置表格高度为视口高度减去400px(为页面其他元素预留空间) + - `min-h-[300px]`:设置最小高度为300px,确保在小屏幕上仍有足够的显示空间 + - `max-h-[calc(100vh-200px)]`:设置最大高度为视口高度减去200px,防止在大屏幕上占用过多空间 + - `overflow-auto`:保持原有的滚动功能 + +5. **优势**: + - **响应式设计**:能够根据不同的屏幕尺寸自动调整 + - **更好的用户体验**:在各种设备上都能提供合适的显示效果 + - **保持功能完整性**:滚动功能和其他交互特性保持不变 + +#### 修改时间: +2024年 + +#### 修改原因: +解决协议日志表格在不同屏幕尺寸下的适配性问题,提升用户体验。 + +--- + ### 协议日志仓储修改 #### 修改文件: