mirror of
https://github.com/Cp0204/quark-auto-save.git
synced 2026-01-16 09:20:43 +08:00
为转存记录添加状态筛选功能
This commit is contained in:
parent
85da3ec023
commit
0c81dd48b7
14
app/run.py
14
app/run.py
@ -3626,6 +3626,18 @@ def get_history_records():
|
|||||||
# 获取筛选参数
|
# 获取筛选参数
|
||||||
task_name_filter = request.args.get("task_name", "")
|
task_name_filter = request.args.get("task_name", "")
|
||||||
keyword_filter = request.args.get("keyword", "")
|
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"]
|
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,
|
order=order,
|
||||||
task_name_filter=task_name_filter,
|
task_name_filter=task_name_filter,
|
||||||
keyword_filter=keyword_filter,
|
keyword_filter=keyword_filter,
|
||||||
|
task_name_list=task_name_list,
|
||||||
exclude_task_names=["rename", "undo_rename"]
|
exclude_task_names=["rename", "undo_rename"]
|
||||||
)
|
)
|
||||||
# 添加所有任务名称到结果中
|
# 添加所有任务名称到结果中
|
||||||
@ -3669,6 +3682,7 @@ def get_history_records():
|
|||||||
order=order,
|
order=order,
|
||||||
task_name_filter=task_name_filter,
|
task_name_filter=task_name_filter,
|
||||||
keyword_filter=keyword_filter,
|
keyword_filter=keyword_filter,
|
||||||
|
task_name_list=task_name_list,
|
||||||
exclude_task_names=["rename", "undo_rename"]
|
exclude_task_names=["rename", "undo_rename"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -167,7 +167,8 @@ class RecordDB:
|
|||||||
|
|
||||||
@retry_on_locked(max_retries=3, base_delay=0.1)
|
@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",
|
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:
|
Args:
|
||||||
@ -178,6 +179,7 @@ class RecordDB:
|
|||||||
task_name_filter: 任务名称筛选条件(精确匹配)
|
task_name_filter: 任务名称筛选条件(精确匹配)
|
||||||
keyword_filter: 关键字筛选条件(模糊匹配任务名、转存为名称)
|
keyword_filter: 关键字筛选条件(模糊匹配任务名、转存为名称)
|
||||||
exclude_task_names: 需要排除的任务名称列表
|
exclude_task_names: 需要排除的任务名称列表
|
||||||
|
task_name_list: 任务名称集合(包含多个任务名时使用IN筛选)
|
||||||
"""
|
"""
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
offset = (page - 1) * page_size
|
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])))
|
where_clauses.append("task_name NOT IN ({})".format(",".join(["?" for _ in exclude_task_names])))
|
||||||
params.extend(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_clause = " AND ".join(where_clauses)
|
||||||
where_sql = f"WHERE {where_clause}" if where_clause else ""
|
where_sql = f"WHERE {where_clause}" if where_clause else ""
|
||||||
|
|
||||||
|
|||||||
@ -967,7 +967,7 @@
|
|||||||
|
|
||||||
<div v-if="activeTab === 'tasklist'">
|
<div v-if="activeTab === 'tasklist'">
|
||||||
<div style="height: 20px;"></div>
|
<div style="height: 20px;"></div>
|
||||||
<div class="row tasklist-filter-row" style="margin-bottom: 8px;">
|
<div class="row tasklist-filter-row" style="margin-bottom: 20px;">
|
||||||
<div class="col-xl-4 col-lg-4 col-md-6 mb-2 mb-lg-0">
|
<div class="col-xl-4 col-lg-4 col-md-6 mb-2 mb-lg-0">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
@ -1425,8 +1425,8 @@
|
|||||||
|
|
||||||
<div v-if="activeTab === 'history'">
|
<div v-if="activeTab === 'history'">
|
||||||
<div style="height: 20px;"></div>
|
<div style="height: 20px;"></div>
|
||||||
<div class="row" style="margin-bottom: 20px;">
|
<div class="row tasklist-filter-row" style="margin-bottom: 20px;">
|
||||||
<div class="col-lg-6 col-md-6 mb-2 mb-md-0">
|
<div class="col-xl-4 col-lg-4 col-md-6 mb-2 mb-lg-0">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">名称筛选</span>
|
<span class="input-group-text">名称筛选</span>
|
||||||
@ -1437,23 +1437,47 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 col-md-6">
|
<div class="col-xl-4 col-lg-4 col-md-6 mb-2 mb-lg-0">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">任务筛选</span>
|
<span class="input-group-text">任务筛选</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="position-relative" style="flex: 1;">
|
<div class="position-relative" style="flex: 1;">
|
||||||
<select class="form-control task-filter-select" v-model="historyTaskSelected" style="padding-left: 8px !important; text-indent: 0 !important; display: flex !important; align-items: center !important; line-height: 1.5 !important; padding-right: 24px !important;">
|
<select class="form-control task-filter-select" v-model="historyTaskSelected" style="padding-left: 8px !important; text-indent: 0 !important; display: flex !important; align-items: center !important; line-height: 1.5 !important; padding-right: 8px !important;">
|
||||||
<option value="">全部</option>
|
<option value="">全部</option>
|
||||||
<option v-for="task in historyTasks" :value="task" v-html="task"></option>
|
<option v-for="task in historyTasks" :value="task" v-html="task"></option>
|
||||||
</select>
|
</select>
|
||||||
<!-- <i class="bi bi-chevron-down select-arrow" style="position: absolute; pointer-events: none; color: var(--dark-text-color);"></i> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button type="button" class="btn btn-outline-secondary filter-btn-square" @click="clearData('historyTaskSelected')"><i class="bi bi-x-lg"></i></button>
|
<button type="button" class="btn btn-outline-secondary filter-btn-square" @click="clearData('historyTaskSelected')"><i class="bi bi-x-lg"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xl-4 col-lg-4 col-md-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">状态筛选</span>
|
||||||
|
</div>
|
||||||
|
<div class="position-relative" style="flex: 1;">
|
||||||
|
<select class="form-control task-filter-select"
|
||||||
|
v-model="historyStatusFilter"
|
||||||
|
style="padding-left: 8px !important; text-indent: 0 !important; display: flex !important; align-items: center !important; line-height: 1.5 !important; padding-right: 8px !important;">
|
||||||
|
<option value="">全部</option>
|
||||||
|
<option value="incomplete">未完成</option>
|
||||||
|
<option value="ongoing">进行中</option>
|
||||||
|
<option value="completed">已完成</option>
|
||||||
|
<option value="airing">播出中</option>
|
||||||
|
<option value="finale">本季终</option>
|
||||||
|
<option value="ended">已完结</option>
|
||||||
|
<option value="unmatched">未匹配</option>
|
||||||
|
<option value="ended_task">已结束</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="btn btn-outline-secondary filter-btn-square" @click="clearData('historyStatusFilter')"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@ -3120,6 +3144,13 @@
|
|||||||
},
|
},
|
||||||
historyNameFilter: "",
|
historyNameFilter: "",
|
||||||
historyTaskSelected: "",
|
historyTaskSelected: "",
|
||||||
|
historyStatusFilter: (() => {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem('history_status_filter') || '';
|
||||||
|
} catch (e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
})(),
|
||||||
gotoPage: 1,
|
gotoPage: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
displayedPages: [],
|
displayedPages: [],
|
||||||
@ -3127,6 +3158,9 @@
|
|||||||
toastMessage: "",
|
toastMessage: "",
|
||||||
selectedRecords: [],
|
selectedRecords: [],
|
||||||
lastSelectedRecordIndex: -1, // 记录最后选择的记录索引,用于Shift选择
|
lastSelectedRecordIndex: -1, // 记录最后选择的记录索引,用于Shift选择
|
||||||
|
_lastTaskFilter: "",
|
||||||
|
_lastNameFilter: "",
|
||||||
|
_lastStatusFilter: "",
|
||||||
fileManager: {
|
fileManager: {
|
||||||
hasLoaded: false, // 标记是否已完成首次加载
|
hasLoaded: false, // 标记是否已完成首次加载
|
||||||
// 当前文件夹ID - 根据localStorage和账号索引决定初始目录
|
// 当前文件夹ID - 根据localStorage和账号索引决定初始目录
|
||||||
@ -3566,7 +3600,6 @@
|
|||||||
|
|
||||||
|
|
||||||
filteredHistoryRecords() {
|
filteredHistoryRecords() {
|
||||||
// 直接返回服务器端已筛选的数据
|
|
||||||
if (!this.history.records || this.history.records.length === 0) {
|
if (!this.history.records || this.history.records.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -3735,6 +3768,14 @@
|
|||||||
this.loadHistoryRecords();
|
this.loadHistoryRecords();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
historyStatusFilter: {
|
||||||
|
handler(newVal) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem('history_status_filter', newVal || '');
|
||||||
|
} catch (e) {}
|
||||||
|
this.loadHistoryRecords();
|
||||||
|
}
|
||||||
|
},
|
||||||
activeTab(newValue, oldValue) {
|
activeTab(newValue, oldValue) {
|
||||||
// 如果切换到任务列表页面,则刷新任务最新信息和元数据
|
// 如果切换到任务列表页面,则刷新任务最新信息和元数据
|
||||||
if (newValue === 'tasklist') {
|
if (newValue === 'tasklist') {
|
||||||
@ -9221,10 +9262,16 @@
|
|||||||
params.keyword = this.historyNameFilter;
|
params.keyword = this.historyNameFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 追加状态筛选
|
||||||
|
if (!this.prepareStatusFilterParams(params, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 判断筛选条件是否变化,只有变化时才重置页码
|
// 判断筛选条件是否变化,只有变化时才重置页码
|
||||||
const isFilterChanged =
|
const isFilterChanged =
|
||||||
(this._lastTaskFilter !== this.historyTaskSelected) ||
|
(this._lastTaskFilter !== this.historyTaskSelected) ||
|
||||||
(this._lastNameFilter !== this.historyNameFilter);
|
(this._lastNameFilter !== this.historyNameFilter) ||
|
||||||
|
(this._lastStatusFilter !== this.historyStatusFilter);
|
||||||
|
|
||||||
if (isFilterChanged) {
|
if (isFilterChanged) {
|
||||||
// 筛选条件变化时重置为第一页
|
// 筛选条件变化时重置为第一页
|
||||||
@ -9235,6 +9282,7 @@
|
|||||||
// 记录当前筛选条件
|
// 记录当前筛选条件
|
||||||
this._lastTaskFilter = this.historyTaskSelected;
|
this._lastTaskFilter = this.historyTaskSelected;
|
||||||
this._lastNameFilter = this.historyNameFilter;
|
this._lastNameFilter = this.historyNameFilter;
|
||||||
|
this._lastStatusFilter = this.historyStatusFilter;
|
||||||
|
|
||||||
// 更新当前参数
|
// 更新当前参数
|
||||||
this.historyParams = {
|
this.historyParams = {
|
||||||
@ -9263,6 +9311,74 @@
|
|||||||
this.history.hasLoaded = true;
|
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) {
|
sortHistory(field) {
|
||||||
// 更新排序参数
|
// 更新排序参数
|
||||||
@ -9291,6 +9407,10 @@
|
|||||||
params.keyword = this.historyNameFilter;
|
params.keyword = this.historyNameFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.prepareStatusFilterParams(params, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 重新加载数据,使用当前页和当前设置的排序方式
|
// 重新加载数据,使用当前页和当前设置的排序方式
|
||||||
axios.get('/history_records', { params })
|
axios.get('/history_records', { params })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
@ -9333,6 +9453,10 @@
|
|||||||
params.keyword = this.historyNameFilter;
|
params.keyword = this.historyNameFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.prepareStatusFilterParams(params, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
axios.get('/history_records', { params })
|
axios.get('/history_records', { params })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
@ -9372,6 +9496,10 @@
|
|||||||
params.keyword = this.historyNameFilter;
|
params.keyword = this.historyNameFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.prepareStatusFilterParams(params, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 重新加载数据
|
// 重新加载数据
|
||||||
axios.get('/history_records', { params })
|
axios.get('/history_records', { params })
|
||||||
.then(response => {
|
.then(response => {
|
||||||
@ -9399,8 +9527,8 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
getVisiblePageNumbers() {
|
getVisiblePageNumbers() {
|
||||||
const current = parseInt(this.historyParams.page) || 1;
|
|
||||||
const total = parseInt(this.totalPages) || 1;
|
const total = parseInt(this.totalPages) || 1;
|
||||||
|
const current = parseInt(this.historyParams.page) || 1;
|
||||||
// 根据屏幕宽度动态调整显示的页码数:移动端显示较少页码,桌面端显示较多页码
|
// 根据屏幕宽度动态调整显示的页码数:移动端显示较少页码,桌面端显示较多页码
|
||||||
const isMobile = window.innerWidth <= 768;
|
const isMobile = window.innerWidth <= 768;
|
||||||
const delta = isMobile ? 1 : 2; // 移动端左右各显示1个页码,桌面端左右各显示2个页码
|
const delta = isMobile ? 1 : 2; // 移动端左右各显示1个页码,桌面端左右各显示2个页码
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user