feat(dc-tool-c): Tool C UX重大改进 - 列头筛选/行号/滚动条/全量数据
新功能 - 列头筛选:Excel风格筛选功能(Community版本,中文本地化,显示唯一值及计数) - 行号列:添加固定行号列(#列头,灰色背景,左侧固定) - 全量数据加载:不再限制50行预览,Session加载全量数据 - 全量数据返回:所有快速操作(筛选/映射/分箱/条件/删NA/计算/Pivot)全量返回结果 Bug修复 - 滚动条终极修复:修改MainLayout为固定高度(h-screen + overflow-hidden),整个浏览器窗口无滚动条,只有AG Grid内部滚动 - 计算列全角字符修复:自动转换中文括号等全角字符为半角 - 计算列特殊字符列名修复:完善列别名机制,支持任意特殊字符列名 UI优化 - 删除'表格仅展示前50行'提示条,减少干扰 - 筛选对话框美化:白色背景,圆角,阴影 - 列头筛选图标优化:清晰可见,易于点击 文档更新 - 工具C_功能按钮开发计划_V1.0.md:添加V1.5版本记录 - 工具C_MVP开发_TODO清单.md:添加Day 8 UX优化内容 - 00-工具C当前状态与开发指南.md:更新进度为98% - 00-模块当前状态与开发指南.md:更新DC模块状态 - 00-系统当前状态与开发指南.md:更新系统整体状态 影响范围 - Python微服务:无修改 - Node.js后端:5处代码修改(SessionService + QuickActionController + AICodeService) - 前端:MainLayout + DataGrid + ag-grid-custom.css + index.tsx - 完成度:Tool C整体完成度提升至98% 代码统计 - 修改文件:~15个文件 - 新增行数:~200行 - 修改行数:~150行 Co-authored-by: AI Assistant <assistant@example.com>
This commit is contained in:
@@ -17,12 +17,12 @@ import ErrorBoundary from '../modules/ErrorBoundary'
|
||||
*/
|
||||
const MainLayout = () => {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gray-50">
|
||||
<div className="h-screen flex flex-col overflow-hidden bg-gray-50">
|
||||
{/* 顶部导航 */}
|
||||
<TopNavigation />
|
||||
|
||||
{/* 主内容区 - 添加错误边界保护 ⭐ */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
<div className="flex-1 flex flex-col overflow-hidden">
|
||||
<ErrorBoundary moduleName="主应用">
|
||||
<Suspense
|
||||
fallback={
|
||||
|
||||
@@ -107,7 +107,7 @@ export const getSession = async (sessionId: string): Promise<SessionData> => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取预览数据(前100行)
|
||||
* 获取预览数据(⭐ 已改为全量加载)
|
||||
*/
|
||||
export const getPreviewData = async (sessionId: string): Promise<PreviewData> => {
|
||||
const response = await axios.get(`${BASE_URL}/sessions/${sessionId}/preview`);
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useMemo } from 'react';
|
||||
import { AgGridReact } from 'ag-grid-react';
|
||||
import { ColDef, ModuleRegistry, AllCommunityModule } from 'ag-grid-community';
|
||||
|
||||
// 注册 AG Grid 模块(修复 error #272)
|
||||
// ⭐ 注册 AG Grid 模块(必需!)
|
||||
ModuleRegistry.registerModules([AllCommunityModule]);
|
||||
|
||||
// 引入AG Grid样式
|
||||
@@ -23,27 +23,110 @@ interface DataGridProps {
|
||||
onCellValueChanged?: (params: any) => void;
|
||||
}
|
||||
|
||||
// ✨ 自定义表头组件(带tooltip)
|
||||
const CustomHeader = (props: any) => {
|
||||
return (
|
||||
<div
|
||||
className="ag-header-cell-label"
|
||||
title={props.displayName}
|
||||
style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{props.displayName}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
// ❌ 移除自定义表头组件,使用AG Grid默认表头(支持筛选、排序、菜单)
|
||||
// 原因:自定义表头会覆盖筛选图标,影响Excel风格筛选功能
|
||||
|
||||
const DataGrid: React.FC<DataGridProps> = ({ data, columns, onCellValueChanged }) => {
|
||||
// 防御性编程:确保 data 和 columns 始终是数组
|
||||
const safeData = data || [];
|
||||
const safeColumns = columns || [];
|
||||
|
||||
// ⭐ AG Grid 汉化配置(必须在所有条件判断之前,确保Hooks顺序一致)
|
||||
const localeText = useMemo(() => ({
|
||||
// 筛选相关
|
||||
selectAll: '(全选)',
|
||||
selectAllSearchResults: '(选择所有搜索结果)',
|
||||
searchOoo: '搜索...',
|
||||
blanks: '(空白)',
|
||||
noMatches: '无匹配项',
|
||||
|
||||
// 筛选按钮
|
||||
filterOoo: '筛选...',
|
||||
applyFilter: '确定',
|
||||
cancelFilter: '取消',
|
||||
clearFilter: '清除',
|
||||
resetFilter: '重置',
|
||||
|
||||
// 菜单
|
||||
pinColumn: '固定列',
|
||||
pinLeft: '固定到左侧',
|
||||
pinRight: '固定到右侧',
|
||||
noPin: '不固定',
|
||||
autosizeThiscolumn: '自动调整此列',
|
||||
autosizeAllColumns: '自动调整所有列',
|
||||
resetColumns: '重置列',
|
||||
|
||||
// 排序
|
||||
sortAscending: '升序',
|
||||
sortDescending: '降序',
|
||||
sortUnSort: '取消排序',
|
||||
|
||||
// 通用
|
||||
loadingOoo: '加载中...',
|
||||
noRowsToShow: '无数据',
|
||||
enabled: '已启用',
|
||||
disabled: '已禁用',
|
||||
|
||||
// 分页(如果启用)
|
||||
page: '页',
|
||||
more: '更多',
|
||||
to: '到',
|
||||
of: '共',
|
||||
next: '下一页',
|
||||
last: '最后一页',
|
||||
first: '第一页',
|
||||
previous: '上一页',
|
||||
|
||||
// 其他
|
||||
columns: '列',
|
||||
filters: '筛选器',
|
||||
rowGroupColumns: '行分组列',
|
||||
rowGroupColumnsEmptyMessage: '拖拽到此处进行行分组',
|
||||
valueColumns: '值列',
|
||||
pivotMode: '透视模式',
|
||||
groups: '分组',
|
||||
values: '值',
|
||||
pivots: '透视',
|
||||
toolPanel: '工具面板',
|
||||
|
||||
// Set Filter特定
|
||||
contains: '包含',
|
||||
notContains: '不包含',
|
||||
equals: '等于',
|
||||
notEqual: '不等于',
|
||||
startsWith: '以...开头',
|
||||
endsWith: '以...结尾',
|
||||
}), []);
|
||||
|
||||
// 转换列定义为AG Grid格式
|
||||
const columnDefs: ColDef[] = useMemo(() => {
|
||||
return safeColumns.map((col, index) => {
|
||||
// ⭐ 行号列(固定在最左侧)
|
||||
const rowNumberColumn: ColDef = {
|
||||
headerName: '#',
|
||||
field: 'rowNumber',
|
||||
valueGetter: (params: any) => {
|
||||
return params.node?.rowIndex != null ? params.node.rowIndex + 1 : '';
|
||||
},
|
||||
width: 60,
|
||||
minWidth: 60,
|
||||
maxWidth: 80,
|
||||
pinned: 'left', // 固定在左侧
|
||||
lockPosition: true, // 锁定位置,不可拖动
|
||||
sortable: false, // 不可排序
|
||||
filter: false, // 不可筛选
|
||||
resizable: false, // 不可调整大小
|
||||
cellStyle: {
|
||||
textAlign: 'center',
|
||||
fontWeight: '500',
|
||||
color: '#64748b',
|
||||
backgroundColor: '#f8fafc',
|
||||
borderRight: '2px solid #e2e8f0',
|
||||
},
|
||||
headerClass: 'row-number-header',
|
||||
};
|
||||
|
||||
// 数据列
|
||||
const dataColumns = safeColumns.map((col, index) => {
|
||||
// ✅ 优化1.2:自动检测是否为数值列
|
||||
const sampleValues = safeData.slice(0, 10).map(row => row[col.id]);
|
||||
const isNumericColumn = sampleValues.length > 0 && sampleValues.every(
|
||||
@@ -54,26 +137,28 @@ const DataGrid: React.FC<DataGridProps> = ({ data, columns, onCellValueChanged }
|
||||
// ✅ 修复:使用安全的field名(索引),通过valueGetter获取实际数据
|
||||
field: `col_${index}`,
|
||||
headerName: col.name,
|
||||
// ✅ 优化:添加tooltip显示完整列名(双保险)
|
||||
// ✅ 优化:添加tooltip显示完整列名
|
||||
headerTooltip: col.name,
|
||||
// ✨ 使用自定义表头组件(确保tooltip一定显示)
|
||||
headerComponent: CustomHeader,
|
||||
headerComponentParams: {
|
||||
displayName: col.name,
|
||||
},
|
||||
// ✅ 关键修复:使用valueGetter直接从原始数据中获取值
|
||||
valueGetter: (params: any) => {
|
||||
return params.data?.[col.id];
|
||||
},
|
||||
sortable: true,
|
||||
filter: true,
|
||||
filter: true, // ⭐ 启用筛选器
|
||||
floatingFilter: false, // ❌ 不显示浮动筛选框(不需要搜索框)
|
||||
resizable: true,
|
||||
editable: false, // MVP阶段暂不支持手动编辑
|
||||
width: 90, // ✅ 优化:减小40%(原150 -> 90)
|
||||
minWidth: 60,
|
||||
|
||||
// ⭐ 筛选器配置
|
||||
filterParams: {
|
||||
buttons: ['clear', 'apply'],
|
||||
closeOnApply: true,
|
||||
},
|
||||
|
||||
// ✅ 优化1.3:缺失值高亮(新CSS类名)
|
||||
cellClass: (params) => {
|
||||
cellClass: (params: any) => {
|
||||
if (
|
||||
params.value === null ||
|
||||
params.value === undefined ||
|
||||
@@ -95,6 +180,9 @@ const DataGrid: React.FC<DataGridProps> = ({ data, columns, onCellValueChanged }
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
// ⭐ 返回:行号列 + 数据列
|
||||
return [rowNumberColumn, ...dataColumns];
|
||||
}, [safeColumns, safeData]);
|
||||
|
||||
// 默认列配置
|
||||
@@ -102,10 +190,11 @@ const DataGrid: React.FC<DataGridProps> = ({ data, columns, onCellValueChanged }
|
||||
() => ({
|
||||
flex: 0,
|
||||
sortable: true,
|
||||
filter: true,
|
||||
filter: true, // ⭐ 启用筛选
|
||||
resizable: true,
|
||||
floatingFilter: false, // ❌ 不显示浮动筛选框
|
||||
}),
|
||||
[safeColumns]
|
||||
[]
|
||||
);
|
||||
|
||||
// 空状态
|
||||
@@ -138,8 +227,8 @@ const DataGrid: React.FC<DataGridProps> = ({ data, columns, onCellValueChanged }
|
||||
enableCellTextSelection={true}
|
||||
// ✅ 启用浏览器原生tooltip(让headerTooltip生效)
|
||||
enableBrowserTooltips={true}
|
||||
// ✅ 修复 AG Grid #239:使用 legacy 主题模式
|
||||
theme="legacy"
|
||||
// ⭐ 汉化配置
|
||||
localeText={localeText}
|
||||
// 性能优化
|
||||
rowBuffer={10}
|
||||
debounceVerticalScrollbar={true}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Modal, Tabs, Radio, Select, Input, Checkbox, Alert, App, Row, Col, InputNumber, Space } from 'antd';
|
||||
import { Modal, Tabs, Radio, Select, Input, Checkbox, Alert, App, Row, Col, InputNumber, Space, Collapse } from 'antd';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
@@ -34,6 +34,7 @@ const MissingValueDialog: React.FC<Props> = ({
|
||||
|
||||
// Tab 3: MICE相关状态
|
||||
const [miceColumns, setMiceColumns] = useState<string[]>([]);
|
||||
const [referenceColumns, setReferenceColumns] = useState<string[]>([]); // ⭐ 新增:参考列
|
||||
const [nIterations, setNIterations] = useState(10);
|
||||
const [randomState, setRandomState] = useState(42);
|
||||
|
||||
@@ -183,6 +184,7 @@ const MissingValueDialog: React.FC<Props> = ({
|
||||
body: JSON.stringify({
|
||||
sessionId,
|
||||
columns: miceColumns,
|
||||
referenceColumns, // ⭐ 新增:传递参考列
|
||||
nIterations,
|
||||
randomState
|
||||
})
|
||||
@@ -355,51 +357,82 @@ const MissingValueDialog: React.FC<Props> = ({
|
||||
},
|
||||
{
|
||||
key: 'mice',
|
||||
label: '高级填补',
|
||||
label: '多重插补',
|
||||
children: (
|
||||
<div className="space-y-4">
|
||||
<Alert
|
||||
message="⭐ MICE多重插补 - 医学研究高质量填补的首选方法"
|
||||
type="success"
|
||||
message="💡 提示:MICE仅支持数值列(分类列会自动跳过)"
|
||||
type="info"
|
||||
showIcon
|
||||
description="MICE会根据其他变量的值来预测缺失值,适合缺失率5%-30%、需要考虑变量间相关性的场景。"
|
||||
/>
|
||||
|
||||
<Alert
|
||||
message="⚠️ 重要:MICE仅适用于数值列"
|
||||
type="warning"
|
||||
showIcon
|
||||
description={
|
||||
<div className="text-sm">
|
||||
<div>• ✅ 适合:年龄、体重、血压、评分等数值列</div>
|
||||
<div>• ❌ 不适合:婚姻状况、性别、职业等分类列(请使用"众数填补")</div>
|
||||
<div className="mt-2 text-orange-600">分类列如果被选中,会自动跳过并创建原样副本列</div>
|
||||
</div>
|
||||
}
|
||||
<Collapse
|
||||
defaultActiveKey={['target']}
|
||||
items={[
|
||||
{
|
||||
key: 'target',
|
||||
label: (
|
||||
<span className="font-medium">
|
||||
需要填补的列(创建新列)
|
||||
{miceColumns.length > 0 && (
|
||||
<span className="ml-2 text-blue-600">
|
||||
已选 {miceColumns.length} 列
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
children: (
|
||||
<Checkbox.Group
|
||||
value={miceColumns}
|
||||
onChange={setMiceColumns}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
{columns.map(col => (
|
||||
<Checkbox key={col.id} value={col.name}>
|
||||
{col.name}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Space>
|
||||
</Checkbox.Group>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'reference',
|
||||
label: (
|
||||
<span className="font-medium">
|
||||
⭐ 参考列(用于预测,不创建新列)
|
||||
{referenceColumns.length > 0 && (
|
||||
<span className="ml-2 text-green-600">
|
||||
已选 {referenceColumns.length} 列
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
children: (
|
||||
<Checkbox.Group
|
||||
value={referenceColumns}
|
||||
onChange={setReferenceColumns}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
{columns.map(col => (
|
||||
<Checkbox key={col.id} value={col.name}>
|
||||
{col.name}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Space>
|
||||
</Checkbox.Group>
|
||||
)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<div className="mb-2 font-medium">选择要填补的列(可多选):</div>
|
||||
<Checkbox.Group
|
||||
value={miceColumns}
|
||||
onChange={setMiceColumns}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Space direction="vertical">
|
||||
{columns.map(col => (
|
||||
<Checkbox key={col.id} value={col.name}>
|
||||
{col.name}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Space>
|
||||
</Checkbox.Group>
|
||||
</div>
|
||||
|
||||
<div className="p-3 bg-blue-50 rounded">
|
||||
<div className="text-sm space-y-1">
|
||||
<div>• 新列命名:原列名 + "_MICE"</div>
|
||||
<div>• 新列位置:紧邻各原列</div>
|
||||
<div>• 计算时间:10万行约1分钟</div>
|
||||
<div>📊 将使用 <span className="font-bold text-blue-600">{miceColumns.length + referenceColumns.length}</span> 个列进行计算({miceColumns.length}个目标 + {referenceColumns.length}个参考)</div>
|
||||
<div>📝 预计创建 <span className="font-bold text-green-600">{miceColumns.length}</span> 个新列</div>
|
||||
<div>⏱️ 计算时间:10万行约1分钟</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -158,4 +158,83 @@
|
||||
font-variant-numeric: tabular-nums; /* 等宽数字 */
|
||||
}
|
||||
|
||||
/* ==================== 筛选弹窗样式(⭐ 新增)==================== */
|
||||
/* 筛选菜单背景(不透明) */
|
||||
.ag-theme-alpine .ag-popup,
|
||||
.ag-theme-alpine .ag-menu {
|
||||
background-color: #ffffff !important; /* ⭐ 白色背景,不透明 */
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important; /* 添加阴影 */
|
||||
border: 1px solid #d1d5db !important;
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
|
||||
/* 筛选器容器 */
|
||||
.ag-theme-alpine .ag-filter {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 筛选器工具面板 */
|
||||
.ag-theme-alpine .ag-filter-toolpanel {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 下拉选择框背景 */
|
||||
.ag-theme-alpine .ag-select {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
/* 输入框背景 */
|
||||
.ag-theme-alpine .ag-input-field-input {
|
||||
background-color: #ffffff !important;
|
||||
padding-left: 30px !important; /* ⭐ 大幅增加左侧间距(10px -> 30px)*/
|
||||
padding-right: 35px !important; /* ⭐ 大幅增加右侧间距(避免与清除按钮重叠)*/
|
||||
}
|
||||
|
||||
/* ⭐ 强力隐藏筛选输入框的清除按钮(多种选择器覆盖)*/
|
||||
.ag-theme-alpine .ag-filter .ag-input-field-input-wrapper .ag-icon-cancel,
|
||||
.ag-theme-alpine .ag-filter .ag-icon-cancel,
|
||||
.ag-theme-alpine .ag-filter .ag-input-field-clear-button,
|
||||
.ag-theme-alpine .ag-filter-filter .ag-icon-cancel,
|
||||
.ag-theme-alpine .ag-text-field .ag-icon-cancel,
|
||||
.ag-theme-alpine .ag-picker-field .ag-icon-cancel,
|
||||
.ag-theme-alpine [class*="ag-icon-cancel"] {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
opacity: 0 !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
/* ⭐ 确保输入框容器不显示清除按钮 */
|
||||
.ag-theme-alpine .ag-filter .ag-input-field-input-wrapper::after {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* ==================== 行号列样式(⭐ 新增)==================== */
|
||||
/* 行号列表头 */
|
||||
.ag-theme-alpine .ag-header-cell.row-number-header {
|
||||
background-color: #f1f5f9 !important;
|
||||
font-weight: 600 !important;
|
||||
text-align: center !important;
|
||||
border-right: 2px solid #e2e8f0 !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
/* 行号列单元格(通过pinned列定位)*/
|
||||
.ag-theme-alpine .ag-pinned-left-cols-container .ag-cell {
|
||||
background-color: #f8fafc !important;
|
||||
border-right: 2px solid #e2e8f0 !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
/* 行号列悬停效果 */
|
||||
.ag-theme-alpine .ag-row:hover .ag-pinned-left-cols-container .ag-cell {
|
||||
background-color: #f1f5f9 !important;
|
||||
}
|
||||
|
||||
/* 行号列选中效果 */
|
||||
.ag-theme-alpine .ag-row-selected .ag-pinned-left-cols-container .ag-cell {
|
||||
background-color: #dbeafe !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ const ToolC = () => {
|
||||
|
||||
// ==================== 渲染 ====================
|
||||
return (
|
||||
<div className="h-screen w-screen flex flex-col bg-gradient-to-br from-slate-50 to-slate-100">
|
||||
<div className="h-screen w-screen flex flex-col bg-gradient-to-br from-slate-50 to-slate-100 overflow-hidden">
|
||||
{/* 顶部栏 */}
|
||||
<Header
|
||||
fileName={state.fileName || '未上传文件'}
|
||||
@@ -239,10 +239,10 @@ const ToolC = () => {
|
||||
onToggleSidebar={() => updateState({ isSidebarOpen: !state.isSidebarOpen })}
|
||||
/>
|
||||
|
||||
{/* 主工作区 - 移除overflow-hidden,让子元素自己处理滚动 */}
|
||||
<div className="flex-1 flex min-h-0">
|
||||
{/* 左侧:表格区域 - 独立滚动 */}
|
||||
<div className="flex-1 flex flex-col min-w-0">
|
||||
{/* 主工作区 - ⭐ Phase 1: 添加overflow-hidden禁止页面滚动 */}
|
||||
<div className="flex-1 flex min-h-0 overflow-hidden">
|
||||
{/* 左侧:表格区域 - ⭐ 添加overflow-hidden */}
|
||||
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||||
<Toolbar
|
||||
sessionId={state.sessionId}
|
||||
onFilterClick={() => updateState({ filterDialogVisible: true })}
|
||||
@@ -253,28 +253,10 @@ const ToolC = () => {
|
||||
onComputeClick={() => updateState({ computeDialogVisible: true })}
|
||||
onPivotClick={() => updateState({ pivotDialogVisible: true })}
|
||||
/>
|
||||
<div className="flex-1 p-4 flex flex-col min-h-0">
|
||||
<div className="flex-1 p-4 flex flex-col min-h-0 overflow-hidden">
|
||||
{/* ✨ 优化:提示只显示前50行(可关闭) */}
|
||||
{state.data.length > 0 && !state.isAlertClosed && (
|
||||
<div className="mb-2 px-3 py-2 bg-blue-50 border border-blue-200 rounded-lg flex items-center justify-between gap-2 text-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-blue-600">ℹ️</span>
|
||||
<span className="text-blue-700">
|
||||
<strong>提示:</strong>表格仅展示前 <strong>50行</strong> 数据预览,导出功能将包含 <strong>全部</strong> 处理结果
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => updateState({ isAlertClosed: true })}
|
||||
className="text-blue-400 hover:text-blue-600 transition-colors p-1 rounded hover:bg-blue-100"
|
||||
title="关闭提示"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 min-h-0">
|
||||
{/* ⭐ 已删除:表格仅展示前50行提示(现在是全量显示)*/}
|
||||
<div className="flex-1 min-h-0 overflow-hidden">
|
||||
<DataGrid data={state.data} columns={state.columns} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user