jettask 0.2.14__py3-none-any.whl → 0.2.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. jettask/__init__.py +14 -35
  2. jettask/{webui/__main__.py → __main__.py} +4 -4
  3. jettask/api/__init__.py +103 -0
  4. jettask/api/v1/__init__.py +29 -0
  5. jettask/api/v1/alerts.py +226 -0
  6. jettask/api/v1/analytics.py +323 -0
  7. jettask/api/v1/namespaces.py +134 -0
  8. jettask/api/v1/overview.py +136 -0
  9. jettask/api/v1/queues.py +530 -0
  10. jettask/api/v1/scheduled.py +420 -0
  11. jettask/api/v1/settings.py +44 -0
  12. jettask/{webui/api.py → api.py} +4 -46
  13. jettask/{webui/backend → backend}/main.py +21 -109
  14. jettask/{webui/backend → backend}/main_unified.py +1 -1
  15. jettask/{webui/backend → backend}/namespace_api_old.py +3 -30
  16. jettask/{webui/backend → backend}/namespace_data_access.py +2 -1
  17. jettask/{webui/backend → backend}/unified_api_router.py +14 -74
  18. jettask/{core/cli.py → cli.py} +106 -26
  19. jettask/config/nacos_config.py +386 -0
  20. jettask/core/app.py +8 -100
  21. jettask/core/db_manager.py +515 -0
  22. jettask/core/event_pool.py +5 -2
  23. jettask/core/unified_manager_base.py +47 -14
  24. jettask/{webui/db_init.py → db_init.py} +1 -1
  25. jettask/executors/asyncio.py +2 -2
  26. jettask/{webui/integrated_gradio_app.py → integrated_gradio_app.py} +1 -1
  27. jettask/{webui/multi_namespace_consumer.py → multi_namespace_consumer.py} +5 -2
  28. jettask/{webui/pg_consumer.py → pg_consumer.py} +137 -69
  29. jettask/{webui/run.py → run.py} +1 -1
  30. jettask/{webui/run_webui.py → run_webui.py} +4 -4
  31. jettask/scheduler/multi_namespace_scheduler.py +2 -2
  32. jettask/scheduler/unified_manager.py +5 -5
  33. jettask/scheduler/unified_scheduler_manager.py +1 -1
  34. jettask/schemas/__init__.py +166 -0
  35. jettask/schemas/alert.py +99 -0
  36. jettask/schemas/backlog.py +122 -0
  37. jettask/schemas/common.py +139 -0
  38. jettask/schemas/monitoring.py +181 -0
  39. jettask/schemas/namespace.py +168 -0
  40. jettask/schemas/queue.py +83 -0
  41. jettask/schemas/scheduled_task.py +128 -0
  42. jettask/schemas/task.py +70 -0
  43. jettask/services/__init__.py +24 -0
  44. jettask/services/alert_service.py +454 -0
  45. jettask/services/analytics_service.py +46 -0
  46. jettask/services/overview_service.py +978 -0
  47. jettask/services/queue_service.py +711 -0
  48. jettask/services/redis_monitor_service.py +151 -0
  49. jettask/services/scheduled_task_service.py +207 -0
  50. jettask/services/settings_service.py +758 -0
  51. jettask/services/task_service.py +157 -0
  52. jettask/{webui/task_center.py → task_center.py} +30 -8
  53. jettask/{webui/task_center_client.py → task_center_client.py} +1 -1
  54. jettask/{webui/config.py → webui_config.py} +6 -1
  55. jettask/webui_exceptions.py +67 -0
  56. jettask/webui_sql/verify_database.sql +72 -0
  57. {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/METADATA +3 -1
  58. jettask-0.2.16.dist-info/RECORD +150 -0
  59. {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/entry_points.txt +1 -1
  60. jettask/webui/backend/data_api.py +0 -3294
  61. jettask/webui/backend/namespace_api.py +0 -295
  62. jettask/webui/backend/queue_backlog_api.py +0 -727
  63. jettask/webui/backend/redis_monitor_api.py +0 -476
  64. jettask/webui/frontend/index.html +0 -13
  65. jettask/webui/frontend/package.json +0 -30
  66. jettask/webui/frontend/src/App.css +0 -109
  67. jettask/webui/frontend/src/App.jsx +0 -66
  68. jettask/webui/frontend/src/components/NamespaceSelector.jsx +0 -166
  69. jettask/webui/frontend/src/components/QueueBacklogChart.jsx +0 -298
  70. jettask/webui/frontend/src/components/QueueBacklogTrend.jsx +0 -638
  71. jettask/webui/frontend/src/components/QueueDetailsTable.css +0 -65
  72. jettask/webui/frontend/src/components/QueueDetailsTable.jsx +0 -487
  73. jettask/webui/frontend/src/components/QueueDetailsTableV2.jsx +0 -465
  74. jettask/webui/frontend/src/components/ScheduledTaskFilter.jsx +0 -423
  75. jettask/webui/frontend/src/components/TaskFilter.jsx +0 -425
  76. jettask/webui/frontend/src/components/TimeRangeSelector.css +0 -21
  77. jettask/webui/frontend/src/components/TimeRangeSelector.jsx +0 -160
  78. jettask/webui/frontend/src/components/charts/QueueChart.jsx +0 -111
  79. jettask/webui/frontend/src/components/charts/QueueTrendChart.jsx +0 -115
  80. jettask/webui/frontend/src/components/charts/WorkerChart.jsx +0 -40
  81. jettask/webui/frontend/src/components/common/StatsCard.jsx +0 -18
  82. jettask/webui/frontend/src/components/layout/AppLayout.css +0 -95
  83. jettask/webui/frontend/src/components/layout/AppLayout.jsx +0 -49
  84. jettask/webui/frontend/src/components/layout/Header.css +0 -106
  85. jettask/webui/frontend/src/components/layout/Header.jsx +0 -106
  86. jettask/webui/frontend/src/components/layout/SideMenu.css +0 -137
  87. jettask/webui/frontend/src/components/layout/SideMenu.jsx +0 -209
  88. jettask/webui/frontend/src/components/layout/TabsNav.css +0 -244
  89. jettask/webui/frontend/src/components/layout/TabsNav.jsx +0 -206
  90. jettask/webui/frontend/src/components/layout/UserInfo.css +0 -197
  91. jettask/webui/frontend/src/components/layout/UserInfo.jsx +0 -197
  92. jettask/webui/frontend/src/contexts/LoadingContext.jsx +0 -27
  93. jettask/webui/frontend/src/contexts/NamespaceContext.jsx +0 -72
  94. jettask/webui/frontend/src/contexts/TabsContext.backup.jsx +0 -245
  95. jettask/webui/frontend/src/index.css +0 -114
  96. jettask/webui/frontend/src/main.jsx +0 -22
  97. jettask/webui/frontend/src/pages/Alerts.jsx +0 -684
  98. jettask/webui/frontend/src/pages/Dashboard/index.css +0 -35
  99. jettask/webui/frontend/src/pages/Dashboard/index.jsx +0 -281
  100. jettask/webui/frontend/src/pages/Dashboard.jsx +0 -1330
  101. jettask/webui/frontend/src/pages/QueueDetail.jsx +0 -1117
  102. jettask/webui/frontend/src/pages/QueueMonitor.jsx +0 -527
  103. jettask/webui/frontend/src/pages/Queues.jsx +0 -12
  104. jettask/webui/frontend/src/pages/ScheduledTasks.jsx +0 -810
  105. jettask/webui/frontend/src/pages/Settings.jsx +0 -801
  106. jettask/webui/frontend/src/pages/Workers.jsx +0 -12
  107. jettask/webui/frontend/src/services/api.js +0 -159
  108. jettask/webui/frontend/src/services/queueTrend.js +0 -166
  109. jettask/webui/frontend/src/utils/suppressWarnings.js +0 -22
  110. jettask/webui/frontend/src/utils/userPreferences.js +0 -154
  111. jettask/webui/frontend/vite.config.js +0 -26
  112. jettask/webui/sql/init_database.sql +0 -640
  113. jettask-0.2.14.dist-info/RECORD +0 -172
  114. /jettask/{webui/backend → backend}/__init__.py +0 -0
  115. /jettask/{webui/backend → backend}/api/__init__.py +0 -0
  116. /jettask/{webui/backend → backend}/api/v1/__init__.py +0 -0
  117. /jettask/{webui/backend → backend}/api/v1/monitoring.py +0 -0
  118. /jettask/{webui/backend → backend}/api/v1/namespaces.py +0 -0
  119. /jettask/{webui/backend → backend}/api/v1/queues.py +0 -0
  120. /jettask/{webui/backend → backend}/api/v1/tasks.py +0 -0
  121. /jettask/{webui/backend → backend}/config.py +0 -0
  122. /jettask/{webui/backend → backend}/core/__init__.py +0 -0
  123. /jettask/{webui/backend → backend}/core/cache.py +0 -0
  124. /jettask/{webui/backend → backend}/core/database.py +0 -0
  125. /jettask/{webui/backend → backend}/core/exceptions.py +0 -0
  126. /jettask/{webui/backend → backend}/data_access.py +0 -0
  127. /jettask/{webui/backend → backend}/dependencies.py +0 -0
  128. /jettask/{webui/backend → backend}/init_meta_db.py +0 -0
  129. /jettask/{webui/backend → backend}/main_v2.py +0 -0
  130. /jettask/{webui/backend → backend}/models/__init__.py +0 -0
  131. /jettask/{webui/backend → backend}/models/requests.py +0 -0
  132. /jettask/{webui/backend → backend}/models/responses.py +0 -0
  133. /jettask/{webui/backend → backend}/queue_stats_v2.py +0 -0
  134. /jettask/{webui/backend → backend}/services/__init__.py +0 -0
  135. /jettask/{webui/backend → backend}/start.py +0 -0
  136. /jettask/{webui/cleanup_deprecated_tables.sql → cleanup_deprecated_tables.sql} +0 -0
  137. /jettask/{webui/gradio_app.py → gradio_app.py} +0 -0
  138. /jettask/{webui/__init__.py → main.py} +0 -0
  139. /jettask/{webui/models.py → models.py} +0 -0
  140. /jettask/{webui/run_monitor.py → run_monitor.py} +0 -0
  141. /jettask/{webui/schema.sql → schema.sql} +0 -0
  142. /jettask/{webui/unified_consumer_manager.py → unified_consumer_manager.py} +0 -0
  143. /jettask/{webui/models → webui_models}/__init__.py +0 -0
  144. /jettask/{webui/models → webui_models}/namespace.py +0 -0
  145. /jettask/{webui/sql → webui_sql}/batch_upsert_functions.sql +0 -0
  146. {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/WHEEL +0 -0
  147. {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/licenses/LICENSE +0 -0
  148. {jettask-0.2.14.dist-info → jettask-0.2.16.dist-info}/top_level.txt +0 -0
@@ -1,465 +0,0 @@
1
- import { useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react';
2
- import { Tag, message, Button, Space, Progress, Tooltip } from 'antd';
3
- import { ProTable } from '@ant-design/pro-components';
4
- import {
5
- TeamOutlined,
6
- ThunderboltOutlined,
7
- CheckCircleOutlined,
8
- CloseCircleOutlined,
9
- SyncOutlined,
10
- EyeOutlined,
11
- ExpandOutlined,
12
- CompressOutlined,
13
- UserOutlined,
14
- CopyOutlined
15
- } from '@ant-design/icons';
16
- import { useNavigate } from 'react-router-dom';
17
- import axios from 'axios';
18
- import dayjs from 'dayjs';
19
- import { useNamespace } from '../contexts/NamespaceContext';
20
- import './QueueDetailsTable.css';
21
-
22
- const QueueDetailsTableV2 = forwardRef(({
23
- autoRefresh = false,
24
- refreshInterval = 5000,
25
- selectedQueues = [],
26
- timeRange = '15m',
27
- customTimeRange = null
28
- }, ref) => {
29
- const navigate = useNavigate();
30
- const { currentNamespace } = useNamespace();
31
- const [loading, setLoading] = useState(false);
32
- const [data, setData] = useState([]);
33
- const [expandedRowKeys, setExpandedRowKeys] = useState([]);
34
- const actionRef = useRef();
35
-
36
- // 暴露刷新方法给父组件
37
- useImperativeHandle(ref, () => ({
38
- refresh: fetchQueueStats
39
- }));
40
-
41
- // 复制文本到剪贴板
42
- const handleCopy = async (text) => {
43
- try {
44
- await navigator.clipboard.writeText(text);
45
- message.success('已复制到剪贴板');
46
- } catch (err) {
47
- message.error('复制失败');
48
- }
49
- };
50
-
51
- // 获取队列统计信息(使用新的v2 API)
52
- const fetchQueueStats = async () => {
53
- if (!currentNamespace) {
54
- return;
55
- }
56
-
57
- setLoading(true);
58
- try {
59
- // 构建查询参数
60
- const params = new URLSearchParams();
61
-
62
- // 添加时间范围参数
63
- if (customTimeRange && customTimeRange.length === 2) {
64
- // 自定义时间范围
65
- // customTimeRange可能是dayjs对象或ISO字符串
66
- const startTime = dayjs.isDayjs(customTimeRange[0])
67
- ? customTimeRange[0].toISOString()
68
- : customTimeRange[0];
69
- const endTime = dayjs.isDayjs(customTimeRange[1])
70
- ? customTimeRange[1].toISOString()
71
- : customTimeRange[1];
72
- params.append('start_time', startTime);
73
- params.append('end_time', endTime);
74
- } else if (timeRange && timeRange !== 'custom') {
75
- // 预设时间范围
76
- params.append('time_range', timeRange);
77
- }
78
-
79
- const url = `/api/v2/namespaces/${currentNamespace}/queues/stats${params.toString() ? '?' + params.toString() : ''}`;
80
- console.log('Fetching queue stats with URL:', url);
81
-
82
- const response = await axios.get(url);
83
- if (response.data.success) {
84
- // 过滤选中的队列
85
- let queuesData = response.data.data;
86
- if (selectedQueues && selectedQueues.length > 0) {
87
- queuesData = queuesData.filter(q => selectedQueues.includes(q.queue_name));
88
- }
89
- setData(queuesData);
90
- } else {
91
- message.error('获取队列详情失败');
92
- }
93
- } catch (error) {
94
- console.error('Failed to fetch queue stats:', error);
95
- message.error('获取队列详情失败');
96
- } finally {
97
- setLoading(false);
98
- }
99
- };
100
-
101
- // 初始化加载数据
102
- useEffect(() => {
103
- if (selectedQueues && selectedQueues.length > 0) {
104
- fetchQueueStats();
105
- } else {
106
- setData([]);
107
- }
108
- }, [currentNamespace, selectedQueues, timeRange, customTimeRange]);
109
-
110
- // 自动刷新
111
- useEffect(() => {
112
- if (autoRefresh) {
113
- const timer = setInterval(() => {
114
- fetchQueueStats();
115
- }, refreshInterval);
116
- return () => clearInterval(timer);
117
- }
118
- }, [autoRefresh, refreshInterval]);
119
-
120
- // 消费者组表格列定义
121
- const consumerGroupColumns = [
122
- // {
123
- // title: '消费者组',
124
- // dataIndex: 'group_name',
125
- // key: 'group_name',
126
- // width: 220,
127
- // ellipsis: {
128
- // showTitle: false, // 不使用默认的 title,我们自定义
129
- // },
130
- // render: (_, record) => {
131
- // // 直接从 record 获取原始数据
132
- // const text = record.group_name || '';
133
- // // 提取最后一部分(冒号分隔的最后一段)
134
- // const lastPart = text.split(':').pop() || text;
135
- // return (
136
- // <div style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
137
- // <Tooltip title={text}>
138
- // <span
139
- // style={{
140
- // cursor: 'pointer',
141
- // overflow: 'hidden',
142
- // textOverflow: 'ellipsis',
143
- // whiteSpace: 'nowrap',
144
- // flex: 1,
145
- // minWidth: 0
146
- // }}
147
- // onClick={() => handleCopy(text)}
148
- // >
149
- // {lastPart}
150
- // </span>
151
- // </Tooltip>
152
- // <Tooltip title="点击复制完整名称">
153
- // <Button
154
- // type="text"
155
- // size="small"
156
- // icon={<CopyOutlined />}
157
- // onClick={() => handleCopy(text)}
158
- // style={{ padding: '0 4px', flexShrink: 0 }}
159
- // />
160
- // </Tooltip>
161
- // </div>
162
- // );
163
- // },
164
- // },
165
- {
166
- title: '任务名',
167
- dataIndex: 'task_name',
168
- key: 'task_name',
169
- width: 180,
170
- ellipsis: true,
171
- copyable: true,
172
- },
173
- {
174
- title: '优先级',
175
- dataIndex: 'priority',
176
- key: 'priority',
177
- width: 80,
178
- align: 'center',
179
- render: (priority) => {
180
- let color;
181
- if (priority === 0) {
182
- color = 'default';
183
- } else if (priority <= 3) {
184
- color = 'red';
185
- } else if (priority <= 6) {
186
- color = 'orange';
187
- } else {
188
- color = 'green';
189
- }
190
-
191
- return (
192
- <Tag color={color} style={{ fontSize: '12px', fontWeight: 'bold' }}>
193
- {priority}
194
- </Tag>
195
- );
196
- }
197
- },
198
- {
199
- title: '待处理',
200
- dataIndex: 'pending',
201
- key: 'pending',
202
- width: 100,
203
- align: 'center',
204
- render: (pending) => (
205
- <span>{pending ? pending : 0}</span>
206
- // <Badge count={pending} style={{ backgroundColor: pending > 0 ? '#fa8c16' : '#d9d9d9' }} overflowCount={9999} />
207
- )
208
- },
209
- {
210
- title: '可见/不可见',
211
- key: 'messages',
212
- width: 140,
213
- align: 'center',
214
- render: (_, record) => (
215
- <Space>
216
- <span style={{ color: '#1890ff' }}>{record.visible_messages}</span>
217
- <span>/</span>
218
- <span style={{ color: '#8c8c8c' }}>{record.invisible_messages}</span>
219
- </Space>
220
- )
221
- },
222
- {
223
- title: '成功/失败',
224
- key: 'stats',
225
- width: 120,
226
- align: 'center',
227
- render: (_, record) => (
228
- <Space>
229
- <span style={{ color: '#52c41a' }}>{record.success_count}</span>
230
- <span>/</span>
231
- <span style={{ color: '#ff4d4f' }}>{record.failed_count}</span>
232
- </Space>
233
- )
234
- },
235
- {
236
- title: '成功率',
237
- dataIndex: 'success_rate',
238
- key: 'success_rate',
239
- width: 120,
240
- align: 'center',
241
- render: (rate) => (
242
- <Progress
243
- percent={rate}
244
- size="small"
245
- strokeColor={rate >= 95 ? '#52c41a' : rate >= 80 ? '#faad14' : '#ff4d4f'}
246
- />
247
- )
248
- },
249
- {
250
- title: '处理速率',
251
- dataIndex: 'processing_rate',
252
- key: 'processing_rate',
253
- width: 100,
254
- align: 'center',
255
- render: (rate) => (
256
- <span>
257
- <ThunderboltOutlined style={{ color: '#faad14' }} /> {rate}/min
258
- </span>
259
- )
260
- },
261
- {
262
- title: '平均耗时',
263
- dataIndex: 'avg_execution_time',
264
- key: 'avg_execution_time',
265
- width: 100,
266
- align: 'center',
267
- render: (time) => (
268
- <span>{time ? `${time.toFixed(2)}s` : '-'}</span>
269
- )
270
- }
271
- ];
272
-
273
- // 主表格列定义
274
- const columns = [
275
- {
276
- title: '队列名',
277
- dataIndex: 'queue_name',
278
- key: 'queue_name',
279
- width: 200,
280
- fixed: 'left',
281
- ellipsis: true,
282
- copyable: true,
283
- render: (text) => (
284
- <span style={{ fontWeight: 'bold' }}>{text}</span>
285
- )
286
- },
287
- {
288
- title: '消费者组数',
289
- dataIndex: 'consumer_groups_count',
290
- key: 'consumer_groups_count',
291
- width: 120,
292
- align: 'center',
293
- render: (count, record) => (
294
- <Space>
295
- <TeamOutlined />
296
- <span>{count}</span>
297
- {count > 0 && (
298
- <Button
299
- type="link"
300
- size="small"
301
- onClick={() => {
302
- if (expandedRowKeys.includes(record.queue_name)) {
303
- setExpandedRowKeys(expandedRowKeys.filter(key => key !== record.queue_name));
304
- } else {
305
- setExpandedRowKeys([...expandedRowKeys, record.queue_name]);
306
- }
307
- }}
308
- >
309
- {expandedRowKeys.includes(record.queue_name) ? '收起' : '展开'}
310
- </Button>
311
- )}
312
- </Space>
313
- )
314
- },
315
- {
316
- title: '队列总长度',
317
- dataIndex: 'total_length',
318
- key: 'total_length',
319
- width: 120,
320
- align: 'center',
321
- render: (length) => (
322
- <span>{length ? length : 0}</span>
323
- // <Badge
324
- // count={length}
325
- // style={{
326
- // backgroundColor: length > 1000 ? '#ff4d4f' : length > 100 ? '#fa8c16' : '#52c41a'
327
- // }}
328
- // overflowCount={999999}
329
- // />
330
- )
331
- },
332
- {
333
- title: '在线Workers',
334
- dataIndex: 'active_workers',
335
- key: 'active_workers',
336
- width: 120,
337
- align: 'center',
338
- render: (workers) => (
339
- <Space>
340
- <UserOutlined style={{ color: workers > 0 ? '#52c41a' : '#d9d9d9' }} />
341
- <span style={{ color: workers > 0 ? '#52c41a' : '#d9d9d9' }}>{workers}</span>
342
- </Space>
343
- )
344
- },
345
- {
346
- title: '成功/失败',
347
- key: 'success_failed',
348
- width: 150,
349
- align: 'center',
350
- render: (_, record) => (
351
- <Space>
352
- <span style={{ color: '#52c41a' }}>{record.total_success}</span>
353
- <span>/</span>
354
- <span style={{ color: '#ff4d4f' }}>{record.total_failed}</span>
355
- </Space>
356
- )
357
- },
358
- {
359
- title: '总体成功率',
360
- dataIndex: 'overall_success_rate',
361
- key: 'overall_success_rate',
362
- width: 120,
363
- align: 'center',
364
- render: (rate) => (
365
- <Progress
366
- percent={rate}
367
- size="small"
368
- strokeColor={rate >= 95 ? '#52c41a' : rate >= 80 ? '#faad14' : '#ff4d4f'}
369
- />
370
- )
371
- },
372
- {
373
- title: '操作',
374
- key: 'action',
375
- width: 100,
376
- fixed: 'right',
377
- align: 'center',
378
- render: (_, record) => (
379
- <Button
380
- type="link"
381
- icon={<EyeOutlined />}
382
- onClick={() => {
383
- navigate(`/queue/${record.queue_name}`);
384
- }}
385
- >
386
- 查看
387
- </Button>
388
- )
389
- }
390
- ];
391
-
392
- // 展开行渲染
393
- const expandedRowRender = (record) => {
394
- return (
395
- <ProTable
396
- columns={consumerGroupColumns}
397
- dataSource={record.consumer_groups}
398
- rowKey="unique_key"
399
- pagination={false}
400
- search={false}
401
- options={false}
402
- size="small"
403
- toolBarRender={false}
404
- />
405
- );
406
- };
407
-
408
- return (
409
- <div className="queue-details-table-v2">
410
- <ProTable
411
- columns={columns}
412
- dataSource={data}
413
- rowKey="queue_name"
414
- loading={loading}
415
- pagination={false}
416
- search={false}
417
- dateFormatter="string"
418
- headerTitle="队列概览"
419
- actionRef={actionRef}
420
- expandable={{
421
- expandedRowRender,
422
- expandedRowKeys,
423
- onExpandedRowsChange: setExpandedRowKeys,
424
- }}
425
- options={{
426
- reload: () => fetchQueueStats(),
427
- density: true,
428
- fullScreen: true,
429
- setting: true,
430
- }}
431
- toolBarRender={() => [
432
- expandedRowKeys.length === data.filter(d => d.consumer_groups_count > 0).length ? (
433
- <Button
434
- key="collapse"
435
- icon={<CompressOutlined />}
436
- onClick={() => setExpandedRowKeys([])}
437
- >
438
- 收起全部
439
- </Button>
440
- ) : (
441
- <Button
442
- key="expand"
443
- icon={<ExpandOutlined />}
444
- onClick={() => {
445
- const keys = data.filter(d => d.consumer_groups_count > 0).map(d => d.queue_name);
446
- setExpandedRowKeys(keys);
447
- }}
448
- >
449
- 展开全部
450
- </Button>
451
- ),
452
- // <Button
453
- // key="refresh"
454
- // icon={<SyncOutlined spin={loading} />}
455
- // onClick={fetchQueueStats}
456
- // >
457
- // 刷新
458
- // </Button>
459
- ]}
460
- />
461
- </div>
462
- );
463
- });
464
-
465
- export default QueueDetailsTableV2;