Skip to content

Commit c1a784b

Browse files
committed
feat: 历史配置表格添加排序和分页功能
- 后端API添加分页和排序参数支持 - 前端表格支持按ID、命令行参数、最后使用时间、使用次数排序 - 添加分页组件,支持选择每页显示数量 - 历史配置卡片显示ID标识
1 parent 6c25a49 commit c1a784b

6 files changed

Lines changed: 359 additions & 70 deletions

File tree

src/backEnd/api/commonApi/scanPreset.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,35 @@ async def get_preset_configs(
142142

143143
@router.get("/history", summary="获取历史配置列表")
144144
async def get_history_configs(
145-
limit: int = Query(20, ge=1, le=100, description="返回数量限制"),
145+
page: int = Query(1, ge=1, description="页码"),
146+
page_size: int = Query(10, ge=1, le=100, description="每页数量"),
147+
sort_field: str = Query("last_used_at", description="排序字段"),
148+
sort_order: str = Query("desc", regex="^(asc|desc)$", description="排序方向"),
146149
current_user: dict = Depends(get_current_user)
147150
):
148-
"""获取历史配置列表"""
151+
"""
152+
获取历史配置列表(带分页和排序)
153+
154+
支持的排序字段:id, name, created_at, updated_at, last_used_at, use_count
155+
"""
149156
try:
150-
presets = scanPresetService.get_history_configs(limit)
157+
offset = (page - 1) * page_size
158+
presets, total = scanPresetService.get_history_configs(
159+
limit=page_size,
160+
offset=offset,
161+
sort_field=sort_field,
162+
sort_order=sort_order
163+
)
151164
return BaseResponseMsg(
152165
success=True,
153166
code=http_status.HTTP_200_OK,
154167
msg="获取成功",
155168
data={
156169
"presets": [p.model_dump() for p in presets],
157-
"total": len(presets)
170+
"total": total,
171+
"page": page,
172+
"page_size": page_size,
173+
"total_pages": (total + page_size - 1) // page_size if page_size > 0 else 0
158174
}
159175
)
160176
except Exception as e:

src/backEnd/model/ScanPresetDatabase.py

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,53 @@ def get_default_preset(self) -> Optional[ScanPreset]:
271271
presets = self.get_presets_by_type(PresetType.DEFAULT)
272272
return presets[0] if presets else None
273273

274-
def get_history_presets(self, limit: int = 20) -> List[ScanPreset]:
275-
"""获取历史配置"""
274+
def get_history_presets(
275+
self,
276+
limit: int = 20,
277+
offset: int = 0,
278+
sort_field: str = "last_used_at",
279+
sort_order: str = "desc"
280+
) -> tuple[List[ScanPreset], int]:
281+
"""
282+
获取历史配置(带分页和排序)
283+
284+
Args:
285+
limit: 每页数量
286+
offset: 偏移量
287+
sort_field: 排序字段 (id, name, created_at, updated_at, last_used_at, use_count)
288+
sort_order: 排序方向 (asc, desc)
289+
290+
Returns:
291+
tuple: (预设列表, 总数)
292+
"""
293+
# 验证排序字段,防止SQL注入
294+
valid_sort_fields = {
295+
"id": "id",
296+
"name": "name",
297+
"created_at": "created_at",
298+
"updated_at": "updated_at",
299+
"last_used_at": "last_used_at",
300+
"use_count": "use_count"
301+
}
302+
303+
order_field = valid_sort_fields.get(sort_field, "last_used_at")
304+
order_direction = "DESC" if sort_order.lower() == "desc" else "ASC"
305+
276306
try:
307+
# 先获取总数
308+
count_cursor = self.only_execute(
309+
"SELECT COUNT(*) FROM scan_presets WHERE preset_type = ? AND is_active = 1",
310+
(PresetType.HISTORY.value,)
311+
)
312+
total = count_cursor.fetchone()[0] if count_cursor else 0
313+
314+
# 获取分页数据
277315
cursor = self.only_execute(
278316
f"""SELECT {_PRESET_COLUMNS} FROM scan_presets
279317
WHERE preset_type = ? AND is_active = 1
280-
ORDER BY last_used_at DESC
281-
LIMIT ?""",
282-
(PresetType.HISTORY.value, limit)
318+
ORDER BY {order_field} {order_direction}
319+
LIMIT ? OFFSET ?""",
320+
(PresetType.HISTORY.value, limit, offset)
283321
)
284322

285323
presets = []
@@ -288,11 +326,11 @@ def get_history_presets(self, limit: int = 20) -> List[ScanPreset]:
288326
preset = self._row_to_preset(row)
289327
if preset:
290328
presets.append(preset)
291-
return presets
329+
return presets, total
292330

293331
except Exception as e:
294332
logger.error(f"Failed to get history presets: {getSafeExString(e)}")
295-
return []
333+
return [], 0
296334

297335
def update_preset(self, preset_id: int, data: ScanPresetUpdate) -> Optional[ScanPreset]:
298336
"""更新预设配置"""

src/backEnd/service/scanPresetService.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,26 @@ def get_preset_configs(self) -> List[ScanPreset]:
5252
"""获取常用配置列表"""
5353
return self.db.get_presets_by_type(PresetType.PRESET)
5454

55-
def get_history_configs(self, limit: int = 20) -> List[ScanPreset]:
56-
"""获取历史配置列表"""
57-
return self.db.get_history_presets(limit)
55+
def get_history_configs(
56+
self,
57+
limit: int = 20,
58+
offset: int = 0,
59+
sort_field: str = "last_used_at",
60+
sort_order: str = "desc"
61+
) -> tuple[List[ScanPreset], int]:
62+
"""
63+
获取历史配置列表(带分页和排序)
64+
65+
Args:
66+
limit: 每页数量
67+
offset: 偏移量
68+
sort_field: 排序字段
69+
sort_order: 排序方向
70+
71+
Returns:
72+
tuple: (预设列表, 总数)
73+
"""
74+
return self.db.get_history_presets(limit, offset, sort_field, sort_order)
5875

5976
def get_default_preset(self) -> Optional[ScanPreset]:
6077
"""获取默认配置"""

src/frontEnd/src/api/scanPreset.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,47 @@ export async function getPresetConfigs(): Promise<ScanPreset[]> {
7676
}
7777

7878
/**
79-
* 获取历史配置列表
79+
* 历史配置列表响应
8080
*/
81-
export async function getHistoryConfigs(limit = 20): Promise<ScanPreset[]> {
81+
export interface HistoryListResponse {
82+
presets: ScanPreset[]
83+
total: number
84+
page: number
85+
page_size: number
86+
total_pages: number
87+
}
88+
89+
/**
90+
* 获取历史配置列表(带分页和排序)
91+
*/
92+
export async function getHistoryConfigs(
93+
page: number = 1,
94+
pageSize: number = 10,
95+
sortField: string = 'last_used_at',
96+
sortOrder: string = 'desc'
97+
): Promise<HistoryListResponse> {
8298
const result = await request.get<{
8399
presets: ScanPreset[]
84100
total: number
101+
page: number
102+
page_size: number
103+
total_pages: number
85104
}>('/scan-preset/history', {
86-
params: { limit }
105+
params: {
106+
page,
107+
page_size: pageSize,
108+
sort_field: sortField,
109+
sort_order: sortOrder
110+
}
87111
})
88112

89-
return result.presets || []
113+
return {
114+
presets: result.presets || [],
115+
total: result.total || 0,
116+
page: result.page || 1,
117+
page_size: result.page_size || 10,
118+
total_pages: result.total_pages || 0
119+
}
90120
}
91121

92122
/**

src/frontEnd/src/views/AddTask/components/PresetModePanel.vue

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@
108108
@click="handleSelect(preset)"
109109
>
110110
<div class="preset-card-header">
111-
<span class="preset-name">{{ preset.name }}</span>
111+
<span class="preset-name">
112+
<span class="preset-id">#{{ preset.id }}</span>
113+
{{ preset.name }}
114+
</span>
112115
<Tag severity="warn" value="历史" />
113116
</div>
114117
<div class="preset-card-params">
@@ -302,6 +305,18 @@ function handleSelect(preset: ScanPreset) {
302305
font-size: 0.95rem;
303306
}
304307
308+
.preset-id {
309+
display: inline-block;
310+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
311+
font-size: 0.75rem;
312+
font-weight: 600;
313+
color: var(--p-primary-color);
314+
background: rgba(var(--p-primary-color-rgb, 99, 102, 241), 0.1);
315+
padding: 1px 6px;
316+
border-radius: 4px;
317+
margin-right: 0.5rem;
318+
}
319+
305320
.preset-card-desc {
306321
font-size: 0.8rem;
307322
color: var(--text-color-secondary);

0 commit comments

Comments
 (0)