Files
Cloud-Index/static/js/selection.js
RhenCloud 730ee20048 refactor: 模块化前端代码 - 将 main.js 和 main.css 拆分为专用模块
- 移除 main.js 并替换为8个 JS 模块
- 移除 main.css 并替换为7个 CSS 模块
- 更新 base.html 以加载模块化文件
- 通过 index.css 保持完全向后兼容
- 改进代码组织、可维护性和可复用性
2025-11-15 12:45:19 +08:00

179 lines
4.8 KiB
JavaScript

/**
* 文件选择和批量操作相关功能
*/
/**
* 获取所有条目复选框
* @returns {NodeListOf<Element>}
*/
function getEntryCheckboxes() {
return document.querySelectorAll(".entry-checkbox");
}
/**
* 更新全选状态
*/
function updateSelectAllState() {
const master = document.getElementById("selectAll");
if (!master) {
return;
}
const checkboxes = Array.from(getEntryCheckboxes());
if (checkboxes.length === 0) {
master.checked = false;
master.indeterminate = false;
return;
}
const checkedCount = checkboxes.filter((checkbox) => checkbox.checked).length;
if (checkedCount === 0) {
master.checked = false;
master.indeterminate = false;
} else if (checkedCount === checkboxes.length) {
master.checked = true;
master.indeterminate = false;
} else {
master.checked = false;
master.indeterminate = true;
}
}
/**
* 切换全选
* @param {HTMLInputElement} master - 主复选框
*/
function toggleSelectAll(master) {
const checkboxes = getEntryCheckboxes();
const desiredState = Boolean(master.checked);
checkboxes.forEach((checkbox) => {
checkbox.checked = desiredState;
});
master.indeterminate = false;
updateSelectAllState();
}
/**
* 绑定复选框监听器
*/
function attachEntryCheckboxListeners() {
const master = document.getElementById("selectAll");
if (master && !master.dataset.listenerAttached) {
master.addEventListener("change", () => toggleSelectAll(master));
master.dataset.listenerAttached = "true";
}
getEntryCheckboxes().forEach((checkbox) => {
if (!checkbox.dataset.listenerAttached) {
checkbox.addEventListener("change", updateSelectAllState);
checkbox.dataset.listenerAttached = "true";
}
});
updateSelectAllState();
}
/**
* 删除选定的条目
*/
async function deleteSelectedEntries() {
const selected = Array.from(getEntryCheckboxes()).filter((checkbox) => checkbox.checked);
if (selected.length === 0) {
const statusDiv = updateStatus("✗ 请先选择要删除的项目", "error");
hideStatusLater(statusDiv);
return;
}
const directories = selected.filter((checkbox) => checkbox.dataset.type === "dir");
if (directories.length > 0) {
const statusDiv = updateStatus("✗ 暂不支持批量删除文件夹,请仅选择文件", "error");
hideStatusLater(statusDiv);
return;
}
const files = selected.map((checkbox) => checkbox.value);
const confirmMessage =
files.length === 1 ? `确定要删除 "${files[0]}" 吗?` : `确定要删除选中的 ${files.length} 个文件吗?`;
const confirmed = await showConfirm(confirmMessage, {
title: "批量删除",
confirmLabel: "删除",
});
if (!confirmed) {
return;
}
const deleteButton = document.getElementById("deleteTrigger");
if (deleteButton) {
deleteButton.disabled = true;
deleteButton.classList.add("is-disabled");
}
const inProgressStatus = updateStatus(`正在删除 ${files.length} 个文件...`, null);
const failures = [];
let successCount = 0;
for (const filePath of files) {
const result = await deleteFile(filePath, {
skipConfirm: true,
suppressReload: true,
suppressStatus: true,
});
if (result) {
successCount += 1;
} else {
failures.push(filePath);
}
}
if (deleteButton) {
deleteButton.disabled = false;
deleteButton.classList.remove("is-disabled");
}
if (inProgressStatus) {
inProgressStatus.style.display = "none";
}
if (failures.length === 0 && successCount > 0) {
const statusDiv = updateStatus(`✓ 已删除 ${successCount} 个文件`, "success");
hideStatusLater(statusDiv, 3000);
setTimeout(() => {
window.location.reload();
}, 1500);
return;
}
if (failures.length > 0) {
const message =
failures.length === files.length ? "✗ 删除失败,请稍后重试" : `删除部分文件失败:${failures.join(", ")}`;
const statusDiv = updateStatus(message, "error");
hideStatusLater(statusDiv, 4000);
if (successCount > 0) {
setTimeout(() => {
window.location.reload();
}, 1500);
}
}
}
/**
* 导出到全局作用域
*/
window.SelectionUtils = {
getEntryCheckboxes,
updateSelectAllState,
toggleSelectAll,
attachEntryCheckboxListeners,
deleteSelectedEntries,
};