mirror of
https://github.com/Cp0204/quark-auto-save.git
synced 2026-01-18 02:40:44 +08:00
为文件整理增加多账号支持和性能设置功能
This commit is contained in:
parent
7b019ab1e0
commit
7d4672cb8e
259
app/run.py
259
app/run.py
@ -28,6 +28,8 @@ import re
|
|||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
import treelib
|
import treelib
|
||||||
|
from functools import lru_cache
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
sys.path.insert(0, parent_dir)
|
sys.path.insert(0, parent_dir)
|
||||||
@ -96,6 +98,45 @@ PORT = int(os.environ.get("PORT", "5005"))
|
|||||||
config_data = {}
|
config_data = {}
|
||||||
task_plugins_config_default = {}
|
task_plugins_config_default = {}
|
||||||
|
|
||||||
|
# 文件列表缓存
|
||||||
|
file_list_cache = {}
|
||||||
|
cache_lock = Lock()
|
||||||
|
|
||||||
|
# 默认性能参数(如果配置中没有设置)
|
||||||
|
DEFAULT_PERFORMANCE_CONFIG = {
|
||||||
|
"api_page_size": 200,
|
||||||
|
"cache_expire_time": 30
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_performance_config():
|
||||||
|
"""获取性能配置参数"""
|
||||||
|
try:
|
||||||
|
if config_data and "file_performance" in config_data:
|
||||||
|
perf_config = config_data["file_performance"]
|
||||||
|
# 确保所有值都是整数类型
|
||||||
|
result = {}
|
||||||
|
for key, default_value in DEFAULT_PERFORMANCE_CONFIG.items():
|
||||||
|
try:
|
||||||
|
result[key] = int(perf_config.get(key, default_value))
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
result[key] = default_value
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
print(f"获取性能配置失败: {e}")
|
||||||
|
return DEFAULT_PERFORMANCE_CONFIG
|
||||||
|
|
||||||
|
def cleanup_expired_cache():
|
||||||
|
"""清理所有过期缓存"""
|
||||||
|
current_time = time.time()
|
||||||
|
perf_config = get_performance_config()
|
||||||
|
cache_expire_time = perf_config.get("cache_expire_time", 30)
|
||||||
|
|
||||||
|
with cache_lock:
|
||||||
|
expired_keys = [k for k, (_, t) in file_list_cache.items() if current_time - t > cache_expire_time]
|
||||||
|
for k in expired_keys:
|
||||||
|
del file_list_cache[k]
|
||||||
|
return len(expired_keys)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config["APP_VERSION"] = get_app_ver()
|
app.config["APP_VERSION"] = get_app_ver()
|
||||||
app.secret_key = "ca943f6db6dd34823d36ab08d8d6f65d"
|
app.secret_key = "ca943f6db6dd34823d36ab08d8d6f65d"
|
||||||
@ -683,7 +724,15 @@ def get_share_detail():
|
|||||||
def get_savepath_detail():
|
def get_savepath_detail():
|
||||||
if not is_login():
|
if not is_login():
|
||||||
return jsonify({"success": False, "message": "未登录"})
|
return jsonify({"success": False, "message": "未登录"})
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
|
||||||
|
# 获取账号索引参数
|
||||||
|
account_index = int(request.args.get("account_index", 0))
|
||||||
|
|
||||||
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
paths = []
|
paths = []
|
||||||
if path := request.args.get("path"):
|
if path := request.args.get("path"):
|
||||||
if path == "/":
|
if path == "/":
|
||||||
@ -718,7 +767,15 @@ def get_savepath_detail():
|
|||||||
def delete_file():
|
def delete_file():
|
||||||
if not is_login():
|
if not is_login():
|
||||||
return jsonify({"success": False, "message": "未登录"})
|
return jsonify({"success": False, "message": "未登录"})
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
|
||||||
|
# 获取账号索引参数
|
||||||
|
account_index = int(request.json.get("account_index", 0))
|
||||||
|
|
||||||
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
if fid := request.json.get("fid"):
|
if fid := request.json.get("fid"):
|
||||||
response = account.delete([fid])
|
response = account.delete([fid])
|
||||||
|
|
||||||
@ -805,6 +862,15 @@ def add_task():
|
|||||||
# 定时任务执行的函数
|
# 定时任务执行的函数
|
||||||
def run_python(args):
|
def run_python(args):
|
||||||
logging.info(f">>> 定时运行任务")
|
logging.info(f">>> 定时运行任务")
|
||||||
|
|
||||||
|
# 在定时任务开始前清理过期缓存
|
||||||
|
try:
|
||||||
|
cleaned_count = cleanup_expired_cache()
|
||||||
|
if cleaned_count > 0:
|
||||||
|
logging.info(f">>> 清理了 {cleaned_count} 个过期缓存项")
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning(f">>> 清理缓存时出错: {e}")
|
||||||
|
|
||||||
# 检查是否需要随机延迟执行
|
# 检查是否需要随机延迟执行
|
||||||
if delay := config_data.get("crontab_delay"):
|
if delay := config_data.get("crontab_delay"):
|
||||||
try:
|
try:
|
||||||
@ -1099,6 +1165,77 @@ def get_user_info():
|
|||||||
return jsonify({"success": True, "data": user_info_list})
|
return jsonify({"success": True, "data": user_info_list})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/get_accounts_detail")
|
||||||
|
def get_accounts_detail():
|
||||||
|
"""获取所有账号的详细信息,包括昵称和空间使用情况"""
|
||||||
|
if not is_login():
|
||||||
|
return jsonify({"success": False, "message": "未登录"})
|
||||||
|
|
||||||
|
accounts_detail = []
|
||||||
|
for idx, cookie in enumerate(config_data["cookie"]):
|
||||||
|
account = Quark(cookie, idx)
|
||||||
|
account_info = account.init()
|
||||||
|
|
||||||
|
# 如果无法获取账号信息,检查是否有移动端参数
|
||||||
|
if not account_info:
|
||||||
|
has_mparam = bool(account.mparam)
|
||||||
|
# 如果只有移动端参数,跳过此账号(不显示在文件整理页面的账号选择栏中)
|
||||||
|
if has_mparam:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# 如果既没有账号信息也没有移动端参数,显示为未登录
|
||||||
|
account_detail = {
|
||||||
|
"index": idx,
|
||||||
|
"nickname": "",
|
||||||
|
"is_active": False,
|
||||||
|
"used_space": 0,
|
||||||
|
"total_space": 0,
|
||||||
|
"usage_rate": 0,
|
||||||
|
"display_text": f"账号{idx + 1}(未登录)"
|
||||||
|
}
|
||||||
|
accounts_detail.append(account_detail)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 成功获取账号信息的情况
|
||||||
|
account_detail = {
|
||||||
|
"index": idx,
|
||||||
|
"nickname": account_info["nickname"],
|
||||||
|
"is_active": account.is_active,
|
||||||
|
"used_space": 0,
|
||||||
|
"total_space": 0,
|
||||||
|
"usage_rate": 0,
|
||||||
|
"display_text": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查是否有移动端参数
|
||||||
|
has_mparam = bool(account.mparam)
|
||||||
|
|
||||||
|
if has_mparam:
|
||||||
|
# 同时有cookie和移动端参数,尝试获取空间信息
|
||||||
|
try:
|
||||||
|
growth_info = account.get_growth_info()
|
||||||
|
if growth_info:
|
||||||
|
total_capacity = growth_info.get("total_capacity", 0)
|
||||||
|
account_detail["total_space"] = total_capacity
|
||||||
|
# 显示昵称和总容量
|
||||||
|
total_str = format_bytes(total_capacity)
|
||||||
|
account_detail["display_text"] = f"{account_info['nickname']} · {total_str}"
|
||||||
|
else:
|
||||||
|
# 获取空间信息失败,只显示昵称
|
||||||
|
account_detail["display_text"] = account_info["nickname"]
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"获取账号 {idx} 空间信息失败: {str(e)}")
|
||||||
|
# 获取空间信息失败,只显示昵称
|
||||||
|
account_detail["display_text"] = account_info["nickname"]
|
||||||
|
else:
|
||||||
|
# 只有cookie,没有移动端参数,只显示昵称
|
||||||
|
account_detail["display_text"] = account_info["nickname"]
|
||||||
|
|
||||||
|
accounts_detail.append(account_detail)
|
||||||
|
|
||||||
|
return jsonify({"success": True, "data": accounts_detail})
|
||||||
|
|
||||||
|
|
||||||
# 重置文件夹(删除文件夹内所有文件和相关记录)
|
# 重置文件夹(删除文件夹内所有文件和相关记录)
|
||||||
@app.route("/reset_folder", methods=["POST"])
|
@app.route("/reset_folder", methods=["POST"])
|
||||||
def reset_folder():
|
def reset_folder():
|
||||||
@ -1107,14 +1244,18 @@ def reset_folder():
|
|||||||
|
|
||||||
# 获取请求参数
|
# 获取请求参数
|
||||||
save_path = request.json.get("save_path", "")
|
save_path = request.json.get("save_path", "")
|
||||||
task_name = request.json.get("task_name", "")
|
account_index = int(request.json.get("account_index", 0)) # 新增账号索引参数
|
||||||
|
|
||||||
if not save_path:
|
if not save_path:
|
||||||
return jsonify({"success": False, "message": "保存路径不能为空"})
|
return jsonify({"success": False, "message": "保存路径不能为空"})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
# 初始化夸克网盘客户端
|
# 初始化夸克网盘客户端
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
|
|
||||||
# 1. 获取文件夹ID
|
# 1. 获取文件夹ID
|
||||||
# 先检查是否已有缓存的文件夹ID
|
# 先检查是否已有缓存的文件夹ID
|
||||||
@ -1189,10 +1330,16 @@ def get_file_list():
|
|||||||
order = request.args.get("order", "asc")
|
order = request.args.get("order", "asc")
|
||||||
page = int(request.args.get("page", 1))
|
page = int(request.args.get("page", 1))
|
||||||
page_size = int(request.args.get("page_size", 15))
|
page_size = int(request.args.get("page_size", 15))
|
||||||
|
account_index = int(request.args.get("account_index", 0))
|
||||||
|
force_refresh = request.args.get("force_refresh", "false").lower() == "true" # 新增账号索引参数
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
# 初始化夸克网盘客户端
|
# 初始化夸克网盘客户端
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
|
|
||||||
# 获取文件列表
|
# 获取文件列表
|
||||||
if folder_id == "root":
|
if folder_id == "root":
|
||||||
@ -1202,35 +1349,84 @@ def get_file_list():
|
|||||||
# 获取当前文件夹的路径
|
# 获取当前文件夹的路径
|
||||||
paths = account.get_paths(folder_id)
|
paths = account.get_paths(folder_id)
|
||||||
|
|
||||||
# 获取文件列表
|
# 获取性能配置
|
||||||
files = account.ls_dir(folder_id)
|
perf_config = get_performance_config()
|
||||||
|
api_page_size = perf_config.get("api_page_size", 200)
|
||||||
|
cache_expire_time = perf_config.get("cache_expire_time", 30)
|
||||||
|
|
||||||
|
# 缓存键
|
||||||
|
cache_key = f"{account_index}_{folder_id}_{sort_by}_{order}"
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
# 检查缓存(除非强制刷新)
|
||||||
|
if not force_refresh:
|
||||||
|
with cache_lock:
|
||||||
|
if cache_key in file_list_cache:
|
||||||
|
cache_data, cache_time = file_list_cache[cache_key]
|
||||||
|
if current_time - cache_time < cache_expire_time:
|
||||||
|
# 使用缓存数据
|
||||||
|
cached_files = cache_data
|
||||||
|
total = len(cached_files)
|
||||||
|
start_idx = (page - 1) * page_size
|
||||||
|
end_idx = min(start_idx + page_size, total)
|
||||||
|
paginated_files = cached_files[start_idx:end_idx]
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"data": {
|
||||||
|
"list": paginated_files,
|
||||||
|
"total": total,
|
||||||
|
"paths": paths
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
# 强制刷新时,清除当前目录的缓存
|
||||||
|
with cache_lock:
|
||||||
|
if cache_key in file_list_cache:
|
||||||
|
del file_list_cache[cache_key]
|
||||||
|
|
||||||
|
# 无论分页还是全部模式,都必须获取所有文件才能进行正确的全局排序
|
||||||
|
files = account.ls_dir(folder_id, page_size=api_page_size)
|
||||||
|
|
||||||
if isinstance(files, dict) and files.get("error"):
|
if isinstance(files, dict) and files.get("error"):
|
||||||
return jsonify({"success": False, "message": f"获取文件列表失败: {files.get('error', '未知错误')}"})
|
# 检查是否是目录不存在的错误
|
||||||
|
error_msg = files.get('error', '未知错误')
|
||||||
|
if "不存在" in error_msg or "无效" in error_msg or "找不到" in error_msg:
|
||||||
|
return jsonify({"success": False, "message": f"目录不存在或无权限访问: {error_msg}"})
|
||||||
|
else:
|
||||||
|
return jsonify({"success": False, "message": f"获取文件列表失败: {error_msg}"})
|
||||||
|
|
||||||
# 计算总数
|
# 计算总数
|
||||||
total = len(files)
|
total = len(files)
|
||||||
|
|
||||||
# 排序
|
# 优化排序:使用更高效的排序方法
|
||||||
if sort_by == "file_name":
|
def get_sort_key(file_item):
|
||||||
files.sort(key=lambda x: x["file_name"].lower())
|
if sort_by == "file_name":
|
||||||
elif sort_by == "file_size":
|
return file_item["file_name"].lower()
|
||||||
files.sort(key=lambda x: x["size"] if not x["dir"] else 0)
|
elif sort_by == "file_size":
|
||||||
else: # updated_at
|
return file_item["size"] if not file_item["dir"] else 0
|
||||||
files.sort(key=lambda x: x["updated_at"])
|
else: # updated_at
|
||||||
|
return file_item["updated_at"]
|
||||||
|
|
||||||
if order == "desc":
|
# 分离文件夹和文件以优化排序
|
||||||
files.reverse()
|
|
||||||
|
|
||||||
# 根据排序字段决定是否将目录放在前面
|
|
||||||
if sort_by == "updated_at":
|
if sort_by == "updated_at":
|
||||||
# 修改日期排序时严格按照日期排序,不区分文件夹和文件
|
# 修改日期排序时严格按照日期排序,不区分文件夹和文件
|
||||||
|
files.sort(key=get_sort_key, reverse=(order == "desc"))
|
||||||
sorted_files = files
|
sorted_files = files
|
||||||
else:
|
else:
|
||||||
# 其他排序时目录始终在前面
|
# 其他排序时目录始终在前面,分别排序以提高效率
|
||||||
directories = [f for f in files if f["dir"]]
|
directories = [f for f in files if f["dir"]]
|
||||||
normal_files = [f for f in files if not f["dir"]]
|
normal_files = [f for f in files if not f["dir"]]
|
||||||
|
|
||||||
|
directories.sort(key=get_sort_key, reverse=(order == "desc"))
|
||||||
|
normal_files.sort(key=get_sort_key, reverse=(order == "desc"))
|
||||||
|
|
||||||
sorted_files = directories + normal_files
|
sorted_files = directories + normal_files
|
||||||
|
|
||||||
|
# 更新缓存
|
||||||
|
with cache_lock:
|
||||||
|
file_list_cache[cache_key] = (sorted_files, current_time)
|
||||||
|
|
||||||
# 分页
|
# 分页
|
||||||
start_idx = (page - 1) * page_size
|
start_idx = (page - 1) * page_size
|
||||||
end_idx = min(start_idx + page_size, total)
|
end_idx = min(start_idx + page_size, total)
|
||||||
@ -1263,13 +1459,18 @@ def preview_rename():
|
|||||||
naming_mode = request.args.get("naming_mode", "regex") # regex, sequence, episode
|
naming_mode = request.args.get("naming_mode", "regex") # regex, sequence, episode
|
||||||
include_folders = request.args.get("include_folders", "false") == "true"
|
include_folders = request.args.get("include_folders", "false") == "true"
|
||||||
filterwords = request.args.get("filterwords", "")
|
filterwords = request.args.get("filterwords", "")
|
||||||
|
account_index = int(request.args.get("account_index", 0)) # 新增账号索引参数
|
||||||
|
|
||||||
if not pattern:
|
if not pattern:
|
||||||
pattern = ".*"
|
pattern = ".*"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
# 初始化夸克网盘客户端
|
# 初始化夸克网盘客户端
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
|
|
||||||
# 获取文件列表
|
# 获取文件列表
|
||||||
if folder_id == "root":
|
if folder_id == "root":
|
||||||
@ -1415,13 +1616,18 @@ def batch_rename():
|
|||||||
# 获取请求参数
|
# 获取请求参数
|
||||||
data = request.json
|
data = request.json
|
||||||
files = data.get("files", [])
|
files = data.get("files", [])
|
||||||
|
account_index = int(data.get("account_index", 0)) # 新增账号索引参数
|
||||||
|
|
||||||
if not files:
|
if not files:
|
||||||
return jsonify({"success": False, "message": "没有文件需要重命名"})
|
return jsonify({"success": False, "message": "没有文件需要重命名"})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
# 初始化夸克网盘客户端
|
# 初始化夸克网盘客户端
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
|
|
||||||
# 批量重命名
|
# 批量重命名
|
||||||
success_count = 0
|
success_count = 0
|
||||||
@ -1481,10 +1687,17 @@ def undo_rename():
|
|||||||
return jsonify({"success": False, "message": "未登录"})
|
return jsonify({"success": False, "message": "未登录"})
|
||||||
data = request.json
|
data = request.json
|
||||||
save_path = data.get("save_path", "")
|
save_path = data.get("save_path", "")
|
||||||
|
account_index = int(data.get("account_index", 0)) # 新增账号索引参数
|
||||||
|
|
||||||
if not save_path:
|
if not save_path:
|
||||||
return jsonify({"success": False, "message": "缺少目录参数"})
|
return jsonify({"success": False, "message": "缺少目录参数"})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
account = Quark(config_data["cookie"][0], 0)
|
# 验证账号索引
|
||||||
|
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||||
|
return jsonify({"success": False, "message": "账号索引无效"})
|
||||||
|
|
||||||
|
account = Quark(config_data["cookie"][account_index], account_index)
|
||||||
# 查询该目录下最近一次重命名(按transfer_time分组,task_name=rename)
|
# 查询该目录下最近一次重命名(按transfer_time分组,task_name=rename)
|
||||||
records = record_db.get_records_by_save_path(save_path)
|
records = record_db.get_records_by_save_path(save_path)
|
||||||
rename_records = [r for r in records if r["task_name"] == "rename"]
|
rename_records = [r for r in records if r["task_name"] == "rename"]
|
||||||
|
|||||||
@ -4037,6 +4037,21 @@ table.selectable-records .expand-button:hover {
|
|||||||
margin-right: -4px !important;
|
margin-right: -4px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 文件整理性能设置样式 */
|
||||||
|
.performance-setting-row > [class*='col-'] {
|
||||||
|
padding-left: 4px !important;
|
||||||
|
padding-right: 4px !important;
|
||||||
|
}
|
||||||
|
.performance-setting-row {
|
||||||
|
margin-left: -4px !important;
|
||||||
|
margin-right: -4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 性能设置板块标题上移8px,统一与其他设置板块的间距 */
|
||||||
|
.row.title[title*="文件整理页面的请求参数"] {
|
||||||
|
margin-top: 12px !important; /* 从默认的20px减少到12px,上移8px */
|
||||||
|
}
|
||||||
|
|
||||||
/* 任务单元基础样式 */
|
/* 任务单元基础样式 */
|
||||||
.task {
|
.task {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -4187,6 +4202,19 @@ select.task-filter-select,
|
|||||||
|
|
||||||
.batch-rename-btn {
|
.batch-rename-btn {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
color: var(--dark-text-color) !important;
|
||||||
|
border-color: var(--dark-text-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch-rename-btn:hover {
|
||||||
|
background-color: var(--dark-text-color) !important;
|
||||||
|
border-color: var(--dark-text-color) !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 文件整理页面刷新当前目录缓存按钮图标大小 */
|
||||||
|
.batch-rename-btn .bi-arrow-clockwise {
|
||||||
|
font-size: 1.15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 文件表格中的展开按钮 */
|
/* 文件表格中的展开按钮 */
|
||||||
@ -4422,6 +4450,28 @@ tr.selected-file .file-size-cell .delete-record-btn {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 文件整理账号选择栏样式 */
|
||||||
|
.file-manager-account-selector {
|
||||||
|
margin-bottom: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 账号选择下拉框样式 */
|
||||||
|
.file-manager-account-select {
|
||||||
|
padding-left: 8px !important;
|
||||||
|
text-indent: 0 !important;
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
line-height: 1.5 !important;
|
||||||
|
padding-right: 24px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 账号选择框右侧圆角 - 需要更高优先级覆盖file-manager-input的圆角设置 */
|
||||||
|
.file-manager-rule-bar .file-manager-account-select,
|
||||||
|
.file-manager-rule-bar-responsive .file-manager-account-select {
|
||||||
|
border-top-right-radius: 6px !important;
|
||||||
|
border-bottom-right-radius: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 禁止在表格中选择文本,以便更好地支持点击选择 */
|
/* 禁止在表格中选择文本,以便更好地支持点击选择 */
|
||||||
table.selectable-files {
|
table.selectable-files {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -4860,6 +4910,12 @@ body .selectable-files tr.selected-file .file-size-cell .delete-record-btn {
|
|||||||
border-radius: 0 !important; /* 去除圆角 */
|
border-radius: 0 !important; /* 去除圆角 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 账号选择框例外 - 保持右侧圆角 */
|
||||||
|
.file-manager-rule-bar .file-manager-input.file-manager-account-select {
|
||||||
|
border-top-right-radius: 6px !important;
|
||||||
|
border-bottom-right-radius: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 文件整理页面重命名配置框输入框相邻边框重叠样式 */
|
/* 文件整理页面重命名配置框输入框相邻边框重叠样式 */
|
||||||
.file-manager-rule-bar .file-manager-input:not(:first-child) {
|
.file-manager-rule-bar .file-manager-input:not(:first-child) {
|
||||||
margin-left: -1px; /* 向左移动1px,使边框重叠 */
|
margin-left: -1px; /* 向左移动1px,使边框重叠 */
|
||||||
@ -5033,6 +5089,15 @@ body .selectable-files tr.selected-file .file-size-cell .delete-record-btn {
|
|||||||
.file-manager-rule-bar-responsive { display: block !important; }
|
.file-manager-rule-bar-responsive { display: block !important; }
|
||||||
.file-manager-rule-bar-responsive .input-group { width: 100%; }
|
.file-manager-rule-bar-responsive .input-group { width: 100%; }
|
||||||
.file-manager-rule-bar-responsive .input-group + .input-group { margin-top: 8px; }
|
.file-manager-rule-bar-responsive .input-group + .input-group { margin-top: 8px; }
|
||||||
|
|
||||||
|
/* 移动端账号选择栏下边距 - 确保与命名规则栏有8px间距 */
|
||||||
|
.file-manager-account-selector {
|
||||||
|
margin-bottom: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-manager-account-selector .file-manager-rule-bar-responsive {
|
||||||
|
margin-bottom: 0 !important; /* 移除内部边距,使用外部容器的边距 */
|
||||||
|
}
|
||||||
/* 含文件夹样式调整 */
|
/* 含文件夹样式调整 */
|
||||||
.file-manager-rule-bar-responsive .input-group-text.file-folder-rounded {
|
.file-manager-rule-bar-responsive .input-group-text.file-folder-rounded {
|
||||||
border-top-left-radius: 0 !important; /* 左侧不要圆角 */
|
border-top-left-radius: 0 !important; /* 左侧不要圆角 */
|
||||||
@ -5067,6 +5132,11 @@ body .selectable-files tr.selected-file .file-size-cell .delete-record-btn {
|
|||||||
.file-manager-rule-bar-responsive .input-group .batch-rename-btn {
|
.file-manager-rule-bar-responsive .input-group .batch-rename-btn {
|
||||||
margin-left: 8px !important;
|
margin-left: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端账号选择栏中的刷新按钮间距 */
|
||||||
|
.file-manager-rule-bar-responsive .d-flex .batch-rename-btn {
|
||||||
|
margin-left: 8px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.file-manager-rule-bar { display: flex !important; }
|
.file-manager-rule-bar { display: flex !important; }
|
||||||
|
|||||||
@ -363,7 +363,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p style="margin-top: -4px; margin-bottom: 4px;">所有账号都会进行签到(纯签到只需填写移动端参数),只有第一个账号会进行转存,请自行确认顺序。如需签到,请在 Cookie 后方添加签到参数。</p>
|
<p style="margin-top: -4px; margin-bottom: 4px;">所有账号都会进行签到(纯签到只需填写移动端参数),只有第一个账号会进行转存,请自行确认账号顺序;所有填写了 Cookie 的账号均支持文件整理,如需签到请在 Cookie 后方添加签到参数。</p>
|
||||||
<div v-for="(value, index) in formData.cookie" :key="index" class="input-group mb-2">
|
<div v-for="(value, index) in formData.cookie" :key="index" class="input-group mb-2">
|
||||||
<div class="input-group-prepend" v-if="userInfoList[index]">
|
<div class="input-group-prepend" v-if="userInfoList[index]">
|
||||||
<span class="input-group-text" :style="userInfoList[index].nickname ? (userInfoList[index].is_active ? 'color: var(--dark-text-color);' : 'color: red;') : 'color: var(--dark-text-color);'">
|
<span class="input-group-text" :style="userInfoList[index].nickname ? (userInfoList[index].is_active ? 'color: var(--dark-text-color);' : 'color: red;') : 'color: var(--dark-text-color);'">
|
||||||
@ -398,7 +398,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 pl-1">
|
<div class="col-sm-6 pl-1">
|
||||||
<div class="input-group" title="添加随机延迟时间:定时任务将在0到设定秒数之间随机延迟执行,可设范围:0–3600秒,0表示不延迟">
|
<div class="input-group" title="添加随机延迟时间:定时任务将在0到设定秒数之间随机延迟执行。建议值:0–3600,0表示不延迟">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">延迟执行</span>
|
<span class="input-group-text">延迟执行</span>
|
||||||
</div>
|
</div>
|
||||||
@ -612,6 +612,40 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 性能设置 -->
|
||||||
|
<div class="row title" title="调整文件整理页面的请求参数和缓存时长,可提升大文件夹的加载速度和数据刷新效率。合理配置可减少API请求次数,同时保证数据及时更新">
|
||||||
|
<div class="col">
|
||||||
|
<h2 style="display: inline-block; font-size: 1.5rem;">性能设置</h2>
|
||||||
|
<span class="badge badge-pill badge-light">
|
||||||
|
<a href="#"><i class="bi bi-question-circle"></i></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2 performance-setting-row">
|
||||||
|
<div class="col-lg-6 col-md-6 mb-2">
|
||||||
|
<div class="input-group" title="每次请求夸克API时获取的文件数量,适当增大该数值可减少请求次数,提升大文件夹的加载效率。建议值:100–500">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">单次请求文件数量</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control no-spinner" v-model="formData.file_performance.api_page_size" placeholder="200">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text square-append">个</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 mb-2">
|
||||||
|
<div class="input-group" title="文件列表在本地缓存的持续时间,过期后将自动清除。设置过短会增加API请求次数,设置过长可能无法及时反映最新变动。建议值:0-300,0表示不缓存">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">文件列表缓存时长</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control no-spinner" v-model="formData.file_performance.cache_expire_time" placeholder="30">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text square-append">秒</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="activeTab === 'tasklist'">
|
<div v-if="activeTab === 'tasklist'">
|
||||||
@ -1000,13 +1034,48 @@
|
|||||||
|
|
||||||
<div v-if="activeTab === 'filemanager'">
|
<div v-if="activeTab === 'filemanager'">
|
||||||
<div style="height: 20px;"></div>
|
<div style="height: 20px;"></div>
|
||||||
|
<!-- 账号选择栏 -->
|
||||||
|
<div class="row file-manager-account-selector">
|
||||||
|
<div class="col-12">
|
||||||
|
<!-- 桌面端账号选择 -->
|
||||||
|
<div class="d-flex align-items-center file-manager-rule-bar">
|
||||||
|
<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 file-manager-input file-manager-account-select" v-model="fileManager.selectedAccountIndex" @change="onAccountChange">
|
||||||
|
<option v-for="(account, index) in accountsDetail" :key="index" :value="index">{{ account.display_text }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="refreshCurrentFolderCache" title="刷新当前目录缓存">
|
||||||
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<!-- 移动端账号选择 -->
|
||||||
|
<div class="file-manager-rule-bar-responsive">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="input-group" style="flex: 1;">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">夸克账号</span>
|
||||||
|
</div>
|
||||||
|
<select class="form-control task-filter-select file-manager-account-select" v-model="fileManager.selectedAccountIndex" @change="onAccountChange">
|
||||||
|
<option v-for="(account, index) in accountsDetail" :key="index" :value="index">{{ account.display_text }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="refreshCurrentFolderCache" title="刷新当前目录缓存">
|
||||||
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- 重命名规则设置栏 -->
|
<!-- 重命名规则设置栏 -->
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<!-- 桌面端结构(原有) -->
|
<!-- 桌面端结构(原有) -->
|
||||||
<div class="d-flex align-items-center file-manager-rule-bar">
|
<div class="d-flex align-items-center file-manager-rule-bar">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<button class="btn btn-outline-secondary" type="button" @click="switchNamingMode"
|
<button class="btn btn-outline-secondary" type="button" @click="previewAndRename"
|
||||||
:title="fileManager.use_sequence_naming ? '预览顺序命名效果' : (fileManager.use_episode_naming ? '预览剧集命名效果' : '预览正则命名效果')">
|
:title="fileManager.use_sequence_naming ? '预览顺序命名效果' : (fileManager.use_episode_naming ? '预览剧集命名效果' : '预览正则命名效果')">
|
||||||
{{ fileManager.use_sequence_naming ? '顺序命名' : (fileManager.use_episode_naming ? '剧集命名' : '正则命名') }}
|
{{ fileManager.use_sequence_naming ? '顺序命名' : (fileManager.use_episode_naming ? '剧集命名' : '正则命名') }}
|
||||||
</button>
|
</button>
|
||||||
@ -1022,7 +1091,7 @@
|
|||||||
<input type="checkbox" v-model="fileManager.include_folders"> 含文件夹
|
<input type="checkbox" v-model="fileManager.include_folders"> 含文件夹
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="switchNamingMode" title="预览并执行重命名">
|
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="previewAndRename" title="预览并执行重命名">
|
||||||
<i class="bi bi-pencil"></i>
|
<i class="bi bi-pencil"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -1031,7 +1100,7 @@
|
|||||||
<!-- 第一行:命名按钮+表达式+替换表达式 -->
|
<!-- 第一行:命名按钮+表达式+替换表达式 -->
|
||||||
<div class="input-group mb-2">
|
<div class="input-group mb-2">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<button class="btn btn-outline-secondary" type="button" @click="switchNamingMode"
|
<button class="btn btn-outline-secondary" type="button" @click="previewAndRename"
|
||||||
:title="fileManager.use_sequence_naming ? '预览顺序命名效果' : (fileManager.use_episode_naming ? '预览剧集命名效果' : '预览正则命名效果')">
|
:title="fileManager.use_sequence_naming ? '预览顺序命名效果' : (fileManager.use_episode_naming ? '预览剧集命名效果' : '预览正则命名效果')">
|
||||||
{{ fileManager.use_sequence_naming ? '顺序命名' : (fileManager.use_episode_naming ? '剧集命名' : '正则命名') }}
|
{{ fileManager.use_sequence_naming ? '顺序命名' : (fileManager.use_episode_naming ? '剧集命名' : '正则命名') }}
|
||||||
</button>
|
</button>
|
||||||
@ -1051,7 +1120,7 @@
|
|||||||
<span class="input-group-text file-folder-rounded">
|
<span class="input-group-text file-folder-rounded">
|
||||||
<input type="checkbox" v-model="fileManager.include_folders"> 含文件夹
|
<input type="checkbox" v-model="fileManager.include_folders"> 含文件夹
|
||||||
</span>
|
</span>
|
||||||
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="switchNamingMode" title="预览并执行重命名">
|
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="previewAndRename" title="预览并执行重命名">
|
||||||
<i class="bi bi-pencil"></i>
|
<i class="bi bi-pencil"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -1417,9 +1486,14 @@
|
|||||||
delete_task: "always",
|
delete_task: "always",
|
||||||
refresh_plex: "always",
|
refresh_plex: "always",
|
||||||
refresh_alist: "always"
|
refresh_alist: "always"
|
||||||
|
},
|
||||||
|
file_performance: {
|
||||||
|
api_page_size: 200,
|
||||||
|
cache_expire_time: 30
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
userInfoList: [], // 用户信息列表
|
userInfoList: [], // 用户信息列表
|
||||||
|
accountsDetail: [], // 账号详细信息列表
|
||||||
newTask: {
|
newTask: {
|
||||||
taskname: "",
|
taskname: "",
|
||||||
shareurl: "",
|
shareurl: "",
|
||||||
@ -1497,8 +1571,13 @@
|
|||||||
lastSelectedRecordIndex: -1, // 记录最后选择的记录索引,用于Shift选择
|
lastSelectedRecordIndex: -1, // 记录最后选择的记录索引,用于Shift选择
|
||||||
fileManager: {
|
fileManager: {
|
||||||
loading: false,
|
loading: false,
|
||||||
// 当前文件夹ID - 根据localStorage决定初始目录
|
// 当前文件夹ID - 根据localStorage和账号索引决定初始目录
|
||||||
currentFolder: localStorage.getItem('quarkAutoSave_fileManagerLastFolder') || 'root',
|
currentFolder: (() => {
|
||||||
|
const selectedAccountIndex = parseInt(localStorage.getItem('quarkAutoSave_selectedAccountIndex') || '0');
|
||||||
|
return localStorage.getItem(`quarkAutoSave_fileManagerLastFolder_${selectedAccountIndex}`) || 'root';
|
||||||
|
})(),
|
||||||
|
// 选中的账号索引 - 从localStorage读取,默认为0
|
||||||
|
selectedAccountIndex: parseInt(localStorage.getItem('quarkAutoSave_selectedAccountIndex') || '0'),
|
||||||
// 面包屑导航路径
|
// 面包屑导航路径
|
||||||
paths: [],
|
paths: [],
|
||||||
// 文件列表
|
// 文件列表
|
||||||
@ -1691,6 +1770,7 @@
|
|||||||
activeTab(newValue, oldValue) {
|
activeTab(newValue, oldValue) {
|
||||||
// 如果切换到文件整理页面,则加载文件列表
|
// 如果切换到文件整理页面,则加载文件列表
|
||||||
if (newValue === 'filemanager') {
|
if (newValue === 'filemanager') {
|
||||||
|
this.fetchAccountsDetail();
|
||||||
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1705,6 +1785,10 @@
|
|||||||
this.fetchData();
|
this.fetchData();
|
||||||
this.checkNewVersion();
|
this.checkNewVersion();
|
||||||
this.fetchUserInfo(); // 获取用户信息
|
this.fetchUserInfo(); // 获取用户信息
|
||||||
|
this.fetchAccountsDetail(); // 获取账号详细信息
|
||||||
|
|
||||||
|
// 迁移旧的localStorage数据到新格式(为每个账号单独存储目录)
|
||||||
|
this.migrateFileManagerFolderData();
|
||||||
|
|
||||||
// 添加点击事件监听
|
// 添加点击事件监听
|
||||||
document.addEventListener('click', this.handleOutsideClick);
|
document.addEventListener('click', this.handleOutsideClick);
|
||||||
@ -1822,6 +1906,7 @@
|
|||||||
|
|
||||||
// 如果当前标签是文件整理,则加载文件列表
|
// 如果当前标签是文件整理,则加载文件列表
|
||||||
if (this.activeTab === 'filemanager') {
|
if (this.activeTab === 'filemanager') {
|
||||||
|
this.fetchAccountsDetail();
|
||||||
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1874,6 +1959,92 @@
|
|||||||
console.error('获取用户信息失败:', error);
|
console.error('获取用户信息失败:', error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fetchAccountsDetail() {
|
||||||
|
// 获取所有账号的详细信息,包括空间使用情况
|
||||||
|
axios.get('/get_accounts_detail')
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.success) {
|
||||||
|
this.accountsDetail = response.data.data;
|
||||||
|
// 验证当前选中的账号索引是否有效
|
||||||
|
if (this.fileManager.selectedAccountIndex >= this.accountsDetail.length) {
|
||||||
|
this.fileManager.selectedAccountIndex = 0;
|
||||||
|
localStorage.setItem('quarkAutoSave_selectedAccountIndex', '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('获取账号详细信息失败:', error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 迁移旧的localStorage数据到新格式(为每个账号单独存储目录)
|
||||||
|
migrateFileManagerFolderData() {
|
||||||
|
const oldFolderKey = 'quarkAutoSave_fileManagerLastFolder';
|
||||||
|
const oldFolderValue = localStorage.getItem(oldFolderKey);
|
||||||
|
|
||||||
|
if (oldFolderValue) {
|
||||||
|
// 如果存在旧数据,将其迁移到当前选中账号的新格式
|
||||||
|
const currentAccountIndex = this.fileManager.selectedAccountIndex;
|
||||||
|
const newFolderKey = `quarkAutoSave_fileManagerLastFolder_${currentAccountIndex}`;
|
||||||
|
|
||||||
|
// 只有当新格式的数据不存在时才进行迁移
|
||||||
|
if (!localStorage.getItem(newFolderKey)) {
|
||||||
|
localStorage.setItem(newFolderKey, oldFolderValue);
|
||||||
|
console.log(`已将文件管理器目录数据迁移到账号 ${currentAccountIndex}: ${oldFolderValue}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除旧的数据
|
||||||
|
localStorage.removeItem(oldFolderKey);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onAccountChange() {
|
||||||
|
// 保存选中的账号索引到localStorage
|
||||||
|
localStorage.setItem('quarkAutoSave_selectedAccountIndex', this.fileManager.selectedAccountIndex.toString());
|
||||||
|
|
||||||
|
// 获取新账号最后一次访问的目录
|
||||||
|
const newAccountLastFolder = localStorage.getItem(`quarkAutoSave_fileManagerLastFolder_${this.fileManager.selectedAccountIndex}`) || 'root';
|
||||||
|
|
||||||
|
// 重置页码并切换到新账号的最后访问目录
|
||||||
|
this.fileManager.currentPage = 1;
|
||||||
|
this.loadFileListWithFallback(newAccountLastFolder);
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshCurrentFolderCache() {
|
||||||
|
// 刷新当前目录的缓存,强制重新请求最新的文件列表
|
||||||
|
// 调用后端接口,添加强制刷新参数
|
||||||
|
const params = {
|
||||||
|
folder_id: this.fileManager.currentFolder || 'root',
|
||||||
|
sort_by: this.fileManager.sortBy,
|
||||||
|
order: this.fileManager.sortOrder,
|
||||||
|
page_size: this.fileManager.pageSize,
|
||||||
|
page: this.fileManager.currentPage,
|
||||||
|
account_index: this.fileManager.selectedAccountIndex,
|
||||||
|
force_refresh: true // 强制刷新参数
|
||||||
|
};
|
||||||
|
|
||||||
|
axios.get('/file_list', { params })
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.success) {
|
||||||
|
this.fileManager.fileList = response.data.data.list;
|
||||||
|
this.fileManager.total = response.data.data.total;
|
||||||
|
this.fileManager.totalPages = Math.ceil(response.data.data.total / this.fileManager.pageSize);
|
||||||
|
this.fileManager.paths = response.data.data.paths || [];
|
||||||
|
this.fileManager.gotoPage = this.fileManager.currentPage;
|
||||||
|
// 移除成功通知
|
||||||
|
} else {
|
||||||
|
this.showToast('刷新失败:' + response.data.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检测当前的命名模式
|
||||||
|
this.detectFileManagerNamingMode();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('刷新缓存失败:', error);
|
||||||
|
this.showToast('刷新缓存失败,请稍后重试');
|
||||||
|
});
|
||||||
|
},
|
||||||
// 添加一个检查分享链接状态的方法
|
// 添加一个检查分享链接状态的方法
|
||||||
checkShareUrlStatus() {
|
checkShareUrlStatus() {
|
||||||
// 只在任务列表页面检查
|
// 只在任务列表页面检查
|
||||||
@ -1966,6 +2137,8 @@
|
|||||||
if (savedFileManagerPageSize) {
|
if (savedFileManagerPageSize) {
|
||||||
this.fileManager.pageSize = savedFileManagerPageSize === 'all' ? 99999 : parseInt(savedFileManagerPageSize);
|
this.fileManager.pageSize = savedFileManagerPageSize === 'all' ? 99999 : parseInt(savedFileManagerPageSize);
|
||||||
}
|
}
|
||||||
|
// 获取账号详细信息
|
||||||
|
this.fetchAccountsDetail();
|
||||||
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2042,6 +2215,24 @@
|
|||||||
refresh_alist: "always"
|
refresh_alist: "always"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// 确保文件整理性能配置存在
|
||||||
|
if (!config_data.file_performance) {
|
||||||
|
config_data.file_performance = {
|
||||||
|
api_page_size: 200,
|
||||||
|
cache_expire_time: 30
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// 确保必要的字段存在,移除废弃的字段
|
||||||
|
if (!config_data.file_performance.api_page_size) {
|
||||||
|
config_data.file_performance.api_page_size = 200;
|
||||||
|
}
|
||||||
|
if (!config_data.file_performance.cache_expire_time) {
|
||||||
|
config_data.file_performance.cache_expire_time = 30;
|
||||||
|
}
|
||||||
|
// 移除废弃的字段
|
||||||
|
delete config_data.file_performance.large_page_size;
|
||||||
|
delete config_data.file_performance.cache_cleanup_interval;
|
||||||
|
}
|
||||||
this.formData = config_data;
|
this.formData = config_data;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.configModified = false;
|
this.configModified = false;
|
||||||
@ -2869,6 +3060,22 @@
|
|||||||
params = { fid: params }
|
params = { fid: params }
|
||||||
}
|
}
|
||||||
this.modalLoading = true;
|
this.modalLoading = true;
|
||||||
|
|
||||||
|
// 根据模态框类型决定使用哪个账号
|
||||||
|
// 任务配置相关的模态框始终使用主账号(索引0)
|
||||||
|
// 文件整理页面的预览模态框使用选中的账号
|
||||||
|
const modalType = document.getElementById('fileSelectModal').getAttribute('data-modal-type');
|
||||||
|
const accountIndex = (modalType === 'preview-filemanager') ? this.fileManager.selectedAccountIndex : 0;
|
||||||
|
|
||||||
|
// 添加账号索引参数
|
||||||
|
if (typeof params === 'object' && params !== null) {
|
||||||
|
params.account_index = accountIndex;
|
||||||
|
} else {
|
||||||
|
params = {
|
||||||
|
fid: params,
|
||||||
|
account_index: accountIndex
|
||||||
|
};
|
||||||
|
}
|
||||||
axios.get('/get_savepath_detail', {
|
axios.get('/get_savepath_detail', {
|
||||||
params: params
|
params: params
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
@ -4272,8 +4479,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存当前目录到localStorage
|
// 保存当前目录到localStorage(为每个账号单独保存)
|
||||||
localStorage.setItem('quarkAutoSave_fileManagerLastFolder', folderId);
|
localStorage.setItem(`quarkAutoSave_fileManagerLastFolder_${this.fileManager.selectedAccountIndex}`, folderId);
|
||||||
|
|
||||||
// 重置页码并加载新文件夹内容,不显示加载动画
|
// 重置页码并加载新文件夹内容,不显示加载动画
|
||||||
this.fileManager.currentPage = 1;
|
this.fileManager.currentPage = 1;
|
||||||
@ -4445,15 +4652,18 @@
|
|||||||
files: [{
|
files: [{
|
||||||
file_id: file.fid,
|
file_id: file.fid,
|
||||||
new_name: newName
|
new_name: newName
|
||||||
}]
|
}],
|
||||||
|
// 添加账号索引参数,使用文件整理页面选中的账号
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
this.showToast('重命名成功');
|
this.showToast('重命名成功');
|
||||||
// 更新本地文件列表中的文件名
|
// 刷新文件列表以确保缓存同步
|
||||||
const index = this.fileManager.fileList.findIndex(f => f.fid === file.fid);
|
this.refreshCurrentFolderCache();
|
||||||
if (index !== -1) {
|
// 如果命名预览模态框是打开的,也要刷新它
|
||||||
this.fileManager.fileList[index].file_name = newName;
|
if ($('#fileSelectModal').hasClass('show')) {
|
||||||
|
this.showFileManagerNamingPreview(this.fileManager.currentFolder);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert(response.data.message || '重命名失败');
|
alert(response.data.message || '重命名失败');
|
||||||
@ -4465,13 +4675,13 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
switchNamingMode() {
|
previewAndRename() {
|
||||||
// 不再切换命名模式,而是显示命名预览模态框
|
// 显示文件整理页面的命名预览模态框
|
||||||
this.showFileManagerNamingPreview();
|
this.showFileManagerNamingPreview();
|
||||||
},
|
},
|
||||||
|
|
||||||
showFileManagerNamingPreview(folderId) {
|
showFileManagerNamingPreview(folderId) {
|
||||||
// 使用文件选择模态框,但设置为预览模式
|
// 显示文件整理页面的命名预览模态框(区别于任务配置的命名预览)
|
||||||
this.fileSelect.selectShare = false;
|
this.fileSelect.selectShare = false;
|
||||||
this.fileSelect.selectDir = true;
|
this.fileSelect.selectDir = true;
|
||||||
this.fileSelect.previewRegex = true;
|
this.fileSelect.previewRegex = true;
|
||||||
@ -4510,7 +4720,9 @@
|
|||||||
include_folders: this.fileManager.include_folders,
|
include_folders: this.fileManager.include_folders,
|
||||||
filterwords: this.fileManager.filterwords,
|
filterwords: this.fileManager.filterwords,
|
||||||
// 添加页面大小参数,获取所有文件
|
// 添加页面大小参数,获取所有文件
|
||||||
page_size: 99999
|
page_size: 99999,
|
||||||
|
// 添加账号索引参数,使用文件整理页面选中的账号
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
@ -4528,7 +4740,11 @@
|
|||||||
page_size: 99999,
|
page_size: 99999,
|
||||||
page: 1,
|
page: 1,
|
||||||
// 同时添加文件夹包含参数
|
// 同时添加文件夹包含参数
|
||||||
include_folders: this.fileManager.include_folders
|
include_folders: this.fileManager.include_folders,
|
||||||
|
// 添加账号索引参数,使用文件整理页面选中的账号
|
||||||
|
account_index: this.fileManager.selectedAccountIndex,
|
||||||
|
// 强制刷新缓存
|
||||||
|
force_refresh: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(listResponse => {
|
.then(listResponse => {
|
||||||
@ -4599,85 +4815,8 @@
|
|||||||
this.modalLoading = false;
|
this.modalLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showBatchRenameModal() {
|
// showBatchRenameModal方法已删除,功能已整合到showFileManagerNamingPreview中
|
||||||
this.batchRename.loading = true;
|
// confirmBatchRename方法已删除,功能已整合到applyPreviewRename中
|
||||||
this.batchRename.results = [];
|
|
||||||
this.batchRename.errors = [];
|
|
||||||
|
|
||||||
// 设置命名模式
|
|
||||||
if (this.fileManager.use_sequence_naming) {
|
|
||||||
this.batchRename.namingMode = 'sequence';
|
|
||||||
} else if (this.fileManager.use_episode_naming) {
|
|
||||||
this.batchRename.namingMode = 'episode';
|
|
||||||
} else {
|
|
||||||
this.batchRename.namingMode = 'regex';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用后端API获取预览结果
|
|
||||||
const params = {
|
|
||||||
folder_id: this.fileManager.currentFolder,
|
|
||||||
pattern: this.fileManager.pattern,
|
|
||||||
replace: this.fileManager.replace,
|
|
||||||
naming_mode: this.batchRename.namingMode,
|
|
||||||
include_folders: this.fileManager.include_folders,
|
|
||||||
filterwords: this.fileManager.filterwords
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.get('/preview_rename', { params })
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.success) {
|
|
||||||
this.batchRename.files = response.data.data.map(file => ({
|
|
||||||
oldName: file.original_name,
|
|
||||||
newName: file.new_name,
|
|
||||||
fileId: file.file_id
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
alert(response.data.message || '预览重命名失败');
|
|
||||||
}
|
|
||||||
this.batchRename.loading = false;
|
|
||||||
$('#batchRenameModal').modal('show');
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('预览重命名失败:', error);
|
|
||||||
alert('预览重命名失败,请检查命名规则是否正确');
|
|
||||||
this.batchRename.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
confirmBatchRename() {
|
|
||||||
this.batchRename.loading = true;
|
|
||||||
|
|
||||||
// 发送批量重命名请求
|
|
||||||
const params = {
|
|
||||||
folder_id: this.fileManager.currentFolder,
|
|
||||||
pattern: this.fileManager.pattern,
|
|
||||||
replace: this.fileManager.replace,
|
|
||||||
naming_mode: this.batchRename.namingMode,
|
|
||||||
include_folders: this.fileManager.include_folders,
|
|
||||||
filterwords: this.fileManager.filterwords,
|
|
||||||
files: this.batchRename.files.filter(file => file.newName).map(file => ({
|
|
||||||
file_id: file.fileId,
|
|
||||||
new_name: file.newName
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post('/batch_rename', params)
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.success) {
|
|
||||||
this.showToast('批量重命名成功');
|
|
||||||
$('#batchRenameModal').modal('hide');
|
|
||||||
// 刷新文件列表
|
|
||||||
this.loadFileList(this.fileManager.currentFolder);
|
|
||||||
} else {
|
|
||||||
alert(response.data.message || '批量重命名失败');
|
|
||||||
}
|
|
||||||
this.batchRename.loading = false;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('批量重命名失败:', error);
|
|
||||||
alert('批量重命名失败');
|
|
||||||
this.batchRename.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteFile(file) {
|
deleteFile(file) {
|
||||||
if (confirm(`确定要删除${file.dir ? '文件夹' : '文件'} "${file.file_name}" 吗?`)) {
|
if (confirm(`确定要删除${file.dir ? '文件夹' : '文件'} "${file.file_name}" 吗?`)) {
|
||||||
// 获取当前路径作为save_path参数
|
// 获取当前路径作为save_path参数
|
||||||
@ -4690,17 +4829,18 @@
|
|||||||
fid: file.fid,
|
fid: file.fid,
|
||||||
file_name: file.file_name,
|
file_name: file.file_name,
|
||||||
delete_records: false,
|
delete_records: false,
|
||||||
save_path: save_path
|
save_path: save_path,
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.data.code === 0) {
|
if (response.data.code === 0) {
|
||||||
this.showToast('成功删除 1 个项目');
|
this.showToast('成功删除 1 个项目');
|
||||||
// 从列表中移除已删除的文件
|
// 刷新文件列表以确保缓存同步
|
||||||
this.fileManager.fileList = this.fileManager.fileList.filter(f => f.fid !== file.fid);
|
this.refreshCurrentFolderCache();
|
||||||
// 更新总数
|
// 如果命名预览模态框是打开的,也要刷新它
|
||||||
this.fileManager.total -= 1;
|
if ($('#fileSelectModal').hasClass('show')) {
|
||||||
// 从选中列表中移除
|
this.showFileManagerNamingPreview(this.fileManager.currentFolder);
|
||||||
this.fileManager.selectedFiles = this.fileManager.selectedFiles.filter(id => id !== file.fid);
|
}
|
||||||
} else {
|
} else {
|
||||||
alert(response.data.message || '删除失败');
|
alert(response.data.message || '删除失败');
|
||||||
}
|
}
|
||||||
@ -4720,7 +4860,8 @@
|
|||||||
sort_by: this.fileManager.sortBy,
|
sort_by: this.fileManager.sortBy,
|
||||||
order: this.fileManager.sortOrder,
|
order: this.fileManager.sortOrder,
|
||||||
page_size: this.fileManager.pageSize,
|
page_size: this.fileManager.pageSize,
|
||||||
page: this.fileManager.currentPage
|
page: this.fileManager.currentPage,
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
axios.get('/file_list', { params })
|
axios.get('/file_list', { params })
|
||||||
@ -4795,8 +4936,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存当前目录到localStorage
|
// 保存当前目录到localStorage(为每个账号单独保存)
|
||||||
localStorage.setItem('quarkAutoSave_fileManagerLastFolder', folderId);
|
localStorage.setItem(`quarkAutoSave_fileManagerLastFolder_${this.fileManager.selectedAccountIndex}`, folderId);
|
||||||
|
|
||||||
// 重置页码并加载新文件夹内容,不显示加载动画
|
// 重置页码并加载新文件夹内容,不显示加载动画
|
||||||
this.fileManager.currentPage = 1;
|
this.fileManager.currentPage = 1;
|
||||||
@ -4819,7 +4960,8 @@
|
|||||||
sort_by: this.fileManager.sortBy,
|
sort_by: this.fileManager.sortBy,
|
||||||
order: this.fileManager.sortOrder,
|
order: this.fileManager.sortOrder,
|
||||||
page_size: this.fileManager.pageSize,
|
page_size: this.fileManager.pageSize,
|
||||||
page: this.fileManager.currentPage
|
page: this.fileManager.currentPage,
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
axios.get('/file_list', { params })
|
axios.get('/file_list', { params })
|
||||||
@ -4841,6 +4983,55 @@
|
|||||||
console.error('获取文件列表失败:', error);
|
console.error('获取文件列表失败:', error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 添加带fallback机制的文件列表加载方法,用于账号切换
|
||||||
|
loadFileListWithFallback(folderId) {
|
||||||
|
this.fileManager.currentFolder = folderId || 'root';
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
folder_id: folderId || 'root',
|
||||||
|
sort_by: this.fileManager.sortBy,
|
||||||
|
order: this.fileManager.sortOrder,
|
||||||
|
page_size: this.fileManager.pageSize,
|
||||||
|
page: this.fileManager.currentPage,
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
axios.get('/file_list', { params })
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.success) {
|
||||||
|
this.fileManager.fileList = response.data.data.list;
|
||||||
|
this.fileManager.total = response.data.data.total;
|
||||||
|
this.fileManager.totalPages = Math.ceil(response.data.data.total / this.fileManager.pageSize);
|
||||||
|
this.fileManager.paths = response.data.data.paths || [];
|
||||||
|
this.fileManager.gotoPage = this.fileManager.currentPage;
|
||||||
|
|
||||||
|
// 检测当前的命名模式
|
||||||
|
this.detectFileManagerNamingMode();
|
||||||
|
} else {
|
||||||
|
// 如果获取文件列表失败,可能是目录在新账号中不存在
|
||||||
|
console.warn('当前目录在新账号中不存在,自动切换到根目录:', response.data.message);
|
||||||
|
this.fallbackToRoot();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('获取文件列表失败,自动切换到根目录:', error);
|
||||||
|
this.fallbackToRoot();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// fallback到根目录的方法
|
||||||
|
fallbackToRoot() {
|
||||||
|
this.fileManager.currentFolder = 'root';
|
||||||
|
this.fileManager.paths = [];
|
||||||
|
this.fileManager.currentPage = 1;
|
||||||
|
|
||||||
|
// 更新localStorage中的当前目录(为每个账号单独保存)
|
||||||
|
localStorage.setItem(`quarkAutoSave_fileManagerLastFolder_${this.fileManager.selectedAccountIndex}`, 'root');
|
||||||
|
|
||||||
|
// 重新加载根目录
|
||||||
|
this.loadFileListWithoutLoading('root');
|
||||||
|
},
|
||||||
getVisibleFolderPageNumbers() {
|
getVisibleFolderPageNumbers() {
|
||||||
const current = parseInt(this.fileManager.currentPage) || 1;
|
const current = parseInt(this.fileManager.currentPage) || 1;
|
||||||
const total = parseInt(this.fileManager.totalPages) || 1;
|
const total = parseInt(this.fileManager.totalPages) || 1;
|
||||||
@ -4876,47 +5067,7 @@
|
|||||||
|
|
||||||
return range;
|
return range;
|
||||||
},
|
},
|
||||||
cancelBatchRename() {
|
// cancelBatchRename和applyBatchRename方法已删除,功能已整合到fileSelectModal中
|
||||||
this.batchRename.loading = false;
|
|
||||||
this.batchRename.results = [];
|
|
||||||
this.batchRename.errors = [];
|
|
||||||
$('#batchRenameModal').modal('hide');
|
|
||||||
},
|
|
||||||
applyBatchRename() {
|
|
||||||
this.batchRename.loading = true;
|
|
||||||
|
|
||||||
// 发送批量重命名请求
|
|
||||||
const params = {
|
|
||||||
folder_id: this.fileManager.currentFolder,
|
|
||||||
pattern: this.fileManager.pattern,
|
|
||||||
replace: this.fileManager.replace,
|
|
||||||
naming_mode: this.batchRename.namingMode,
|
|
||||||
include_folders: this.fileManager.include_folders,
|
|
||||||
filterwords: this.fileManager.filterwords,
|
|
||||||
files: this.batchRename.files.filter(file => file.newName).map(file => ({
|
|
||||||
file_id: file.fileId,
|
|
||||||
new_name: file.newName
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post('/batch_rename', params)
|
|
||||||
.then(response => {
|
|
||||||
if (response.data.success) {
|
|
||||||
this.showToast('批量重命名成功');
|
|
||||||
$('#batchRenameModal').modal('hide');
|
|
||||||
// 刷新文件列表
|
|
||||||
this.loadFileList(this.fileManager.currentFolder);
|
|
||||||
} else {
|
|
||||||
alert(response.data.message || '批量重命名失败');
|
|
||||||
}
|
|
||||||
this.batchRename.loading = false;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('批量重命名失败:', error);
|
|
||||||
alert('批量重命名失败');
|
|
||||||
this.batchRename.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleFileManagerOutsideClick(event) {
|
handleFileManagerOutsideClick(event) {
|
||||||
// 如果当前不是文件整理页面或者没有选中的文件,则不处理
|
// 如果当前不是文件整理页面或者没有选中的文件,则不处理
|
||||||
if (this.activeTab !== 'filemanager' || this.fileManager.selectedFiles.length === 0) {
|
if (this.activeTab !== 'filemanager' || this.fileManager.selectedFiles.length === 0) {
|
||||||
@ -4973,7 +5124,8 @@
|
|||||||
fid: fid,
|
fid: fid,
|
||||||
file_name: fileName,
|
file_name: fileName,
|
||||||
delete_records: deleteRecords,
|
delete_records: deleteRecords,
|
||||||
save_path: save_path
|
save_path: save_path,
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
return { fid: fid, success: response.data.code === 0, deleted_records: response.data.deleted_records || 0 };
|
return { fid: fid, success: response.data.code === 0, deleted_records: response.data.deleted_records || 0 };
|
||||||
@ -4990,22 +5142,21 @@
|
|||||||
const successCount = results.filter(r => r.success).length;
|
const successCount = results.filter(r => r.success).length;
|
||||||
const failCount = results.length - successCount;
|
const failCount = results.length - successCount;
|
||||||
|
|
||||||
// 从文件列表中移除成功删除的文件
|
|
||||||
const successfullyDeletedFids = results.filter(r => r.success).map(r => r.fid);
|
|
||||||
this.fileManager.fileList = this.fileManager.fileList.filter(item => !successfullyDeletedFids.includes(item.fid));
|
|
||||||
|
|
||||||
// 更新总数
|
|
||||||
this.fileManager.total -= successCount;
|
|
||||||
|
|
||||||
// 清空选中文件列表
|
|
||||||
this.fileManager.selectedFiles = [];
|
|
||||||
|
|
||||||
// 显示结果
|
// 显示结果
|
||||||
if (failCount > 0) {
|
if (failCount > 0) {
|
||||||
alert(`成功删除 ${successCount} 个项目,${failCount} 个项目删除失败`);
|
alert(`成功删除 ${successCount} 个项目,${failCount} 个项目删除失败`);
|
||||||
} else {
|
} else {
|
||||||
this.showToast(`成功删除 ${successCount} 个项目`);
|
this.showToast(`成功删除 ${successCount} 个项目`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果有成功删除的文件,刷新文件列表以确保缓存同步
|
||||||
|
if (successCount > 0) {
|
||||||
|
this.refreshCurrentFolderCache();
|
||||||
|
// 如果命名预览模态框是打开的,也要刷新它
|
||||||
|
if ($('#fileSelectModal').hasClass('show')) {
|
||||||
|
this.showFileManagerNamingPreview(this.fileManager.currentFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -5056,10 +5207,16 @@
|
|||||||
old_name: f.file_name // 传递原文件名,便于撤销
|
old_name: f.file_name // 传递原文件名,便于撤销
|
||||||
}));
|
}));
|
||||||
const save_path = this.fileManager.currentFolder;
|
const save_path = this.fileManager.currentFolder;
|
||||||
const response = await axios.post('/batch_rename', { files, save_path });
|
const response = await axios.post('/batch_rename', {
|
||||||
|
files,
|
||||||
|
save_path,
|
||||||
|
// 添加账号索引参数,使用文件整理页面选中的账号
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
|
});
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
this.showToast(`成功重命名 ${response.data.success_count || files.length} 个项目`);
|
this.showToast(`成功重命名 ${response.data.success_count || files.length} 个项目`);
|
||||||
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
// 强制刷新文件列表缓存
|
||||||
|
this.refreshCurrentFolderCache();
|
||||||
$('#fileSelectModal').modal('hide');
|
$('#fileSelectModal').modal('hide');
|
||||||
this.fileSelect.canUndoRename = true; // 重命名后立即可撤销
|
this.fileSelect.canUndoRename = true; // 重命名后立即可撤销
|
||||||
} else {
|
} else {
|
||||||
@ -5075,11 +5232,16 @@
|
|||||||
this.modalLoading = true;
|
this.modalLoading = true;
|
||||||
try {
|
try {
|
||||||
const save_path = this.fileManager.currentFolder;
|
const save_path = this.fileManager.currentFolder;
|
||||||
const response = await axios.post('/undo_rename', { save_path });
|
const response = await axios.post('/undo_rename', {
|
||||||
|
save_path,
|
||||||
|
// 添加账号索引参数,使用文件整理页面选中的账号
|
||||||
|
account_index: this.fileManager.selectedAccountIndex
|
||||||
|
});
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
this.showToast(`成功撤销 ${response.data.success_count} 个项目重命名`);
|
this.showToast(`成功撤销 ${response.data.success_count} 个项目重命名`);
|
||||||
this.showFileManagerNamingPreview(save_path);
|
this.showFileManagerNamingPreview(save_path);
|
||||||
this.loadFileListWithoutLoading(this.fileManager.currentFolder);
|
// 强制刷新文件列表缓存
|
||||||
|
this.refreshCurrentFolderCache();
|
||||||
// 撤销后如无可撤销项再设为false(由showFileManagerNamingPreview刷新)
|
// 撤销后如无可撤销项再设为false(由showFileManagerNamingPreview刷新)
|
||||||
} else {
|
} else {
|
||||||
this.showToast(response.data.message || '撤销失败');
|
this.showToast(response.data.message || '撤销失败');
|
||||||
|
|||||||
@ -932,6 +932,9 @@ class Quark:
|
|||||||
def ls_dir(self, pdir_fid, **kwargs):
|
def ls_dir(self, pdir_fid, **kwargs):
|
||||||
file_list = []
|
file_list = []
|
||||||
page = 1
|
page = 1
|
||||||
|
# 优化:增加每页大小,减少API调用次数
|
||||||
|
page_size = kwargs.get("page_size", 200) # 从50增加到200
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
url = f"{self.BASE_URL}/1/clouddrive/file/sort"
|
url = f"{self.BASE_URL}/1/clouddrive/file/sort"
|
||||||
querystring = {
|
querystring = {
|
||||||
@ -940,7 +943,7 @@ class Quark:
|
|||||||
"uc_param_str": "",
|
"uc_param_str": "",
|
||||||
"pdir_fid": pdir_fid,
|
"pdir_fid": pdir_fid,
|
||||||
"_page": page,
|
"_page": page,
|
||||||
"_size": "50",
|
"_size": str(page_size),
|
||||||
"_fetch_total": "1",
|
"_fetch_total": "1",
|
||||||
"_fetch_sub_dirs": "0",
|
"_fetch_sub_dirs": "0",
|
||||||
"_sort": "file_type:asc,updated_at:desc",
|
"_sort": "file_type:asc,updated_at:desc",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user