Files
2026-09-16 14:07:40 +08:00

152 lines
3.9 KiB
PHP

<?php
require __DIR__ . '/auth.php';
require_login();
$uploadDir = __DIR__ . '/uploads';
$files = [];
if (is_dir($uploadDir)) {
foreach (scandir($uploadDir) as $name) {
if ($name === '.' || $name === '..') continue;
$path = $uploadDir . '/' . $name;
if (is_file($path)) {
$files[] = [
'name' => $name,
'size' => filesize($path),
'time' => filemtime($path),
];
}
}
}
usort($files, fn($a, $b) => $b['time'] <=> $a['time']);
function humanSize($bytes) {
$units = ['B', 'KB', 'MB', 'GB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>崩溃报告接收列表</title>
<style>
body {
font-family: -apple-system, "Segoe UI", "Microsoft YaHei", sans-serif;
max-width: 960px;
margin: 40px auto;
padding: 0 16px;
color: #222;
background: #f7f8fa;
}
.head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
h1 { font-size: 20px; margin: 0; }
.logout { font-size: 13px; color: #888; text-decoration: none; }
.logout:hover { color: #d33; }
.meta { color: #888; font-size: 13px; margin-bottom: 20px; }
table {
width: 100%;
border-collapse: collapse;
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0,0,0,.06);
}
th, td {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid #eee;
font-size: 14px;
}
th { background: #fafafa; font-weight: 600; color: #555; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: #f5f9ff; }
a { color: #1677ff; text-decoration: none; }
a:hover { text-decoration: underline; }
.empty {
padding: 40px;
text-align: center;
color: #999;
background: #fff;
border-radius: 8px;
}
.size { color: #666; white-space: nowrap; }
.time { color: #666; white-space: nowrap; }
button.del {
padding: 4px 10px;
font-size: 13px;
color: #d33;
background: #fff;
border: 1px solid #f0c0c0;
border-radius: 4px;
cursor: pointer;
}
button.del:hover { background: #fff0f0; }
</style>
</head>
<body>
<div class="head">
<h1>崩溃报告接收列表</h1>
<a class="logout" href="logout.php">退出登录</a>
</div>
<div class="meta">共 <?= count($files) ?> 个文件 · 目录:uploads/</div>
<?php if (empty($files)): ?>
<div class="empty">还没有收到任何文件</div>
<?php else: ?>
<table>
<thead>
<tr>
<th>文件名</th>
<th>大小</th>
<th>接收时间</th>
<th style="width:80px;">操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($files as $f): ?>
<tr>
<td><a href="uploads/<?= htmlspecialchars(rawurlencode($f['name'])) ?>" download><?= htmlspecialchars($f['name']) ?></a></td>
<td class="size"><?= humanSize($f['size']) ?></td>
<td class="time"><?= date('Y-m-d H:i:s', $f['time']) ?></td>
<td><button class="del" data-name="<?= htmlspecialchars($f['name']) ?>">删除</button></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<script>
document.querySelectorAll('.del').forEach(btn => {
btn.addEventListener('click', async () => {
const name = btn.dataset.name;
if (!confirm('确定删除 ' + name + ' 吗?')) return;
const fd = new FormData();
fd.append('name', name);
const res = await fetch('delete.php', { method: 'POST', body: fd });
const text = await res.text();
if (res.ok && text.trim() === 'OK') {
btn.closest('tr').remove();
} else {
alert('删除失败:' + text);
}
});
});
</script>
</body>
</html>