From 96ef4d2d6fd6cfeef6b28ce0575bb3282dbe7484 Mon Sep 17 00:00:00 2001 From: zongyangleo Date: Tue, 2 Jun 2026 10:30:29 +0000 Subject: [PATCH] =?UTF-8?q?!157=20refactor:=20kafka=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: es新增导出功能 * refactor: kafka操作优化 --- frontend/src/i18n/en/es.ts | 25 + frontend/src/i18n/en/mq.ts | 6 + frontend/src/i18n/zh-cn/es.ts | 25 + frontend/src/i18n/zh-cn/mq.ts | 6 + .../ops/db/component/table/DbTableData.vue | 29 +- frontend/src/views/ops/es/api.ts | 2 + .../views/ops/es/component/EsIndexData.vue | 528 ++++++++++--- .../ops/mq/kafka/component/ConsumerGroup.vue | 74 +- .../ops/mq/kafka/component/NodeManage.vue | 75 +- .../ops/mq/kafka/component/TopicManage.vue | 6 +- .../views/ops/mq/kafka/resource/KafkaOp.vue | 11 +- .../src/views/ops/resource/ResourceOp.vue | 6 +- frontend/src/views/ops/resource/resourceOp.ts | 10 +- server/go.mod | 6 + server/internal/es/api/es_instance.go | 695 ++++++++++++++++++ server/internal/es/api/form/es_export.go | 9 + 16 files changed, 1374 insertions(+), 139 deletions(-) create mode 100644 server/internal/es/api/form/es_export.go diff --git a/frontend/src/i18n/en/es.ts b/frontend/src/i18n/en/es.ts index 6cdb4798..12100531 100644 --- a/frontend/src/i18n/en/es.ts +++ b/frontend/src/i18n/en/es.ts @@ -100,6 +100,31 @@ export default { text: 'Text', startAnalyze: 'Start Analyze', }, + export: { + title: 'Export Data', + selectedCount: '{count} rows selected', + exportAll: 'Export All Data', + exportSelected: 'Export Selected Data', + exportQuery: 'Export Query Results', + exportType: 'Export Type', + csv: 'CSV File', + excel: 'Excel File', + json: 'JSON File', + confirm: 'Confirm Export', + exporting: 'Exporting...', + exportAllConfirm: 'Export all data from index [{name}] ({total} docs total). Continue?', + largeExportTip: 'Large dataset ({total} docs), will be exported via backend batch processing and compressed download', + selectAllFields: 'Select All Fields', + exportFields: 'Export Fields', + noData: 'No data to export', + phase: { + querying: 'Querying...', + exporting: 'Exporting...', + compressing: 'Compressing...', + completed: 'Completed', + unknown: 'Unknown', + }, + }, contextmenu: { index: { addIndex: 'Add Index', diff --git a/frontend/src/i18n/en/mq.ts b/frontend/src/i18n/en/mq.ts index 69ecd675..d5d2557a 100644 --- a/frontend/src/i18n/en/mq.ts +++ b/frontend/src/i18n/en/mq.ts @@ -83,6 +83,12 @@ export default { searchGroup: 'Enter group name', selectGroupPlaceholder: 'select group', Members: 'Members', + groupMembers: 'Consumer Group Members', + clientHost: 'Client Host', + clientID: 'Client ID', + instanceID: 'Instance ID', + memberID: 'Member ID', + assignedTopics: 'Assigned Topic Partitions', partitionsFeatureComingSoon: 'Partitions feature coming soon', }, }, diff --git a/frontend/src/i18n/zh-cn/es.ts b/frontend/src/i18n/zh-cn/es.ts index 1d9c2d4d..428169be 100644 --- a/frontend/src/i18n/zh-cn/es.ts +++ b/frontend/src/i18n/zh-cn/es.ts @@ -99,6 +99,31 @@ export default { text: '文本', startAnalyze: '开始分析', }, + export: { + title: '导出数据', + selectedCount: '已选择 {count} 条数据', + exportAll: '导出所有数据', + exportSelected: '导出已选数据', + exportQuery: '导出查询结果', + exportType: '导出类型', + csv: 'CSV 文件', + excel: 'Excel 文件', + json: 'JSON 文件', + confirm: '确认导出', + exporting: '正在导出...', + exportAllConfirm: '将导出索引 [{name}] 的所有数据(共 {total} 条),确认继续吗?', + largeExportTip: '数据量较大(共 {total} 条),将通过后台分批查询并压缩后下载', + selectAllFields: '全选字段', + exportFields: '导出字段', + noData: '没有可导出的数据', + phase: { + querying: '正在查询...', + exporting: '正在导出数据...', + compressing: '正在压缩...', + completed: '导出完成', + unknown: '未知状态', + }, + }, contextmenu: { index: { addIndex: '添加索引', diff --git a/frontend/src/i18n/zh-cn/mq.ts b/frontend/src/i18n/zh-cn/mq.ts index 17363854..72c6faff 100644 --- a/frontend/src/i18n/zh-cn/mq.ts +++ b/frontend/src/i18n/zh-cn/mq.ts @@ -83,6 +83,12 @@ export default { searchGroup: '输入组名称', selectGroupPlaceholder: '选择分组', Members: '成员', + groupMembers: '消费者组成员', + clientHost: '客户端地址', + clientID: '客户端 ID', + instanceID: '实例 ID', + memberID: '成员 ID', + assignedTopics: '分配的 Topic 分区', partitionsFeatureComingSoon: '分区详情功能即将上线', }, }, diff --git a/frontend/src/views/ops/db/component/table/DbTableData.vue b/frontend/src/views/ops/db/component/table/DbTableData.vue index a5486922..31736330 100644 --- a/frontend/src/views/ops/db/component/table/DbTableData.vue +++ b/frontend/src/views/ops/db/component/table/DbTableData.vue @@ -368,6 +368,9 @@ let nowUpdateCell: Ref = ref(null) as any; // 选中的数据, key->rowIndex value->primaryKeyValue const selectionRowsMap = ref(new Map()); +// 最后一次点击的行索引,用于 shift 批量选择 +let lastSelectedRowIndex: number | null = null; + // 更新单元格 key-> rowIndex value -> 更新行 const cellUpdateMap = ref(new Map()); @@ -525,6 +528,7 @@ const setTableData = (datas: any) => { tableRef.value?.scrollTo({ scrollLeft: 0, scrollTop: 0 }); selectionRowsMap.value.clear(); cellUpdateMap.value.clear(); + lastSelectedRowIndex = null; // formatDataValues(datas); state.datas = datas; setTableColumns(props.columns); @@ -650,7 +654,7 @@ const isSelection = (rowIndex: number): boolean => { */ const selectionRow = (rowIndex: number, rowData: any, isMultiple = false) => { if (isMultiple) { - // 如果重复点击,则取消改选中数据 + // 如果重复点击,则取消该选中数据 if (selectionRowsMap.value.get(rowIndex)) { selectionRowsMap.value.delete(rowIndex); return; @@ -659,6 +663,21 @@ const selectionRow = (rowIndex: number, rowData: any, isMultiple = false) => { selectionRowsMap.value.clear(); } selectionRowsMap.value.set(rowIndex, rowData); + lastSelectedRowIndex = rowIndex; +}; + +/** + * Shift 批量选择:选中起始行到当前行之间的所有行 + */ +const selectionRowRange = (startIndex: number, endIndex: number) => { + const from = Math.min(startIndex, endIndex); + const to = Math.max(startIndex, endIndex); + for (let i = from; i <= to; i++) { + const rowData = state.datas[i]; + if (rowData) { + selectionRowsMap.value.set(i, rowData); + } + } }; /** @@ -669,11 +688,17 @@ const rowEventHandlers = { const event = e.event; const rowIndex = e.rowIndex; const rowData = e.rowData; - // 按住ctrl点击,则新建标签页打开, metaKey对应mac command键 + // 按住ctrl/meta点击,则多选切换 if (event.ctrlKey || event.metaKey) { selectionRow(rowIndex, rowData, true); return; } + // 按住shift点击,则批量选择起始行到当前行 + if (event.shiftKey && lastSelectedRowIndex !== null) { + selectionRowsMap.value.clear(); + selectionRowRange(lastSelectedRowIndex, rowIndex); + return; + } selectionRow(rowIndex, rowData); }, }; diff --git a/frontend/src/views/ops/es/api.ts b/frontend/src/views/ops/es/api.ts index 42f59062..866d1fd8 100644 --- a/frontend/src/views/ops/es/api.ts +++ b/frontend/src/views/ops/es/api.ts @@ -7,6 +7,8 @@ export const esApi = { deleteInstance: Api.newDelete('/es/instance/{id}'), saveInstance: Api.newPost('/es/instance'), testConn: Api.newPost('/es/instance/test-conn'), + exportData: Api.newPost('/es/instance/export/{instanceId}'), + exportProgress: Api.newGet('/es/instance/export/progress/{exportId}'), // proxyGet: Api.newGet('/es/instance/proxy/{id}/{path}'), // proxyPost: Api.newPost('/es/instance/proxy/{id}/{path}'), diff --git a/frontend/src/views/ops/es/component/EsIndexData.vue b/frontend/src/views/ops/es/component/EsIndexData.vue index e544dae3..147c8751 100644 --- a/frontend/src/views/ops/es/component/EsIndexData.vue +++ b/frontend/src/views/ops/es/component/EsIndexData.vue @@ -32,108 +32,73 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{ state.currentFrom + 1 }} - {{ Math.min(state.currentFrom + state.search.size, state.total) }} - - - + + + + + + + + + + {{ state.currentFrom + 1 }} - {{ Math.min(state.currentFrom + state.search.size, state.total) }} + + / - - - {{ state.searchRes.hits?.total?.value || 0 }} - - - - + + {{ state.searchRes.hits?.total?.value || 0 }} + - - - - + + + @@ -151,6 +116,8 @@ fixed :header-height="22" class="es-table" + :row-class="({ rowIndex }) => state.datas[rowIndex]?._selected ? 'es-row-selected' : ''" + :row-event-handlers="rowEventHandlers" > diff --git a/frontend/src/views/ops/mq/kafka/component/TopicManage.vue b/frontend/src/views/ops/mq/kafka/component/TopicManage.vue index 447a557c..0abe2c93 100644 --- a/frontend/src/views/ops/mq/kafka/component/TopicManage.vue +++ b/frontend/src/views/ops/mq/kafka/component/TopicManage.vue @@ -38,10 +38,10 @@ {{ row.isInternal ? 'Y' : 'N' }} - +