import React from 'react'; import { Button, Dropdown, Tabs, Tooltip, type MenuProps } from 'antd'; import { CloseOutlined, EyeInvisibleOutlined, RobotOutlined } from '@ant-design/icons'; import type { EditRowLocator } from '../utils/rowLocator'; import DataGrid from './DataGrid'; export type QueryEditorResultSet = { key: string; sql: string; exportSql?: string; sourceStatementIndex?: number; statementResultIndex?: number; rows: any[]; columns: string[]; messages?: string[]; resultType?: 'grid' | 'message'; tableName?: string; pkColumns: string[]; editLocator?: EditRowLocator; readOnly: boolean; truncated?: boolean; pkLoading?: boolean; }; interface QueryEditorResultsPanelProps { resultSets: QueryEditorResultSet[]; activeResultKey: string; loading: boolean; executionError: string; darkMode: boolean; isV2Ui: boolean; currentDb: string; currentConnectionId: string; toggleShortcutLabel: string; transactionToolbar?: React.ReactNode; onActiveResultKeyChange: (key: string) => void; onHide: () => void; onCloseResult: (key: string) => void; onCloseOtherResultTabs: (key: string) => void; onCloseResultTabsToLeft: (key: string) => void; onCloseResultTabsToRight: (key: string) => void; onCloseAllResultTabs: () => void; onReloadResult: (key: string, sql: string) => void; onDiagnoseExecutionError: () => void; } const isAffectedRowsResult = (result: QueryEditorResultSet): boolean => result.columns.length === 1 && result.columns[0] === 'affectedRows'; const QueryEditorResultsPanel: React.FC = ({ resultSets, activeResultKey, loading, executionError, darkMode, isV2Ui, currentDb, currentConnectionId, toggleShortcutLabel, transactionToolbar, onActiveResultKeyChange, onHide, onCloseResult, onCloseOtherResultTabs, onCloseResultTabsToLeft, onCloseResultTabsToRight, onCloseAllResultTabs, onReloadResult, onDiagnoseExecutionError, }) => { const resolvedActiveResultKey = activeResultKey || resultSets[0]?.key || ''; const activeResultSet = resultSets.find((rs) => rs.key === resolvedActiveResultKey) || null; const activeResultUsesDataGrid = Boolean( activeResultSet && activeResultSet.resultType !== 'message' && !isAffectedRowsResult(activeResultSet), ); const hideTooltipTitle = toggleShortcutLabel ? `隐藏结果区(${toggleShortcutLabel})` : '隐藏结果区'; const buildResultTabMenuItems = (key: string, index: number): MenuProps['items'] => [ { key: 'close-other', label: '关闭其他页', disabled: resultSets.length <= 1, onClick: () => onCloseOtherResultTabs(key), }, { key: 'close-left', label: '关闭左侧', disabled: index <= 0, onClick: () => onCloseResultTabsToLeft(key), }, { key: 'close-right', label: '关闭右侧', disabled: index >= resultSets.length - 1, onClick: () => onCloseResultTabsToRight(key), }, { type: 'divider' }, { key: 'close-all', label: '关闭所有', disabled: resultSets.length === 0, onClick: onCloseAllResultTabs, }, ]; const hideButton = ( ); const tabsHideButton = ( ); return ( <>
{resultSets.length > 0 ? ( ({ key: rs.key, label: (
{ event.preventDefault(); }} > {rs.resultType === 'message' ? `消息 ${idx + 1}` : `结果 ${idx + 1}`} {(() => { if (rs.resultType === 'message') { return i; } if (isAffectedRowsResult(rs)) { return ; } if (!Array.isArray(rs.rows)) { return null; } return {rs.rows.length}; })()} { e.preventDefault(); e.stopPropagation(); onCloseResult(rs.key); }} >
), children: (() => { if (rs.resultType === 'message') { return (
执行消息
{(rs.messages || []).join('\n')}
); } if (isAffectedRowsResult(rs)) { const affected = Number(rs.rows[0]?.affectedRows ?? 0); return (
执行成功 影响行数:{affected} {Array.isArray(rs.messages) && rs.messages.length > 0 && (
{rs.messages.join('\n')}
)}
); } return (
{Array.isArray(rs.messages) && rs.messages.length > 0 && (
{rs.messages.join('\n')}
)} onReloadResult(rs.key, rs.sql)} readOnly={rs.readOnly} toolbarExtraActions={resolvedActiveResultKey === rs.key ? toolbarHideButton : null} />
); })(), }))} /> ) : executionError ? ( <>
结果区 {hideButton}
执行失败
{executionError}
) : ( <>
结果区 {hideButton}
{isV2Ui && (
等待执行 SQL 运行查询后,结果会在下方以新版数据网格展示。
)}
)}
); }; export default QueryEditorResultsPanel;