From 39e52469f2615be338a6f684d94d1cca9a4c76bf Mon Sep 17 00:00:00 2001 From: Syngnat Date: Fri, 19 Jun 2026 17:23:53 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(sidebar):=20?= =?UTF-8?q?=E6=8A=BD=E5=87=BA=E6=89=B9=E9=87=8F=E6=93=8D=E4=BD=9C=E5=BC=B9?= =?UTF-8?q?=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Sidebar.tsx | 341 ++------------ .../sidebar/SidebarBatchExportModals.tsx | 415 ++++++++++++++++++ 2 files changed, 459 insertions(+), 297 deletions(-) create mode 100644 frontend/src/components/sidebar/SidebarBatchExportModals.tsx diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index dcadb91..81548a7 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -28,9 +28,8 @@ import { } from './sidebar/sidebarMetadataLoaders'; import { useSidebarBatchExport, - type BatchObjectFilterType, - type BatchSelectionScope, } from './sidebar/useSidebarBatchExport'; +import { SidebarBatchExportModals } from './sidebar/SidebarBatchExportModals'; import { ExternalSQLFileModal, SQLFileExecutionModal, @@ -6179,301 +6178,49 @@ const Sidebar: React.FC<{ - , "批量操作表", "按对象批量导出结构、数据或完整备份。")} - open={isBatchModalOpen} - onCancel={() => setIsBatchModalOpen(false)} - width={720} - centered - styles={{ content: modalPanelStyle, header: { background: 'transparent', borderBottom: 'none', paddingBottom: 10 }, body: { paddingTop: 8 }, footer: { background: 'transparent', borderTop: 'none', paddingTop: 12 } }} - footer={ -
- - - - - - - -
- } - > -
-
- - -
-
- - -
-
先选择连接与数据库,再决定导出范围和目标对象。
-
- - {batchTables.length > 0 && ( -
- - setBatchFilterKeyword(e.target.value)} - placeholder="筛选表/视图名称" - prefix={} - style={{ width: 260 }} - /> - setBatchSelectionScope(value as BatchSelectionScope)} - style={{ width: 220 }} - options={[ - { label: '勾选作用于:当前筛选结果', value: 'filtered' }, - { label: '勾选作用于:全部对象', value: 'all' }, - ]} - /> - -
- 当前筛选命中 {filteredBatchObjects.length} / {batchTables.length} 个对象 -
-
- )} - - {batchTables.length > 0 && ( - <> -
- - - - - - 已选择 {checkedTableKeys.length} / {batchTables.length} 个对象 - - -
-
- setCheckedTableKeys(values as string[])} - style={{ width: '100%' }} - > -
- {groupedBatchObjects.tables.length > 0 && ( -
-
- 表 ({groupedBatchObjects.tables.length}) -
- - {groupedBatchObjects.tables.map(table => ( - - - {table.title} - - ))} - -
- )} - {groupedBatchObjects.views.length > 0 && ( -
-
- 视图 ({groupedBatchObjects.views.length}) -
- - {groupedBatchObjects.views.map(view => ( - - - {view.title} - - ))} - -
- )} - {groupedBatchObjects.tables.length === 0 && groupedBatchObjects.views.length === 0 && ( -
- 无匹配对象 -
- )} -
-
-
- - )} -
- - , "批量操作库", "按数据库批量导出结构,或生成结构加数据的备份。")} - open={isBatchDbModalOpen} - onCancel={() => setIsBatchDbModalOpen(false)} - width={640} - centered - styles={{ content: modalPanelStyle, header: { background: 'transparent', borderBottom: 'none', paddingBottom: 10 }, body: { paddingTop: 8 }, footer: { background: 'transparent', borderTop: 'none', paddingTop: 12 } }} - footer={[ - , - , - - ]} - > -
- - -
连接选定后会加载当前连接下可批量导出的数据库列表。
-
- - {batchDatabases.length > 0 && ( - <> -
- - - - - - 已选择 {checkedDbKeys.length} / {batchDatabases.length} 个库 - - -
-
- setCheckedDbKeys(values as string[])} - style={{ width: '100%' }} - > - - {batchDatabases.map(db => ( - - - {db.title} - - ))} - - -
- - )} -
+ , "批量操作表", "按对象批量导出结构、数据或完整备份。")} + databaseModalTitle={renderSidebarModalTitle(, "批量操作库", "按数据库批量导出结构,或生成结构加数据的备份。")} + isBatchModalOpen={isBatchModalOpen} + setIsBatchModalOpen={setIsBatchModalOpen} + selectedConnection={selectedConnection} + selectedDatabase={selectedDatabase} + availableDatabases={availableDatabases} + batchTables={batchTables} + checkedTableKeys={checkedTableKeys} + setCheckedTableKeys={setCheckedTableKeys} + batchFilterKeyword={batchFilterKeyword} + setBatchFilterKeyword={setBatchFilterKeyword} + batchFilterType={batchFilterType} + setBatchFilterType={setBatchFilterType} + batchSelectionScope={batchSelectionScope} + setBatchSelectionScope={setBatchSelectionScope} + filteredBatchObjects={filteredBatchObjects} + groupedBatchObjects={groupedBatchObjects} + selectionScopeTargetKeys={selectionScopeTargetKeys} + handleConnectionChange={handleConnectionChange} + handleDatabaseChange={handleDatabaseChange} + handleBatchClear={handleBatchClear} + handleBatchExport={handleBatchExport} + handleCheckAll={handleCheckAll} + handleInvertSelection={handleInvertSelection} + isBatchDbModalOpen={isBatchDbModalOpen} + setIsBatchDbModalOpen={setIsBatchDbModalOpen} + selectedDbConnection={selectedDbConnection} + batchDatabases={batchDatabases} + checkedDbKeys={checkedDbKeys} + setCheckedDbKeys={setCheckedDbKeys} + handleDbConnectionChange={handleDbConnectionChange} + handleBatchDbExport={handleBatchDbExport} + handleCheckAllDb={handleCheckAllDb} + handleInvertSelectionDb={handleInvertSelectionDb} + /> void; + selectedConnection: string; + selectedDatabase: string; + availableDatabases: BatchObjectItem[]; + batchTables: BatchObjectItem[]; + checkedTableKeys: string[]; + setCheckedTableKeys: (keys: string[]) => void; + batchFilterKeyword: string; + setBatchFilterKeyword: (value: string) => void; + batchFilterType: BatchObjectFilterType; + setBatchFilterType: (value: BatchObjectFilterType) => void; + batchSelectionScope: BatchSelectionScope; + setBatchSelectionScope: (value: BatchSelectionScope) => void; + filteredBatchObjects: BatchObjectItem[]; + groupedBatchObjects: { + tables: BatchObjectItem[]; + views: BatchObjectItem[]; + }; + selectionScopeTargetKeys: string[]; + handleConnectionChange: (connectionId: string) => void; + handleDatabaseChange: (databaseName: string) => void; + handleBatchClear: () => void; + handleBatchExport: (mode: 'schema' | 'dataOnly' | 'backup') => void; + handleCheckAll: (checked: boolean) => void; + handleInvertSelection: () => void; + isBatchDbModalOpen: boolean; + setIsBatchDbModalOpen: (open: boolean) => void; + selectedDbConnection: string; + batchDatabases: BatchObjectItem[]; + checkedDbKeys: string[]; + setCheckedDbKeys: (keys: string[]) => void; + handleDbConnectionChange: (connectionId: string) => void; + handleBatchDbExport: (includeData: boolean) => void; + handleCheckAllDb: (checked: boolean) => void; + handleInvertSelectionDb: () => void; +}; + +const nonRedisConnections = (connections: SavedConnection[]) => + connections.filter((connection) => connection.config.type !== 'redis'); + +export const SidebarBatchExportModals: React.FC = ({ + connections, + modalPanelStyle, + modalSectionStyle, + modalScrollSectionStyle, + modalHintTextStyle, + darkMode, + tableModalTitle, + databaseModalTitle, + isBatchModalOpen, + setIsBatchModalOpen, + selectedConnection, + selectedDatabase, + availableDatabases, + batchTables, + checkedTableKeys, + setCheckedTableKeys, + batchFilterKeyword, + setBatchFilterKeyword, + batchFilterType, + setBatchFilterType, + batchSelectionScope, + setBatchSelectionScope, + filteredBatchObjects, + groupedBatchObjects, + selectionScopeTargetKeys, + handleConnectionChange, + handleDatabaseChange, + handleBatchClear, + handleBatchExport, + handleCheckAll, + handleInvertSelection, + isBatchDbModalOpen, + setIsBatchDbModalOpen, + selectedDbConnection, + batchDatabases, + checkedDbKeys, + setCheckedDbKeys, + handleDbConnectionChange, + handleBatchDbExport, + handleCheckAllDb, + handleInvertSelectionDb, +}) => ( + <> + setIsBatchModalOpen(false)} + width={720} + centered + styles={{ content: modalPanelStyle, header: { background: 'transparent', borderBottom: 'none', paddingBottom: 10 }, body: { paddingTop: 8 }, footer: { background: 'transparent', borderTop: 'none', paddingTop: 12 } }} + footer={ +
+ + + + + + + +
+ } + > +
+
+ + +
+
+ + +
+
先选择连接与数据库,再决定导出范围和目标对象。
+
+ + {batchTables.length > 0 && ( +
+ + setBatchFilterKeyword(e.target.value)} + placeholder="筛选表/视图名称" + prefix={} + style={{ width: 260 }} + /> + setBatchSelectionScope(value as BatchSelectionScope)} + style={{ width: 220 }} + options={[ + { label: '勾选作用于:当前筛选结果', value: 'filtered' }, + { label: '勾选作用于:全部对象', value: 'all' }, + ]} + /> + +
+ 当前筛选命中 {filteredBatchObjects.length} / {batchTables.length} 个对象 +
+
+ )} + + {batchTables.length > 0 && ( + <> +
+ + + + + + 已选择 {checkedTableKeys.length} / {batchTables.length} 个对象 + + +
+
+ setCheckedTableKeys(values as string[])} + style={{ width: '100%' }} + > +
+ {groupedBatchObjects.tables.length > 0 && ( +
+
+ 表 ({groupedBatchObjects.tables.length}) +
+ + {groupedBatchObjects.tables.map(table => ( + + + {table.title} + + ))} + +
+ )} + {groupedBatchObjects.views.length > 0 && ( +
+
+ 视图 ({groupedBatchObjects.views.length}) +
+ + {groupedBatchObjects.views.map(view => ( + + + {view.title} + + ))} + +
+ )} + {groupedBatchObjects.tables.length === 0 && groupedBatchObjects.views.length === 0 && ( +
+ 无匹配对象 +
+ )} +
+
+
+ + )} +
+ + setIsBatchDbModalOpen(false)} + width={640} + centered + styles={{ content: modalPanelStyle, header: { background: 'transparent', borderBottom: 'none', paddingBottom: 10 }, body: { paddingTop: 8 }, footer: { background: 'transparent', borderTop: 'none', paddingTop: 12 } }} + footer={[ + , + , + , + ]} + > +
+ + +
连接选定后会加载当前连接下可批量导出的数据库列表。
+
+ + {batchDatabases.length > 0 && ( + <> +
+ + + + + + 已选择 {checkedDbKeys.length} / {batchDatabases.length} 个库 + + +
+
+ setCheckedDbKeys(values as string[])} + style={{ width: '100%' }} + > + + {batchDatabases.map(db => ( + + + {db.title} + + ))} + + +
+ + )} +
+ +);