mirror of
https://github.com/Cp0204/quark-auto-save.git
synced 2026-01-12 15:20:44 +08:00
在文件整理页面增加了移动文件和新建文件夹功能
This commit is contained in:
parent
0f121a2a4a
commit
ffe6bfdbaa
108
app/run.py
108
app/run.py
@ -1021,6 +1021,114 @@ def delete_file():
|
||||
return jsonify(response)
|
||||
|
||||
|
||||
@app.route("/move_file", methods=["POST"])
|
||||
def move_file():
|
||||
if not is_login():
|
||||
return jsonify({"success": False, "message": "未登录"})
|
||||
|
||||
# 获取账号索引参数
|
||||
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)
|
||||
|
||||
# 获取参数
|
||||
file_ids = request.json.get("file_ids", [])
|
||||
target_folder_id = request.json.get("target_folder_id")
|
||||
|
||||
if not file_ids:
|
||||
return jsonify({"success": False, "message": "缺少文件ID列表"})
|
||||
|
||||
if not target_folder_id:
|
||||
return jsonify({"success": False, "message": "缺少目标文件夹ID"})
|
||||
|
||||
try:
|
||||
# 调用夸克网盘的移动API
|
||||
response = account.move(file_ids, target_folder_id)
|
||||
|
||||
if response["code"] == 0:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"成功移动 {len(file_ids)} 个文件",
|
||||
"moved_count": len(file_ids)
|
||||
})
|
||||
else:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"message": response.get("message", "移动失败")
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"message": f"移动文件时出错: {str(e)}"
|
||||
})
|
||||
|
||||
|
||||
@app.route("/create_folder", methods=["POST"])
|
||||
def create_folder():
|
||||
if not is_login():
|
||||
return jsonify({"success": False, "message": "未登录"})
|
||||
|
||||
# 获取请求参数
|
||||
data = request.json
|
||||
parent_folder_id = data.get("parent_folder_id")
|
||||
folder_name = data.get("folder_name", "新建文件夹")
|
||||
account_index = int(data.get("account_index", 0))
|
||||
|
||||
# 验证参数
|
||||
if not parent_folder_id:
|
||||
return jsonify({"success": False, "message": "缺少父目录ID"})
|
||||
|
||||
# 验证账号索引
|
||||
if account_index < 0 or account_index >= len(config_data["cookie"]):
|
||||
return jsonify({"success": False, "message": "账号索引无效"})
|
||||
|
||||
try:
|
||||
# 初始化夸克网盘客户端
|
||||
account = Quark(config_data["cookie"][account_index], account_index)
|
||||
|
||||
# 调用新建文件夹API
|
||||
response = account.mkdir_in_folder(parent_folder_id, folder_name)
|
||||
|
||||
if response.get("code") == 0:
|
||||
# 创建成功,返回新文件夹信息
|
||||
new_folder = response.get("data", {})
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": "文件夹创建成功",
|
||||
"data": {
|
||||
"fid": new_folder.get("fid"),
|
||||
"file_name": new_folder.get("file_name", folder_name),
|
||||
"dir": True,
|
||||
"size": 0,
|
||||
"updated_at": new_folder.get("updated_at"),
|
||||
"include_items": 0
|
||||
}
|
||||
})
|
||||
else:
|
||||
# 处理特定的错误信息
|
||||
error_message = response.get("message", "创建文件夹失败")
|
||||
|
||||
# 检查是否是同名文件夹冲突
|
||||
if "同名" in error_message or "已存在" in error_message or "重复" in error_message or "doloading" in error_message:
|
||||
error_message = "已存在同名文件夹,请修改名称后再试"
|
||||
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"message": error_message
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f">>> 创建文件夹时出错: {str(e)}")
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"message": f"创建文件夹时出错: {str(e)}"
|
||||
})
|
||||
|
||||
|
||||
# 添加任务接口
|
||||
@app.route("/api/add_task", methods=["POST"])
|
||||
def add_task():
|
||||
|
||||
@ -804,12 +804,16 @@ main div[v-if="activeTab === 'config'"] .row.title:first-child {
|
||||
/* 文件夹图标样式 */
|
||||
.bi-folder {
|
||||
color: var(--dark-text-color);
|
||||
font-size: 0.98rem;
|
||||
font-size: 1.01rem;
|
||||
position: relative;
|
||||
top: 0.5px;
|
||||
}
|
||||
|
||||
/* 重置文件夹图标样式 */
|
||||
.bi-folder-x {
|
||||
font-size: 0.98rem;
|
||||
font-size: 1.01rem;
|
||||
position: relative;
|
||||
top: 0.5px;
|
||||
}
|
||||
|
||||
/* 恢复图标样式 */
|
||||
@ -876,7 +880,9 @@ select.form-control {
|
||||
/* 链接图标样式 */
|
||||
.bi-link-45deg {
|
||||
color: var(--dark-text-color);
|
||||
font-size: 1.15rem;
|
||||
font-size: 1.2rem;
|
||||
position: relative;
|
||||
top: 0.5px;
|
||||
}
|
||||
|
||||
/* 谷歌图标样式 */
|
||||
@ -2118,7 +2124,7 @@ div.jsoneditor-tree button.jsoneditor-button:focus {
|
||||
|
||||
/* 侧边栏菜单项图标样式 */
|
||||
.sidebar .nav-link .bi-list-ul {
|
||||
font-size: 1.08rem;
|
||||
font-size: 1.09rem;
|
||||
position: relative;
|
||||
top: 0.5px; /* 向下微调 */
|
||||
}
|
||||
@ -4249,6 +4255,13 @@ select.task-filter-select,
|
||||
font-size: 1.17rem;
|
||||
}
|
||||
|
||||
/* 文件整理页面新建文件夹按钮图标大小 */
|
||||
.batch-rename-btn .bi-folder-plus {
|
||||
font-size: 1.01rem;
|
||||
position: relative;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
/* 确保文件整理页面的Plex和AList按钮样式与任务列表一致 */
|
||||
.batch-rename-btn.btn-outline-plex,
|
||||
.batch-rename-btn.btn-outline-alist {
|
||||
@ -4293,6 +4306,8 @@ select.task-filter-select,
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 文件表格中的展开按钮 */
|
||||
.expand-button {
|
||||
position: absolute;
|
||||
@ -4587,6 +4602,11 @@ table.selectable-files .rename-record-btn:hover {
|
||||
color: #0A42CC !important;
|
||||
}
|
||||
|
||||
/* 文件整理页面移动按钮悬停效果 */
|
||||
table.selectable-files .move-record-btn:hover {
|
||||
color: #0A42CC !important;
|
||||
}
|
||||
|
||||
/* 文件整理页面删除按钮悬停效果 */
|
||||
table.selectable-files .delete-record-btn:hover {
|
||||
color: #b02a37 !important;
|
||||
@ -4699,17 +4719,6 @@ table.selectable-records tr td {
|
||||
|
||||
|
||||
|
||||
/* 文件大小列中展开行的删除按钮特殊处理 */
|
||||
tr:has(.expanded-text) .file-size-cell .delete-record-btn,
|
||||
.selectable-records tbody tr:has(.expanded-text) .file-size-cell .delete-record-btn,
|
||||
#fileSelectModal .table tr:has([style*="white-space: normal"]) .file-size-cell .delete-record-btn,
|
||||
.selectable-files tr:has([style*="white-space: normal"]) .file-size-cell .delete-record-btn {
|
||||
top: 8px !important; /* 强制固定位置 */
|
||||
transform: none !important; /* 确保不使用任何转换 */
|
||||
left: 32px !important; /* 确保左边距固定,在重命名按钮右侧 */
|
||||
/* 不设置display,保持默认的隐藏状态 */
|
||||
}
|
||||
|
||||
/* 文件大小列中展开行的重命名按钮特殊处理 */
|
||||
tr:has(.expanded-text) .file-size-cell .rename-record-btn,
|
||||
.selectable-records tbody tr:has(.expanded-text) .file-size-cell .rename-record-btn,
|
||||
@ -4721,6 +4730,28 @@ tr:has(.expanded-text) .file-size-cell .rename-record-btn,
|
||||
/* 不设置display,保持默认的隐藏状态 */
|
||||
}
|
||||
|
||||
/* 文件大小列中展开行的移动按钮特殊处理 */
|
||||
tr:has(.expanded-text) .file-size-cell .move-record-btn,
|
||||
.selectable-records tbody tr:has(.expanded-text) .file-size-cell .move-record-btn,
|
||||
#fileSelectModal .table tr:has([style*="white-space: normal"]) .file-size-cell .move-record-btn,
|
||||
.selectable-files tr:has([style*="white-space: normal"]) .file-size-cell .move-record-btn {
|
||||
top: 8px !important; /* 强制固定位置 */
|
||||
transform: none !important; /* 确保不使用任何转换 */
|
||||
left: 32px !important; /* 确保左边距固定,在重命名按钮右侧 */
|
||||
/* 不设置display,保持默认的隐藏状态 */
|
||||
}
|
||||
|
||||
/* 文件大小列中展开行的删除按钮特殊处理 */
|
||||
tr:has(.expanded-text) .file-size-cell .delete-record-btn,
|
||||
.selectable-records tbody tr:has(.expanded-text) .file-size-cell .delete-record-btn,
|
||||
#fileSelectModal .table tr:has([style*="white-space: normal"]) .file-size-cell .delete-record-btn,
|
||||
.selectable-files tr:has([style*="white-space: normal"]) .file-size-cell .delete-record-btn {
|
||||
top: 8px !important; /* 强制固定位置 */
|
||||
transform: none !important; /* 确保不使用任何转换 */
|
||||
left: 59px !important; /* 确保左边距固定,在移动按钮右侧 */
|
||||
/* 不设置display,保持默认的隐藏状态 */
|
||||
}
|
||||
|
||||
/* 修复删除按钮位置问题 - 使用更强制的方法 */
|
||||
.delete-record-btn {
|
||||
color: #dc3545;
|
||||
@ -4808,11 +4839,34 @@ tr.selected-record .file-size-cell .delete-record-btn,
|
||||
|
||||
/* 文件整理页面的重命名文件按钮图标大小 */
|
||||
.selectable-files .rename-record-btn .bi-pencil {
|
||||
font-size: 0.98rem;
|
||||
font-size: 0.99rem;
|
||||
position: relative;
|
||||
left: 0.5px;
|
||||
}
|
||||
|
||||
/* 移动按钮样式 */
|
||||
.selectable-files .move-record-btn {
|
||||
color: var(--focus-border-color);
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
left: 32px; /* 在重命名按钮右侧,调整间距 */
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 文件整理页面的移动文件按钮图标大小 */
|
||||
.selectable-files .move-record-btn .bi-arrow-up-right-circle {
|
||||
font-size: 1.07rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 删除按钮样式调整 */
|
||||
.selectable-files .delete-record-btn {
|
||||
color: #dc3545;
|
||||
@ -4825,7 +4879,7 @@ tr.selected-record .file-size-cell .delete-record-btn,
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
right: auto; /* 移除右对齐 */
|
||||
left: 32px; /* 在重命名按钮右侧,调整间距 */
|
||||
left: 59px; /* 在移动按钮右侧,调整间距 */
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 14px;
|
||||
@ -4837,9 +4891,11 @@ tr.selected-record .file-size-cell .delete-record-btn,
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
/* 修复:确保在悬停和选中状态下重命名和删除按钮显示 */
|
||||
/* 修复:确保在悬停和选中状态下重命名、移动和删除按钮显示 */
|
||||
.selectable-files tr:hover .file-size-cell .rename-record-btn,
|
||||
.selectable-files tr.selected-file .file-size-cell .rename-record-btn,
|
||||
.selectable-files tr:hover .file-size-cell .move-record-btn,
|
||||
.selectable-files tr.selected-file .file-size-cell .move-record-btn,
|
||||
.selectable-files tr:hover .file-size-cell .delete-record-btn,
|
||||
.selectable-files tr.selected-file .file-size-cell .delete-record-btn {
|
||||
display: inline-flex !important;
|
||||
@ -4892,6 +4948,23 @@ body .selectable-files tr.selected-file .file-size-cell .rename-record-btn {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 确保文件整理页面的移动按钮在悬停和选中状态下始终可见 - 最高优先级 */
|
||||
body .selectable-files tbody tr:hover .file-size-cell .move-record-btn,
|
||||
body .selectable-files tr.selected-file .file-size-cell .move-record-btn {
|
||||
display: inline-flex !important;
|
||||
visibility: visible !important;
|
||||
position: absolute !important;
|
||||
top: 50% !important;
|
||||
transform: translateY(-50%) !important;
|
||||
left: 32px !important;
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
z-index: 5 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 确保文件整理页面的删除按钮在悬停和选中状态下始终可见 - 最高优先级 */
|
||||
body .selectable-files tbody tr:hover .file-size-cell .delete-record-btn,
|
||||
body .selectable-files tr.selected-file .file-size-cell .delete-record-btn {
|
||||
@ -4900,7 +4973,7 @@ body .selectable-files tr.selected-file .file-size-cell .delete-record-btn {
|
||||
position: absolute !important;
|
||||
top: 50% !important;
|
||||
transform: translateY(-50%) !important;
|
||||
left: 32px !important;
|
||||
left: 59px !important;
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
align-items: center !important;
|
||||
@ -4926,6 +4999,23 @@ body .selectable-files tr.selected-file:has([style*="white-space: normal"]) .fil
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 展开状态下的移动按钮悬停和选中状态 - 最高优先级 */
|
||||
body .selectable-files tbody tr:hover:has([style*="white-space: normal"]) .file-size-cell .move-record-btn,
|
||||
body .selectable-files tr.selected-file:has([style*="white-space: normal"]) .file-size-cell .move-record-btn {
|
||||
display: inline-flex !important;
|
||||
visibility: visible !important;
|
||||
position: absolute !important;
|
||||
top: 8px !important;
|
||||
transform: none !important;
|
||||
left: 32px !important;
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
z-index: 5 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 展开状态下的删除按钮悬停和选中状态 - 最高优先级 */
|
||||
body .selectable-files tbody tr:hover:has([style*="white-space: normal"]) .file-size-cell .delete-record-btn,
|
||||
body .selectable-files tr.selected-file:has([style*="white-space: normal"]) .file-size-cell .delete-record-btn {
|
||||
@ -4934,7 +5024,7 @@ body .selectable-files tr.selected-file:has([style*="white-space: normal"]) .fil
|
||||
position: absolute !important;
|
||||
top: 8px !important;
|
||||
transform: none !important;
|
||||
left: 32px !important;
|
||||
left: 59px !important;
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
align-items: center !important;
|
||||
@ -5197,6 +5287,18 @@ body .selectable-files tr.selected-file:has([style*="white-space: normal"]) .fil
|
||||
color: var(--dark-text-color) !important;
|
||||
}
|
||||
|
||||
/* 移动文件模态框的取消按钮样式 */
|
||||
#fileSelectModal[data-modal-type="move"] .modal-footer .btn-cancel {
|
||||
background-color: var(--button-gray-background-color) !important;
|
||||
border-color: var(--button-gray-background-color) !important;
|
||||
color: var(--dark-text-color) !important;
|
||||
}
|
||||
#fileSelectModal[data-modal-type="move"] .modal-footer .btn-cancel:hover {
|
||||
background-color: #e0e2e6 !important;
|
||||
border-color: #e0e2e6 !important;
|
||||
color: var(--dark-text-color) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.file-manager-rule-bar-responsive {
|
||||
display: flex;
|
||||
|
||||
@ -1052,6 +1052,9 @@
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-plex batch-rename-btn" v-if="formData.plugins && formData.plugins.plex && formData.plugins.plex.url && formData.plugins.plex.token && formData.plugins.plex.quark_root_path && formData.button_display.refresh_plex !== 'disabled'" @click="refreshFileManagerPlexLibrary" title="刷新Plex媒体库"><img src="./static/Plex.svg" class="plex-icon"></button>
|
||||
<button type="button" class="btn btn-outline-alist batch-rename-btn" v-if="formData.plugins && formData.plugins.alist && formData.plugins.alist.url && formData.plugins.alist.token && formData.plugins.alist.storage_id && formData.button_display.refresh_alist !== 'disabled'" @click="refreshFileManagerAlistDirectory" title="刷新AList目录"><img src="https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg" class="alist-icon"></button>
|
||||
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="createNewFolder" title="新建文件夹">
|
||||
<i class="bi bi-folder-plus"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="refreshCurrentFolderCache" title="刷新当前目录缓存">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
@ -1069,6 +1072,9 @@
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-plex batch-rename-btn" v-if="formData.plugins && formData.plugins.plex && formData.plugins.plex.url && formData.plugins.plex.token && formData.plugins.plex.quark_root_path && formData.button_display.refresh_plex !== 'disabled'" @click="refreshFileManagerPlexLibrary" title="刷新Plex媒体库"><img src="./static/Plex.svg" class="plex-icon"></button>
|
||||
<button type="button" class="btn btn-outline-alist batch-rename-btn" v-if="formData.plugins && formData.plugins.alist && formData.plugins.alist.url && formData.plugins.alist.token && formData.plugins.alist.storage_id && formData.button_display.refresh_alist !== 'disabled'" @click="refreshFileManagerAlistDirectory" title="刷新AList目录"><img src="https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg" class="alist-icon"></button>
|
||||
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="createNewFolder" title="新建文件夹">
|
||||
<i class="bi bi-folder-plus"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary batch-rename-btn" @click="refreshCurrentFolderCache" title="刷新当前目录缓存">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
@ -1207,6 +1213,9 @@
|
||||
<span class="rename-record-btn" @click.stop="startRenameFile(file)" title="重命名文件">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</span>
|
||||
<span class="move-record-btn" @click.stop="startMoveFile(file)" title="移动文件">
|
||||
<i class="bi bi-arrow-up-right-circle"></i>
|
||||
</span>
|
||||
<span class="delete-record-btn" @click.stop="deleteSelectedFilesForManager(file.fid, file.file_name, file.dir)" title="删除文件">
|
||||
<i class="bi bi-trash3"></i>
|
||||
</span>
|
||||
@ -1303,9 +1312,9 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" style="font-weight: 600; font-family: inherit; letter-spacing: normal;">
|
||||
<span v-if="fileSelect.previewRegex && fileSelect.index >= 0" style="font-weight: 600; font-family: inherit; letter-spacing: normal;">{{ formData.tasklist[fileSelect.index].use_sequence_naming ? '顺序命名预览' : (formData.tasklist[fileSelect.index].use_episode_naming ? '剧集命名预览' : '正则命名预览') }}</span>
|
||||
<span v-if="fileSelect.previewRegex && fileSelect.index >= 0 && formData.tasklist[fileSelect.index]" style="font-weight: 600; font-family: inherit; letter-spacing: normal;">{{ formData.tasklist[fileSelect.index].use_sequence_naming ? '顺序命名预览' : (formData.tasklist[fileSelect.index].use_episode_naming ? '剧集命名预览' : '正则命名预览') }}</span>
|
||||
<span v-else-if="fileSelect.previewRegex && fileSelect.index === -1" style="font-weight: 600; font-family: inherit; letter-spacing: normal;">{{ fileManager.use_sequence_naming ? '顺序命名预览' : (fileManager.use_episode_naming ? '剧集命名预览' : '正则命名预览') }}</span>
|
||||
<span v-else-if="fileSelect.selectDir" style="font-weight: 600; font-family: inherit; letter-spacing: normal;">选择{{fileSelect.selectShare ? '需转存的' : '保存到的'}}文件夹</span>
|
||||
<span v-else-if="fileSelect.selectDir" style="font-weight: 600; font-family: inherit; letter-spacing: normal;">选择{{fileSelect.moveMode ? '移动到的' : (fileSelect.selectShare ? '需转存的' : '保存到的')}}文件夹</span>
|
||||
<span v-else style="font-weight: 600; font-family: inherit; letter-spacing: normal;">选择起始文件</span>
|
||||
<div v-if="modalLoading" class="spinner-border spinner-border-sm m-1" role="status"></div>
|
||||
</h5>
|
||||
@ -1329,7 +1338,7 @@
|
||||
<!-- 文件列表 -->
|
||||
<div class="mb-3" v-if="fileSelect.previewRegex">
|
||||
<!-- 任务配置的命名预览 -->
|
||||
<div v-if="fileSelect.index >= 0">
|
||||
<div v-if="fileSelect.index >= 0 && formData.tasklist[fileSelect.index]">
|
||||
<div v-if="formData.tasklist[fileSelect.index].use_sequence_naming">
|
||||
<div style="margin-bottom: 1px; padding-left: 12px; display: flex; align-items: center;">
|
||||
<span style="font-weight: 600; font-family: inherit; letter-spacing: normal;">顺序命名表达式:</span><span class="badge badge-info" v-html="formData.tasklist[fileSelect.index].pattern"></span>
|
||||
@ -1386,7 +1395,7 @@
|
||||
<template v-if="!fileSelect.previewRegex">
|
||||
<th scope="col" class="col-size cursor-pointer" style="font-family: inherit; letter-spacing: normal;" @click="sortFileList('size')">大小 <i v-if="fileSelect.sortBy === 'size'" :class="fileSelect.sortOrder === 'asc' ? 'bi bi-arrow-up' : 'bi bi-arrow-down'"></i></th>
|
||||
<th scope="col" class="col-date cursor-pointer" style="font-family: inherit; letter-spacing: normal;" @click="sortFileList('updated_at')">修改日期 <i v-if="fileSelect.sortBy === 'updated_at'" :class="fileSelect.sortOrder === 'asc' ? 'bi bi-arrow-up' : 'bi bi-arrow-down'"></i></th>
|
||||
<th scope="col" class="col-action" v-if="!fileSelect.selectShare" style="font-family: inherit; letter-spacing: normal;">操作</th>
|
||||
<th scope="col" class="col-action" v-if="!fileSelect.selectShare && !fileSelect.moveMode" style="font-family: inherit; letter-spacing: normal;">操作</th>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -1441,7 +1450,7 @@
|
||||
<td class="col-size" v-if="file.dir" style="vertical-align: top;">{{ file.include_items }} 项</td>
|
||||
<td class="col-size" v-else style="vertical-align: top;">{{file.size | size}}</td>
|
||||
<td class="col-date" style="vertical-align: top;">{{file.updated_at | ts2date}}</td>
|
||||
<td class="col-action" v-if="!fileSelect.selectShare" style="vertical-align: top;">
|
||||
<td class="col-action" v-if="!fileSelect.selectShare && !fileSelect.moveMode" style="vertical-align: top;">
|
||||
<a @click.stop.prevent="deleteSelectedFiles(file.fid, file.file_name, file.dir)" style="cursor: pointer;">删除文件</a>
|
||||
<a @click.stop.prevent="deleteSelectedFiles(file.fid, file.file_name, file.dir, true)" style="cursor: pointer; margin-left: 10px;">删除文件和记录</a>
|
||||
</td>
|
||||
@ -1455,8 +1464,12 @@
|
||||
<div class="file-selection-info mr-auto" style="color: var(--dark-text-color); font-size: 0.875rem; line-height: 1.5;">
|
||||
共 {{ fileSelect.fileList.length }} 个项目<span v-if="fileSelect.selectedFiles.length > 0">,已选中 {{ fileSelect.selectedFiles.length }} 个项目</span>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary btn-sm" @click="selectCurrentFolder()">{{fileSelect.selectShare ? '转存当前文件夹' : '保存到当前文件夹'}}</button>
|
||||
<button type="button" class="btn btn-primary btn-sm" v-if="!fileSelect.selectShare" @click="selectCurrentFolder(true)">保存到当前位置的「<span class="badge badge-light" v-html="formData.tasklist[fileSelect.index].taskname"></span>」文件夹</button>
|
||||
<button type="button" class="btn btn-primary btn-cancel" @click="$('#fileSelectModal').modal('hide')" v-if="fileSelect.moveMode">取消</button>
|
||||
<button type="button" class="btn btn-primary btn-sm" @click="selectCurrentFolder()">
|
||||
<span v-if="fileSelect.moveMode">移动到当前文件夹</span>
|
||||
<span v-else>{{fileSelect.selectShare ? '转存当前文件夹' : '保存到当前文件夹'}}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary btn-sm" v-if="!fileSelect.selectShare && !fileSelect.moveMode && fileSelect.index !== null && fileSelect.index >= 0 && formData.tasklist[fileSelect.index]" @click="selectCurrentFolder(true)">保存到当前位置的「<span class="badge badge-light" v-html="formData.tasklist[fileSelect.index].taskname"></span>」文件夹</button>
|
||||
</div>
|
||||
<div class="modal-footer" v-if="fileSelect.previewRegex && fileSelect.index === -1">
|
||||
<div class="file-selection-info mr-auto" style="color: var(--dark-text-color); font-size: 0.875rem; line-height: 1.5;">
|
||||
@ -1572,7 +1585,9 @@
|
||||
sortOrder: "desc", // 默认排序顺序
|
||||
selectedFiles: [], // 存储选中的文件ID
|
||||
lastSelectedFileIndex: -1, // 记录最后选择的文件索引
|
||||
canUndoRename: false
|
||||
canUndoRename: false,
|
||||
moveMode: false, // 是否为移动文件模式
|
||||
moveFileIds: [] // 要移动的文件ID列表
|
||||
},
|
||||
historyParams: {
|
||||
sortBy: "transfer_time",
|
||||
@ -1823,6 +1838,9 @@
|
||||
$('#fileSelectModal').on('hidden.bs.modal', () => {
|
||||
this.fileSelect.selectedFiles = [];
|
||||
this.fileSelect.lastSelectedFileIndex = -1;
|
||||
// 重置移动模式相关参数
|
||||
this.fileSelect.moveMode = false;
|
||||
this.fileSelect.moveFileIds = [];
|
||||
});
|
||||
|
||||
// 检查本地存储中的标签页状态
|
||||
@ -1883,6 +1901,9 @@
|
||||
$('#fileSelectModal').on('hidden.bs.modal', () => {
|
||||
this.fileSelect.selectedFiles = [];
|
||||
this.fileSelect.lastSelectedFileIndex = -1;
|
||||
// 重置移动模式相关参数
|
||||
this.fileSelect.moveMode = false;
|
||||
this.fileSelect.moveFileIds = [];
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
||||
@ -2061,9 +2082,19 @@
|
||||
// 重置页码并切换到新账号的最后访问目录
|
||||
this.fileManager.currentPage = 1;
|
||||
this.loadFileListWithFallback(newAccountLastFolder);
|
||||
|
||||
// 如果移动文件模态框正在显示,需要重新加载目录
|
||||
if ($('#fileSelectModal').hasClass('show')) {
|
||||
const modalType = document.getElementById('fileSelectModal').getAttribute('data-modal-type');
|
||||
if (modalType === 'move') {
|
||||
// 重置路径并重新加载根目录
|
||||
this.fileSelect.paths = [];
|
||||
this.getSavepathDetail(0);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
refreshCurrentFolderCache() {
|
||||
refreshCurrentFolderCache(retryCount = 0) {
|
||||
// 刷新当前目录的缓存,强制重新请求最新的文件列表
|
||||
// 调用后端接口,添加强制刷新参数
|
||||
const params = {
|
||||
@ -2073,7 +2104,8 @@
|
||||
page_size: this.fileManager.pageSize,
|
||||
page: this.fileManager.currentPage,
|
||||
account_index: this.fileManager.selectedAccountIndex,
|
||||
force_refresh: true // 强制刷新参数
|
||||
force_refresh: true, // 强制刷新参数
|
||||
timestamp: Date.now() // 添加时间戳避免缓存
|
||||
};
|
||||
|
||||
axios.get('/file_list', { params })
|
||||
@ -2085,16 +2117,163 @@
|
||||
this.fileManager.paths = response.data.data.paths || [];
|
||||
this.fileManager.gotoPage = this.fileManager.currentPage;
|
||||
// 移除成功通知
|
||||
} else {
|
||||
this.showToast('刷新失败:' + response.data.message);
|
||||
}
|
||||
|
||||
// 检测当前的命名模式
|
||||
this.detectFileManagerNamingMode();
|
||||
// 检测当前的命名模式
|
||||
this.detectFileManagerNamingMode();
|
||||
} else {
|
||||
// 如果刷新失败且重试次数少于2次,则重试
|
||||
if (retryCount < 2) {
|
||||
setTimeout(() => {
|
||||
this.refreshCurrentFolderCache(retryCount + 1);
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showToast('刷新失败:' + response.data.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('刷新缓存失败:', error);
|
||||
this.showToast('刷新缓存失败,请稍后重试');
|
||||
// 如果网络错误且重试次数少于2次,则重试
|
||||
if (retryCount < 2) {
|
||||
setTimeout(() => {
|
||||
this.refreshCurrentFolderCache(retryCount + 1);
|
||||
}, 1000);
|
||||
} else {
|
||||
this.showToast('刷新缓存失败,请稍后重试');
|
||||
}
|
||||
});
|
||||
},
|
||||
// 获取指定文件夹的上级目录ID
|
||||
getParentFolderId(folderId) {
|
||||
// 如果是根目录,没有上级目录
|
||||
if (folderId === 'root' || folderId === '0') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果是当前目录(源目录),从fileManager.paths中获取上级目录
|
||||
if (folderId === this.fileManager.currentFolder || folderId === (this.fileManager.currentFolder || "0")) {
|
||||
if (this.fileManager.paths.length === 0) {
|
||||
// 当前目录是根目录的直接子目录,上级是根目录
|
||||
return 'root';
|
||||
} else {
|
||||
// 当前目录的上级是paths中的最后一个目录
|
||||
return this.fileManager.paths[this.fileManager.paths.length - 1].fid;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是目标目录,从fileSelect.paths中获取上级目录
|
||||
if (this.fileSelect.paths && this.fileSelect.paths.length > 0) {
|
||||
// 目标目录就是fileSelect.paths的最后一个目录,其上级目录是倒数第二个
|
||||
if (this.fileSelect.paths.length === 1) {
|
||||
// 目标目录是根目录的直接子目录
|
||||
return 'root';
|
||||
} else {
|
||||
// 目标目录的上级是paths中的倒数第二个目录
|
||||
return this.fileSelect.paths[this.fileSelect.paths.length - 2].fid;
|
||||
}
|
||||
} else {
|
||||
// 如果fileSelect.paths为空,说明目标目录是根目录,没有上级
|
||||
return null;
|
||||
}
|
||||
},
|
||||
// 刷新指定文件夹的缓存
|
||||
refreshFolderCache(folderId) {
|
||||
// 刷新指定目录的缓存,强制重新请求最新的文件列表
|
||||
// 调用后端接口,添加强制刷新参数
|
||||
const params = {
|
||||
folder_id: folderId || 'root',
|
||||
sort_by: this.fileManager.sortBy,
|
||||
order: this.fileManager.sortOrder,
|
||||
page_size: this.fileManager.pageSize,
|
||||
page: 1, // 使用第一页来刷新缓存
|
||||
account_index: this.fileManager.selectedAccountIndex,
|
||||
force_refresh: true // 强制刷新参数
|
||||
};
|
||||
|
||||
axios.get('/file_list', { params })
|
||||
.then(response => {
|
||||
// 如果刷新的是当前显示的文件夹,则更新显示
|
||||
if (folderId === this.fileManager.currentFolder) {
|
||||
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 {
|
||||
this.showToast('刷新失败:' + response.data.message);
|
||||
}
|
||||
}
|
||||
// 如果不是当前文件夹,只是刷新缓存,不更新显示
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('刷新文件夹缓存失败:', error);
|
||||
// 只有在刷新当前文件夹时才显示错误提示
|
||||
if (folderId === this.fileManager.currentFolder) {
|
||||
this.showToast('刷新缓存失败,请稍后重试');
|
||||
}
|
||||
});
|
||||
},
|
||||
// 新建文件夹
|
||||
createNewFolder() {
|
||||
// 检查是否有文件正在编辑状态
|
||||
const editingFile = this.fileManager.fileList.find(file => file._editing);
|
||||
if (editingFile) {
|
||||
// 如果有其他文件正在编辑,先保存编辑状态
|
||||
this.saveRenameFile(editingFile);
|
||||
return;
|
||||
}
|
||||
|
||||
// 生成带时间戳的文件夹名称
|
||||
const timestamp = new Date().toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
}).replace(/[\/\s:]/g, '');
|
||||
const folderName = `新建文件夹 ${timestamp}`;
|
||||
|
||||
// 调用后端API创建文件夹
|
||||
axios.post('/create_folder', {
|
||||
parent_folder_id: this.fileManager.currentFolder || '0',
|
||||
folder_name: folderName,
|
||||
account_index: this.fileManager.selectedAccountIndex
|
||||
})
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
// 创建成功,将新文件夹添加到文件列表
|
||||
const newFolder = response.data.data;
|
||||
|
||||
// 设置编辑状态
|
||||
this.$set(newFolder, '_editing', true);
|
||||
this.$set(newFolder, '_editingName', newFolder.file_name);
|
||||
|
||||
// 将新文件夹添加到列表开头(文件夹通常显示在前面)
|
||||
this.fileManager.fileList.unshift(newFolder);
|
||||
this.fileManager.total += 1;
|
||||
|
||||
// 下一个tick后聚焦输入框并全选文本
|
||||
this.$nextTick(() => {
|
||||
const input = this.$refs['renameInput_' + newFolder.fid];
|
||||
if (input) {
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
});
|
||||
|
||||
this.showToast('文件夹创建成功');
|
||||
} else {
|
||||
this.showToast(response.data.message || '创建文件夹失败');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('创建文件夹失败:', error);
|
||||
this.showToast('创建文件夹失败');
|
||||
});
|
||||
},
|
||||
// 添加一个检查分享链接状态的方法
|
||||
@ -3115,9 +3294,9 @@
|
||||
|
||||
// 根据模态框类型决定使用哪个账号
|
||||
// 任务配置相关的模态框始终使用主账号(索引0)
|
||||
// 文件整理页面的预览模态框使用选中的账号
|
||||
// 文件整理页面的预览模态框和移动文件模态框使用选中的账号
|
||||
const modalType = document.getElementById('fileSelectModal').getAttribute('data-modal-type');
|
||||
const accountIndex = (modalType === 'preview-filemanager') ? this.fileManager.selectedAccountIndex : 0;
|
||||
const accountIndex = (modalType === 'preview-filemanager' || modalType === 'move') ? this.fileManager.selectedAccountIndex : 0;
|
||||
|
||||
// 添加账号索引参数
|
||||
if (typeof params === 'object' && params !== null) {
|
||||
@ -3180,21 +3359,43 @@
|
||||
},
|
||||
getShareDetail(retryCount = 0, maxRetries = 1) {
|
||||
this.modalLoading = true;
|
||||
|
||||
// 检查index是否有效,如果无效则使用默认值
|
||||
let regexConfig = {};
|
||||
if (this.fileSelect.index !== null && this.fileSelect.index >= 0 && this.formData.tasklist[this.fileSelect.index]) {
|
||||
const task = this.formData.tasklist[this.fileSelect.index];
|
||||
regexConfig = {
|
||||
pattern: task.pattern,
|
||||
replace: task.replace,
|
||||
taskname: task.taskname,
|
||||
filterwords: task.filterwords,
|
||||
magic_regex: this.formData.magic_regex,
|
||||
use_sequence_naming: task.use_sequence_naming,
|
||||
sequence_naming: task.sequence_naming,
|
||||
use_episode_naming: task.use_episode_naming,
|
||||
episode_naming: task.episode_naming,
|
||||
episode_patterns: this.formData.episode_patterns
|
||||
};
|
||||
} else {
|
||||
// 使用默认配置
|
||||
regexConfig = {
|
||||
pattern: '',
|
||||
replace: '',
|
||||
taskname: '',
|
||||
filterwords: '',
|
||||
magic_regex: this.formData.magic_regex,
|
||||
use_sequence_naming: false,
|
||||
sequence_naming: '',
|
||||
use_episode_naming: false,
|
||||
episode_naming: '',
|
||||
episode_patterns: this.formData.episode_patterns
|
||||
};
|
||||
}
|
||||
|
||||
axios.post('/get_share_detail', {
|
||||
shareurl: this.fileSelect.shareurl,
|
||||
stoken: this.fileSelect.stoken,
|
||||
regex: {
|
||||
pattern: this.formData.tasklist[this.fileSelect.index].pattern,
|
||||
replace: this.formData.tasklist[this.fileSelect.index].replace,
|
||||
taskname: this.formData.tasklist[this.fileSelect.index].taskname,
|
||||
filterwords: this.formData.tasklist[this.fileSelect.index].filterwords,
|
||||
magic_regex: this.formData.magic_regex,
|
||||
use_sequence_naming: this.formData.tasklist[this.fileSelect.index].use_sequence_naming,
|
||||
sequence_naming: this.formData.tasklist[this.fileSelect.index].sequence_naming,
|
||||
use_episode_naming: this.formData.tasklist[this.fileSelect.index].use_episode_naming,
|
||||
episode_naming: this.formData.tasklist[this.fileSelect.index].episode_naming,
|
||||
episode_patterns: this.formData.episode_patterns
|
||||
}
|
||||
regex: regexConfig
|
||||
}).then(response => {
|
||||
if (response.data.success) {
|
||||
this.fileSelect.fileList = response.data.data.list;
|
||||
@ -3324,24 +3525,122 @@
|
||||
}
|
||||
},
|
||||
selectCurrentFolder(addTaskname = false) {
|
||||
if (this.fileSelect.selectShare) {
|
||||
this.formData.tasklist[this.fileSelect.index].shareurl_ban = undefined;
|
||||
// 如果是分享文件夹且文件列表为空,则设置shareurl_ban
|
||||
if (!this.fileSelect.fileList || this.fileSelect.fileList.length === 0) {
|
||||
this.$set(this.formData.tasklist[this.fileSelect.index], "shareurl_ban", "该分享已被删除,无法访问");
|
||||
if (this.fileSelect.moveMode) {
|
||||
// 移动文件模式
|
||||
this.moveFilesToCurrentFolder();
|
||||
} else if (this.fileSelect.selectShare) {
|
||||
// 检查index是否有效
|
||||
if (this.fileSelect.index !== null && this.fileSelect.index >= 0 && this.formData.tasklist[this.fileSelect.index]) {
|
||||
this.formData.tasklist[this.fileSelect.index].shareurl_ban = undefined;
|
||||
// 如果是分享文件夹且文件列表为空,则设置shareurl_ban
|
||||
if (!this.fileSelect.fileList || this.fileSelect.fileList.length === 0) {
|
||||
this.$set(this.formData.tasklist[this.fileSelect.index], "shareurl_ban", "该分享已被删除,无法访问");
|
||||
}
|
||||
this.formData.tasklist[this.fileSelect.index].shareurl = this.fileSelect.shareurl;
|
||||
}
|
||||
this.formData.tasklist[this.fileSelect.index].shareurl = this.fileSelect.shareurl;
|
||||
} else {
|
||||
// 去掉前导斜杠,避免双斜杠问题
|
||||
this.formData.tasklist[this.fileSelect.index].savepath = this.fileSelect.paths.map(item => item.name).join("/");
|
||||
if (addTaskname) {
|
||||
this.formData.tasklist[this.fileSelect.index].savepath += "/" + this.formData.tasklist[this.fileSelect.index].taskname
|
||||
// 检查index是否有效
|
||||
if (this.fileSelect.index !== null && this.fileSelect.index >= 0 && this.formData.tasklist[this.fileSelect.index]) {
|
||||
// 去掉前导斜杠,避免双斜杠问题
|
||||
this.formData.tasklist[this.fileSelect.index].savepath = this.fileSelect.paths.map(item => item.name).join("/");
|
||||
if (addTaskname) {
|
||||
this.formData.tasklist[this.fileSelect.index].savepath += "/" + this.formData.tasklist[this.fileSelect.index].taskname
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#fileSelectModal').modal('hide')
|
||||
if (!this.fileSelect.moveMode) {
|
||||
$('#fileSelectModal').modal('hide')
|
||||
}
|
||||
},
|
||||
// 移动文件到当前文件夹
|
||||
moveFilesToCurrentFolder() {
|
||||
if (!this.fileSelect.moveFileIds || this.fileSelect.moveFileIds.length === 0) {
|
||||
alert('没有选择要移动的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取目标文件夹ID
|
||||
const targetFolderId = this.fileSelect.paths.length > 0
|
||||
? this.fileSelect.paths[this.fileSelect.paths.length - 1].fid
|
||||
: "0";
|
||||
|
||||
// 记录源目录ID(文件原本所在的目录)
|
||||
const sourceFolderId = this.fileManager.currentFolder || "0";
|
||||
|
||||
const fileCount = this.fileSelect.moveFileIds.length;
|
||||
const confirmMessage = fileCount === 1
|
||||
? '确定要移动此文件吗?'
|
||||
: `确定要移动选中的 ${fileCount} 个文件吗?`;
|
||||
|
||||
if (!confirm(confirmMessage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用移动文件API
|
||||
axios.post('/move_file', {
|
||||
file_ids: this.fileSelect.moveFileIds,
|
||||
target_folder_id: targetFolderId,
|
||||
account_index: this.fileManager.selectedAccountIndex
|
||||
})
|
||||
.then(response => {
|
||||
if (response.data.success) {
|
||||
this.showToast(`成功移动 ${response.data.moved_count} 个文件`);
|
||||
|
||||
// 关闭模态框
|
||||
$('#fileSelectModal').modal('hide');
|
||||
|
||||
// 重置移动模式相关参数
|
||||
this.fileSelect.moveMode = false;
|
||||
this.fileSelect.moveFileIds = [];
|
||||
this.fileSelect.index = null; // 重置index避免后续访问undefined
|
||||
|
||||
// 清空选中的文件
|
||||
this.fileManager.selectedFiles = [];
|
||||
|
||||
// 延迟刷新以确保后端处理完成
|
||||
setTimeout(() => {
|
||||
// 刷新当前页面显示(源目录)
|
||||
this.refreshCurrentFolderCache();
|
||||
|
||||
// 如果目标目录不同于源目录,也刷新目标目录的缓存
|
||||
if (targetFolderId !== sourceFolderId) {
|
||||
this.refreshFolderCache(targetFolderId); // 刷新目标目录缓存
|
||||
}
|
||||
|
||||
// 刷新源目录的上级目录(更新源文件夹的项目数量)
|
||||
const sourceParentFolderId = this.getParentFolderId(sourceFolderId);
|
||||
if (sourceParentFolderId !== null) {
|
||||
this.refreshFolderCache(sourceParentFolderId);
|
||||
}
|
||||
|
||||
// 刷新目标目录的上级目录(更新目标文件夹的项目数量)
|
||||
if (targetFolderId !== sourceFolderId) {
|
||||
const targetParentFolderId = this.getParentFolderId(targetFolderId);
|
||||
if (targetParentFolderId !== null && targetParentFolderId !== sourceParentFolderId) {
|
||||
this.refreshFolderCache(targetParentFolderId);
|
||||
}
|
||||
}
|
||||
}, 500); // 延迟500ms确保后端处理完成
|
||||
} else {
|
||||
const errorMessage = response.data.message || '移动失败';
|
||||
// 对于"不能移动至相同目录"错误使用Toast通知
|
||||
if (errorMessage.includes('不能移动至相同目录')) {
|
||||
this.showToast('不能移动至相同目录');
|
||||
} else {
|
||||
this.showToast(errorMessage);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('移动文件失败:', error);
|
||||
this.showToast('移动文件失败');
|
||||
});
|
||||
},
|
||||
selectStartFid(fid) {
|
||||
Vue.set(this.formData.tasklist[this.fileSelect.index], 'startfid', fid);
|
||||
// 检查index是否有效
|
||||
if (this.fileSelect.index !== null && this.fileSelect.index >= 0 && this.formData.tasklist[this.fileSelect.index]) {
|
||||
Vue.set(this.formData.tasklist[this.fileSelect.index], 'startfid', fid);
|
||||
}
|
||||
$('#fileSelectModal').modal('hide')
|
||||
},
|
||||
getShareurl(shareurl, path = {}) {
|
||||
@ -5031,6 +5330,39 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
// 开始移动文件
|
||||
startMoveFile(file) {
|
||||
// 如果是文件夹,不允许移动
|
||||
if (file.dir) {
|
||||
this.showToast('暂不支持移动文件夹');
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置移动模式相关参数
|
||||
this.fileSelect.moveMode = true;
|
||||
this.fileSelect.moveFileIds = this.fileManager.selectedFiles.length > 0 && this.fileManager.selectedFiles.includes(file.fid)
|
||||
? this.fileManager.selectedFiles
|
||||
: [file.fid];
|
||||
this.fileSelect.selectShare = false;
|
||||
this.fileSelect.selectDir = true;
|
||||
this.fileSelect.previewRegex = false;
|
||||
this.fileSelect.error = undefined;
|
||||
this.fileSelect.fileList = [];
|
||||
this.fileSelect.paths = [];
|
||||
this.fileSelect.index = -1;
|
||||
|
||||
// 重置排序状态为默认值 - 选择移动目标文件夹模态框默认修改时间倒序
|
||||
this.fileSelect.sortBy = "updated_at";
|
||||
this.fileSelect.sortOrder = "desc";
|
||||
|
||||
// 设置模态框类型为move(移动目标文件夹)
|
||||
document.getElementById('fileSelectModal').setAttribute('data-modal-type', 'move');
|
||||
|
||||
$('#fileSelectModal').modal('show');
|
||||
|
||||
// 加载根目录
|
||||
this.getSavepathDetail(0);
|
||||
},
|
||||
// 保存重命名
|
||||
saveRenameFile(file) {
|
||||
if (!file._editing) return;
|
||||
@ -5534,6 +5866,9 @@
|
||||
$('#fileSelectModal').on('hidden.bs.modal', () => {
|
||||
this.fileSelect.selectedFiles = [];
|
||||
this.fileSelect.lastSelectedFileIndex = -1;
|
||||
// 重置移动模式相关参数
|
||||
this.fileSelect.moveMode = false;
|
||||
this.fileSelect.moveFileIds = [];
|
||||
});
|
||||
|
||||
// 检查本地存储中的标签页状态
|
||||
@ -5591,6 +5926,9 @@
|
||||
$('#fileSelectModal').on('hidden.bs.modal', () => {
|
||||
this.fileSelect.selectedFiles = [];
|
||||
this.fileSelect.lastSelectedFileIndex = -1;
|
||||
// 重置移动模式相关参数
|
||||
this.fileSelect.moveMode = false;
|
||||
this.fileSelect.moveFileIds = [];
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
||||
|
||||
@ -1121,6 +1121,21 @@ class Quark:
|
||||
).json()
|
||||
return response
|
||||
|
||||
def mkdir_in_folder(self, parent_fid, folder_name):
|
||||
"""在指定父目录下创建新文件夹"""
|
||||
url = f"{self.BASE_URL}/1/clouddrive/file"
|
||||
querystring = {"pr": "ucpro", "fr": "pc", "uc_param_str": ""}
|
||||
payload = {
|
||||
"pdir_fid": parent_fid,
|
||||
"file_name": folder_name,
|
||||
"dir_path": "",
|
||||
"dir_init_lock": False,
|
||||
}
|
||||
response = self._send_request(
|
||||
"POST", url, json=payload, params=querystring
|
||||
).json()
|
||||
return response
|
||||
|
||||
def rename(self, fid, file_name):
|
||||
url = f"{self.BASE_URL}/1/clouddrive/file/rename"
|
||||
querystring = {"pr": "ucpro", "fr": "pc", "uc_param_str": ""}
|
||||
@ -1139,6 +1154,21 @@ class Quark:
|
||||
).json()
|
||||
return response
|
||||
|
||||
def move(self, filelist, to_pdir_fid):
|
||||
"""移动文件到指定目录"""
|
||||
url = f"{self.BASE_URL}/1/clouddrive/file/move"
|
||||
querystring = {"pr": "ucpro", "fr": "pc", "uc_param_str": ""}
|
||||
payload = {
|
||||
"action_type": 2,
|
||||
"filelist": filelist,
|
||||
"to_pdir_fid": to_pdir_fid,
|
||||
"exclude_fids": []
|
||||
}
|
||||
response = self._send_request(
|
||||
"POST", url, json=payload, params=querystring
|
||||
).json()
|
||||
return response
|
||||
|
||||
def recycle_list(self, page=1, size=30):
|
||||
url = f"{self.BASE_URL}/1/clouddrive/file/recycle/list"
|
||||
querystring = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user