Spaces:
Sleeping
Sleeping
Update templates/index.html
Browse files- templates/index.html +45 -14
templates/index.html
CHANGED
@@ -931,6 +931,29 @@
|
|
931 |
color: white;
|
932 |
border-color: transparent;
|
933 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
934 |
</style>
|
935 |
</head>
|
936 |
<body>
|
@@ -971,6 +994,11 @@
|
|
971 |
<div class="search-container">
|
972 |
<input type="text" class="search-box" placeholder="搜索文件...">
|
973 |
</div>
|
|
|
|
|
|
|
|
|
|
|
974 |
</header>
|
975 |
|
976 |
<!-- 主内容区 -->
|
@@ -1462,19 +1490,15 @@
|
|
1462 |
</div>
|
1463 |
</div>
|
1464 |
`;
|
1465 |
-
|
1466 |
uploadProgress.style.display = 'block';
|
1467 |
uploadProgress.appendChild(progressItem);
|
1468 |
-
|
1469 |
const progressFill = progressItem.querySelector('.progress-fill');
|
1470 |
const progressText = progressItem.querySelector('.progress-text');
|
1471 |
const speedElement = progressItem.querySelector('.speed');
|
1472 |
const sizeElement = progressItem.querySelector('.downloaded-size');
|
1473 |
const cancelButton = progressItem.querySelector('.cancel-download');
|
1474 |
-
|
1475 |
const controller = new AbortController();
|
1476 |
let isDownloadCancelled = false;
|
1477 |
-
|
1478 |
cancelButton.onclick = () => {
|
1479 |
controller.abort();
|
1480 |
isDownloadCancelled = true;
|
@@ -1483,13 +1507,10 @@
|
|
1483 |
uploadProgress.style.display = 'none';
|
1484 |
}
|
1485 |
};
|
1486 |
-
|
1487 |
const response = await fetch(`/api/files/download/${file.path}`, {
|
1488 |
signal: controller.signal
|
1489 |
});
|
1490 |
-
|
1491 |
if (!response.ok) throw new Error('Download failed');
|
1492 |
-
|
1493 |
const contentLength = response.headers.get('content-length');
|
1494 |
const total = parseInt(contentLength, 10);
|
1495 |
const reader = response.body.getReader();
|
@@ -1500,7 +1521,6 @@
|
|
1500 |
let currentSpeed = 0;
|
1501 |
let lastSpeedUpdate = Date.now();
|
1502 |
const chunks = [];
|
1503 |
-
|
1504 |
while (true) {
|
1505 |
const {done, value} = await reader.read();
|
1506 |
|
@@ -1532,7 +1552,6 @@
|
|
1532 |
|
1533 |
sizeElement.textContent = `${this.formatFileSize(receivedLength)} / ${this.formatFileSize(total)}`;
|
1534 |
}
|
1535 |
-
|
1536 |
if (!isDownloadCancelled) {
|
1537 |
const blob = new Blob(chunks);
|
1538 |
const url = URL.createObjectURL(blob);
|
@@ -1543,13 +1562,11 @@
|
|
1543 |
a.click();
|
1544 |
document.body.removeChild(a);
|
1545 |
URL.revokeObjectURL(url);
|
1546 |
-
|
1547 |
progressItem.remove();
|
1548 |
if (!uploadProgress.hasChildNodes()) {
|
1549 |
uploadProgress.style.display = 'none';
|
1550 |
}
|
1551 |
}
|
1552 |
-
|
1553 |
} catch (error) {
|
1554 |
const uploadProgress = document.querySelector('.upload-progress');
|
1555 |
if (error.name === 'AbortError') {
|
@@ -1864,15 +1881,16 @@
|
|
1864 |
|
1865 |
if (!response.ok) {
|
1866 |
const errorData = await response.json();
|
1867 |
-
throw new Error(errorData.
|
1868 |
}
|
1869 |
|
|
|
1870 |
await this.loadFiles();
|
1871 |
-
this.showMessage('
|
1872 |
|
1873 |
} catch (error) {
|
1874 |
console.error('Error deleting file:', error);
|
1875 |
-
this.showError(
|
1876 |
}
|
1877 |
}
|
1878 |
|
@@ -2082,6 +2100,19 @@
|
|
2082 |
}
|
2083 |
|
2084 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2085 |
// 初始化文件管理器
|
2086 |
new FileManager();
|
2087 |
</script>
|
|
|
931 |
color: white;
|
932 |
border-color: transparent;
|
933 |
}
|
934 |
+
.logout-btn {
|
935 |
+
padding: 8px 15px;
|
936 |
+
border: 1px solid var(--border-color);
|
937 |
+
border-radius: 8px;
|
938 |
+
background: var(--card-bg);
|
939 |
+
color: var(--text);
|
940 |
+
cursor: pointer;
|
941 |
+
transition: all 0.3s ease;
|
942 |
+
display: flex;
|
943 |
+
align-items: center;
|
944 |
+
gap: 8px;
|
945 |
+
margin-right: 10px;
|
946 |
+
margin-left: 10px;
|
947 |
+
}
|
948 |
+
.logout-btn:hover {
|
949 |
+
border-color: var(--primary-glow);
|
950 |
+
color: var(--primary-glow);
|
951 |
+
transform: translateY(-2px);
|
952 |
+
}
|
953 |
+
|
954 |
+
.logout-btn i {
|
955 |
+
font-size: 16px;
|
956 |
+
}
|
957 |
</style>
|
958 |
</head>
|
959 |
<body>
|
|
|
994 |
<div class="search-container">
|
995 |
<input type="text" class="search-box" placeholder="搜索文件...">
|
996 |
</div>
|
997 |
+
<!-- 添加退出登录按钮 -->
|
998 |
+
<button class="logout-btn" onclick="handleLogout()">
|
999 |
+
<i class="fas fa-sign-out-alt"></i>
|
1000 |
+
退出登录
|
1001 |
+
</button>
|
1002 |
</header>
|
1003 |
|
1004 |
<!-- 主内容区 -->
|
|
|
1490 |
</div>
|
1491 |
</div>
|
1492 |
`;
|
|
|
1493 |
uploadProgress.style.display = 'block';
|
1494 |
uploadProgress.appendChild(progressItem);
|
|
|
1495 |
const progressFill = progressItem.querySelector('.progress-fill');
|
1496 |
const progressText = progressItem.querySelector('.progress-text');
|
1497 |
const speedElement = progressItem.querySelector('.speed');
|
1498 |
const sizeElement = progressItem.querySelector('.downloaded-size');
|
1499 |
const cancelButton = progressItem.querySelector('.cancel-download');
|
|
|
1500 |
const controller = new AbortController();
|
1501 |
let isDownloadCancelled = false;
|
|
|
1502 |
cancelButton.onclick = () => {
|
1503 |
controller.abort();
|
1504 |
isDownloadCancelled = true;
|
|
|
1507 |
uploadProgress.style.display = 'none';
|
1508 |
}
|
1509 |
};
|
|
|
1510 |
const response = await fetch(`/api/files/download/${file.path}`, {
|
1511 |
signal: controller.signal
|
1512 |
});
|
|
|
1513 |
if (!response.ok) throw new Error('Download failed');
|
|
|
1514 |
const contentLength = response.headers.get('content-length');
|
1515 |
const total = parseInt(contentLength, 10);
|
1516 |
const reader = response.body.getReader();
|
|
|
1521 |
let currentSpeed = 0;
|
1522 |
let lastSpeedUpdate = Date.now();
|
1523 |
const chunks = [];
|
|
|
1524 |
while (true) {
|
1525 |
const {done, value} = await reader.read();
|
1526 |
|
|
|
1552 |
|
1553 |
sizeElement.textContent = `${this.formatFileSize(receivedLength)} / ${this.formatFileSize(total)}`;
|
1554 |
}
|
|
|
1555 |
if (!isDownloadCancelled) {
|
1556 |
const blob = new Blob(chunks);
|
1557 |
const url = URL.createObjectURL(blob);
|
|
|
1562 |
a.click();
|
1563 |
document.body.removeChild(a);
|
1564 |
URL.revokeObjectURL(url);
|
|
|
1565 |
progressItem.remove();
|
1566 |
if (!uploadProgress.hasChildNodes()) {
|
1567 |
uploadProgress.style.display = 'none';
|
1568 |
}
|
1569 |
}
|
|
|
1570 |
} catch (error) {
|
1571 |
const uploadProgress = document.querySelector('.upload-progress');
|
1572 |
if (error.name === 'AbortError') {
|
|
|
1881 |
|
1882 |
if (!response.ok) {
|
1883 |
const errorData = await response.json();
|
1884 |
+
throw new Error(errorData.error || '删除失败');
|
1885 |
}
|
1886 |
|
1887 |
+
// Only proceed with refresh and success message if deletion was successful
|
1888 |
await this.loadFiles();
|
1889 |
+
this.showMessage(`文件 "${file.path.split('/').pop()}" 已成功删除`);
|
1890 |
|
1891 |
} catch (error) {
|
1892 |
console.error('Error deleting file:', error);
|
1893 |
+
this.showError('删除文件失败');
|
1894 |
}
|
1895 |
}
|
1896 |
|
|
|
2100 |
}
|
2101 |
|
2102 |
}
|
2103 |
+
async function handleLogout() {
|
2104 |
+
try {
|
2105 |
+
const response = await fetch('/logout');
|
2106 |
+
if (response.ok) {
|
2107 |
+
window.location.href = '/login';
|
2108 |
+
} else {
|
2109 |
+
throw new Error('Logout failed');
|
2110 |
+
}
|
2111 |
+
} catch (error) {
|
2112 |
+
console.error('Error during logout:', error);
|
2113 |
+
alert('退出登录失败,请重试');
|
2114 |
+
}
|
2115 |
+
}
|
2116 |
// 初始化文件管理器
|
2117 |
new FileManager();
|
2118 |
</script>
|