diff --git a/app/run.py b/app/run.py index 9f2cf7e..19b0b16 100644 --- a/app/run.py +++ b/app/run.py @@ -3626,6 +3626,18 @@ def get_history_records(): # 获取筛选参数 task_name_filter = request.args.get("task_name", "") keyword_filter = request.args.get("keyword", "") + task_names_raw = request.args.get("task_names", "") + task_name_list = [] + if task_names_raw: + try: + decoded_names = json.loads(task_names_raw) + if isinstance(decoded_names, list): + task_name_list = [ + str(name).strip() for name in decoded_names + if isinstance(name, (str, bytes)) and str(name).strip() + ] + except Exception: + task_name_list = [] # 是否只请求所有任务名称 get_all_task_names = request.args.get("get_all_task_names", "").lower() in ["true", "1", "yes"] @@ -3648,6 +3660,7 @@ def get_history_records(): order=order, task_name_filter=task_name_filter, keyword_filter=keyword_filter, + task_name_list=task_name_list, exclude_task_names=["rename", "undo_rename"] ) # 添加所有任务名称到结果中 @@ -3669,6 +3682,7 @@ def get_history_records(): order=order, task_name_filter=task_name_filter, keyword_filter=keyword_filter, + task_name_list=task_name_list, exclude_task_names=["rename", "undo_rename"] ) diff --git a/app/sdk/db.py b/app/sdk/db.py index 77ecc53..3f70771 100644 --- a/app/sdk/db.py +++ b/app/sdk/db.py @@ -167,7 +167,8 @@ class RecordDB: @retry_on_locked(max_retries=3, base_delay=0.1) def get_records(self, page=1, page_size=20, sort_by="transfer_time", order="desc", - task_name_filter="", keyword_filter="", exclude_task_names=None): + task_name_filter="", keyword_filter="", exclude_task_names=None, + task_name_list=None): """获取转存记录列表,支持分页、排序和筛选 Args: @@ -178,6 +179,7 @@ class RecordDB: task_name_filter: 任务名称筛选条件(精确匹配) keyword_filter: 关键字筛选条件(模糊匹配任务名、转存为名称) exclude_task_names: 需要排除的任务名称列表 + task_name_list: 任务名称集合(包含多个任务名时使用IN筛选) """ cursor = self.conn.cursor() offset = (page - 1) * page_size @@ -208,6 +210,11 @@ class RecordDB: where_clauses.append("task_name NOT IN ({})".format(",".join(["?" for _ in exclude_task_names]))) params.extend(exclude_task_names) + if task_name_list: + placeholders = ",".join(["?" for _ in task_name_list]) + where_clauses.append(f"task_name IN ({placeholders})") + params.extend(task_name_list) + where_clause = " AND ".join(where_clauses) where_sql = f"WHERE {where_clause}" if where_clause else "" diff --git a/app/templates/index.html b/app/templates/index.html index 3102d7b..d2f6d9f 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -967,7 +967,7 @@
-
+
@@ -1425,8 +1425,8 @@
-
-
+
+
名称筛选 @@ -1437,23 +1437,47 @@
-
+
任务筛选
- -
+
+
+
+ 状态筛选 +
+
+ +
+
+ +
+
+
@@ -3120,6 +3144,13 @@ }, historyNameFilter: "", historyTaskSelected: "", + historyStatusFilter: (() => { + try { + return localStorage.getItem('history_status_filter') || ''; + } catch (e) { + return ''; + } + })(), gotoPage: 1, totalPages: 1, displayedPages: [], @@ -3127,6 +3158,9 @@ toastMessage: "", selectedRecords: [], lastSelectedRecordIndex: -1, // 记录最后选择的记录索引,用于Shift选择 + _lastTaskFilter: "", + _lastNameFilter: "", + _lastStatusFilter: "", fileManager: { hasLoaded: false, // 标记是否已完成首次加载 // 当前文件夹ID - 根据localStorage和账号索引决定初始目录 @@ -3566,7 +3600,6 @@ filteredHistoryRecords() { - // 直接返回服务器端已筛选的数据 if (!this.history.records || this.history.records.length === 0) { return []; } @@ -3735,6 +3768,14 @@ this.loadHistoryRecords(); } }, + historyStatusFilter: { + handler(newVal) { + try { + localStorage.setItem('history_status_filter', newVal || ''); + } catch (e) {} + this.loadHistoryRecords(); + } + }, activeTab(newValue, oldValue) { // 如果切换到任务列表页面,则刷新任务最新信息和元数据 if (newValue === 'tasklist') { @@ -9221,10 +9262,16 @@ params.keyword = this.historyNameFilter; } + // 追加状态筛选 + if (!this.prepareStatusFilterParams(params, true)) { + return; + } + // 判断筛选条件是否变化,只有变化时才重置页码 const isFilterChanged = (this._lastTaskFilter !== this.historyTaskSelected) || - (this._lastNameFilter !== this.historyNameFilter); + (this._lastNameFilter !== this.historyNameFilter) || + (this._lastStatusFilter !== this.historyStatusFilter); if (isFilterChanged) { // 筛选条件变化时重置为第一页 @@ -9235,6 +9282,7 @@ // 记录当前筛选条件 this._lastTaskFilter = this.historyTaskSelected; this._lastNameFilter = this.historyNameFilter; + this._lastStatusFilter = this.historyStatusFilter; // 更新当前参数 this.historyParams = { @@ -9263,6 +9311,74 @@ this.history.hasLoaded = true; }); }, + prepareStatusFilterParams(params, handleEmptyResult = false) { + if (!this.historyStatusFilter) { + return true; + } + const taskNames = this.getStatusFilteredTaskNames(this.historyStatusFilter); + if (!taskNames || taskNames.length === 0) { + if (handleEmptyResult) { + this.handleEmptyHistoryResult(params.page_size); + } + return false; + } + params.task_names = JSON.stringify(taskNames); + return true; + }, + getStatusFilteredTaskNames(filterValue) { + if (!filterValue) { + return []; + } + if (filterValue === 'ended_task') { + const allTaskNames = (this.allTaskNames && this.allTaskNames.length > 0) + ? this.allTaskNames + : this.extractTaskNamesFromHistory(); + if (!this.allTaskNames || this.allTaskNames.length === 0) { + this.loadAllTaskNames(); + } + const currentNames = new Set(); + (this.formData.tasklist || []).forEach(task => { + if (task && task.taskname) { + currentNames.add(task.taskname); + } + }); + return allTaskNames.filter(name => name && !currentNames.has(name)); + } + const matchedNames = new Set(); + (this.formData.tasklist || []).forEach(task => { + if (!task || !task.taskname) { + return; + } + if (this.filterTaskByStatus(task, filterValue)) { + matchedNames.add(task.taskname); + } + }); + return Array.from(matchedNames); + }, + extractTaskNamesFromHistory() { + const names = new Set(); + (this.history.records || []).forEach(record => { + if (record && record.task_name) { + names.add(record.task_name); + } + }); + return Array.from(names); + }, + handleEmptyHistoryResult(pageSize) { + const resolvedPageSize = pageSize || parseInt(this.historyParams.page_size || 15); + this.history.records = []; + this.history.pagination = { + total_records: 0, + total_pages: 1, + current_page: 1, + page_size: resolvedPageSize + }; + this.history.hasLoaded = true; + this.totalPages = 1; + this.historyParams.page = 1; + this.gotoPage = 1; + this.selectedRecords = []; + }, sortHistory(field) { // 更新排序参数 @@ -9291,6 +9407,10 @@ params.keyword = this.historyNameFilter; } + if (!this.prepareStatusFilterParams(params, true)) { + return; + } + // 重新加载数据,使用当前页和当前设置的排序方式 axios.get('/history_records', { params }) .then(response => { @@ -9333,6 +9453,10 @@ params.keyword = this.historyNameFilter; } + if (!this.prepareStatusFilterParams(params, true)) { + return; + } + axios.get('/history_records', { params }) .then(response => { if (response.data.success) { @@ -9372,6 +9496,10 @@ params.keyword = this.historyNameFilter; } + if (!this.prepareStatusFilterParams(params, true)) { + return; + } + // 重新加载数据 axios.get('/history_records', { params }) .then(response => { @@ -9399,8 +9527,8 @@ }, getVisiblePageNumbers() { - const current = parseInt(this.historyParams.page) || 1; const total = parseInt(this.totalPages) || 1; + const current = parseInt(this.historyParams.page) || 1; // 根据屏幕宽度动态调整显示的页码数:移动端显示较少页码,桌面端显示较多页码 const isMobile = window.innerWidth <= 768; const delta = isMobile ? 1 : 2; // 移动端左右各显示1个页码,桌面端左右各显示2个页码