初始化版本

This commit is contained in:
LL
2025-11-18 14:18:28 +08:00
commit 3c348195b7
23 changed files with 2837 additions and 0 deletions

96
upload_picture.php Normal file
View File

@@ -0,0 +1,96 @@
<?php
// 图片投稿页面:允许用户上传图片,保存到 pictures_pending 等待处理/审核
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>图片投稿</title>
<link rel="stylesheet" href="assets/style.css" />
</head>
<body>
<div class="page">
<header class="menu">
<div class="menu__logo">图片投稿</div>
<nav aria-label="主菜单">
<ul class="menu__nav">
<li><a class="menu__link" href="index.php">返回首页</a></li>
</ul>
</nav>
</header>
<main class="upload-container" aria-label="图片投稿表单">
<h1 class="upload-title">提交你的图片</h1>
<form id="form" class="upload-grid two" action="api/upload_picture.php" method="post" enctype="multipart/form-data">
<div class="card">
<div id="drop" class="dropzone" tabindex="0" aria-label="拖拽图片到此或点击选择">
<p style="margin:0 0 8px;">拖拽图片到此,或点击选择文件</p>
<input id="file" name="picture" type="file" accept="image/*" style="display:none;" />
<p class="tips">支持 jpg / jpeg / png / gif / webp</p>
</div>
<div class="field" style="margin-top:12px;">
<label>标题(可选)</label>
<input type="text" name="title" id="title" placeholder="给你的图片起个标题" />
</div>
</div>
<div class="card" aria-live="polite">
<img id="previewImg" class="preview-img" alt="预览图" />
<div class="meta" id="meta">未选择文件</div>
<div id="errors" class="errors"></div>
<div class="actions">
<button id="submitBtn" class="btn" type="submit">提交图片</button>
<a class="btn-ghost" href="review_pictures.php" title="管理员审核入口">管理员审核入口</a>
</div>
</div>
</form>
<p class="tips">说明提交后图片会保存到“待处理”目录管理员审核通过后将入库随后可在本地随机图片中显示。单张图片大小限制10MB。</p>
</main>
</div>
<script>
const drop = document.getElementById('drop');
const fileInput = document.getElementById('file');
const previewImg = document.getElementById('previewImg');
const metaBox = document.getElementById('meta');
const titleInput = document.getElementById('title');
const errors = document.getElementById('errors');
const submitBtn = document.getElementById('submitBtn');
const SIZE_LIMIT = 10 * 1024 * 1024; // 10MB
function setPreview(file) {
if (!file) { previewImg.src = ''; metaBox.textContent = '未选择文件'; return; }
const url = URL.createObjectURL(file);
previewImg.src = url;
const kb = (file.size/1024).toFixed(1);
metaBox.textContent = `文件:${file.name} 大小:${kb} KB 类型:${file.type || '未知'}`;
// 校验大小
if (file.size > SIZE_LIMIT) {
errors.textContent = '文件过大:超过 10MB 限制';
previewImg.removeAttribute('src');
metaBox.textContent = '未选择文件';
const dt = new DataTransfer();
document.getElementById('file').files = dt.files; // 清空选择
submitBtn.disabled = true;
return;
}
errors.textContent = '';
submitBtn.disabled = false;
if (!titleInput.value) {
const base = file.name.replace(/\.[A-Za-z0-9]+$/, '');
titleInput.value = base;
}
}
drop.addEventListener('click', () => fileInput.click());
drop.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); fileInput.click(); } });
drop.addEventListener('dragover', (e) => { e.preventDefault(); drop.classList.add('dragging'); });
drop.addEventListener('dragleave', () => drop.classList.remove('dragging'));
drop.addEventListener('drop', (e) => {
e.preventDefault(); drop.classList.remove('dragging');
const file = e.dataTransfer.files?.[0];
if (file) { fileInput.files = e.dataTransfer.files; setPreview(file); }
});
fileInput.addEventListener('change', () => { const f = fileInput.files?.[0]; setPreview(f); });
</script>
</body>
</html>